mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
feat: nuxt bridge (#459)
This commit is contained in:
parent
de57626a7a
commit
44458fcbbb
14
.github/workflows/ci.yml
vendored
14
.github/workflows/ci.yml
vendored
@ -57,7 +57,7 @@ jobs:
|
|||||||
- name: Test (presets)
|
- name: Test (presets)
|
||||||
run: yarn test:presets
|
run: yarn test:presets
|
||||||
|
|
||||||
test-compat:
|
test-bridge:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
@ -73,24 +73,24 @@ jobs:
|
|||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
cache-dependency-path: |
|
cache-dependency-path: |
|
||||||
yarn.lock
|
yarn.lock
|
||||||
test/fixtures/compat/yarn.lock
|
test/fixtures/bridge/yarn.lock
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn --immutable
|
run: yarn --immutable
|
||||||
|
|
||||||
- name: Install dependencies (compat fixture)
|
- name: Install dependencies (bridge fixture)
|
||||||
run: yarn --immutable && cd test/fixtures/compat && yarn --immutable
|
run: yarn --immutable && cd test/fixtures/bridge && yarn --immutable
|
||||||
|
|
||||||
- name: Stub
|
- name: Stub
|
||||||
run: yarn stub
|
run: yarn stub
|
||||||
|
|
||||||
- name: Test (presets compat)
|
- name: Test (presets bridge)
|
||||||
run: yarn test:compat
|
run: yarn test:bridge
|
||||||
|
|
||||||
build-release:
|
build-release:
|
||||||
needs:
|
needs:
|
||||||
- test
|
- test
|
||||||
- test-compat
|
- test-bridge
|
||||||
- lint
|
- lint
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
Getting started with Nuxt3 is straightforward.
|
Getting started with Nuxt3 is straightforward.
|
||||||
|
|
||||||
|
💡 Do you want to experience and prepare your project for Nuxt 3 without breaking changes? Check out [Nuxt Bridge](/bridge/intro) page!
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
Before installing Nuxt, you'll need to have a local development environment.
|
Before installing Nuxt, you'll need to have a local development environment.
|
||||||
|
@ -9,8 +9,6 @@ Nuxt3 is powered by a new server engine, code-named Nitro. It has:
|
|||||||
- Hybrid mode for static + serverless sites
|
- Hybrid mode for static + serverless sites
|
||||||
- A development mode with hot module reloading
|
- A development mode with hot module reloading
|
||||||
|
|
||||||
In addition it is backwards compatible with Nuxt2 via [a compatibility module](/server/compat).
|
|
||||||
|
|
||||||
## API Layer
|
## API Layer
|
||||||
|
|
||||||
Server [API endpoints](/server/api) and [Middleware](/server/middleware) are added by Nitro that internally uses [h3](https://github.com/unjs/h3).
|
Server [API endpoints](/server/api) and [Middleware](/server/middleware) are added by Nitro that internally uses [h3](https://github.com/unjs/h3).
|
||||||
|
81
docs/content/7.bridge/1.intro.md
Normal file
81
docs/content/7.bridge/1.intro.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# Nuxt Bridge
|
||||||
|
|
||||||
|
> ⚠️ This section is work-in-progress and can change. Please check this page regularly.
|
||||||
|
|
||||||
|
Nuxt3 brings a brand-new experience for developing Vue applications.
|
||||||
|
|
||||||
|
To make this happen, we've rewritten most parts of nuxt codebase and are using the latest tooling such as Webpack5, vite, vue3 and native ESM.
|
||||||
|
And we've also rethought how nuxt rendering works by introducing the `@nuxt/nitro` project.
|
||||||
|
|
||||||
|
Our goal is a smooth transition path from legacy stack to new one, reducing breaking changes as much as possible.
|
||||||
|
|
||||||
|
To make this happen, we considered backward- and forward-compatibility and most layers (such as modules and plugins). Nonetheless, this is in-progress and a bumpy road.
|
||||||
|
|
||||||
|
In the meantime, you can make sure your project is almost ready for nuxt3 and have latest DX experience, without major rewrites and risk of breaking changes by adding a simple module.
|
||||||
|
|
||||||
|
👉 Please see [Migration Guide](./migration) for more details how you can migrate your nuxt 2 project or module to bridge level.
|
||||||
|
|
||||||
|
## Nuxt 2 vs Nuxt Bridge vs Nuxt 3
|
||||||
|
|
||||||
|
In the table below, there is a quick comparation between 3 versions of nuxt:
|
||||||
|
|
||||||
|
Feature / Version | Nuxt 2 | Nuxt Bridge | Nuxt 3
|
||||||
|
-----------------------|-----------------|------------------|---------
|
||||||
|
Stability | 😸 Stable | 😺 Semi Stable | 🙀 Unstable
|
||||||
|
Performance | 👎 Slower | 👍 Enhanced | 🔥 Fastest
|
||||||
|
Nitro Engine | ❌ | ✅ | ✅
|
||||||
|
ESM support | 🌙 Partial | 👍 Better | ✅
|
||||||
|
Typescript | ☑️ Opt-in | 🚧 Faster | ✅
|
||||||
|
Composition API | 📖 Community | 🚧 Nuxt3 API | ✅
|
||||||
|
Components Auto Import | ✅ | ✅ | ✅
|
||||||
|
Auto Imports | ❌ | 🚧 | ✅
|
||||||
|
Webpack | 4 | 5 | 5
|
||||||
|
Vite | ⚠️ Partial | 🚧 Partial | 🚧 Experimental
|
||||||
|
Nuxi CLI | ❌ Old | ✅ | ✅
|
||||||
|
|
||||||
|
## Nuxt 3 vs Nuxt 2
|
||||||
|
|
||||||
|
The good news is that most features from Nitro Engine and the new CLI, like `api` routes, will be supported when you use `@nuxt/bridge`.
|
||||||
|
|
||||||
|
Some features have been dropped from nuxt2, some still need to be implemented for nuxt3 and some are new in nuxt3.
|
||||||
|
Biggest changes with nuxt3 other than the ones covered by bridge, are `vue2` to `vue3`, webpack5 and Core rewrite with new templating engine.
|
||||||
|
|
||||||
|
At the moment, there is no Nuxt 2 to Nuxt 3 migration guide nor is recommanded to do it due to potentially more changes coming.
|
||||||
|
We are working to provide a stable migration guide and tooling to make it as smooth as possible.
|
||||||
|
|
||||||
|
In table below there is an overall feature comparation table (might be incomplete or outdated):
|
||||||
|
|
||||||
|
|
||||||
|
Feature / Version | Nuxt 2 | Nuxt 3 | Changes required
|
||||||
|
--------------------------|---------|----------|------------------
|
||||||
|
Vue Version | 2 | 3 | Yes
|
||||||
|
`app.vue` | ❌ | ✅ | -
|
||||||
|
Assets | ✅ | ✅ | No
|
||||||
|
Components | ✅ | ✅ | No
|
||||||
|
Layouts | ✅ | ✅ | Yes
|
||||||
|
Error Pages | ✅ | 🚧 | Yes
|
||||||
|
Pages | ✅ | ✅ | Yes
|
||||||
|
Pages: Dynamic Params | ✅ | ✅ | Yes
|
||||||
|
Pages: _.vue | ✅ | ✅ | No
|
||||||
|
Plugins | ✅ | ✅ | Yes (compatible by default)
|
||||||
|
Store | ✅ | 🚧 | Yes
|
||||||
|
Transitions | ✅ | 🚧 | ?
|
||||||
|
Suspense | ❌ | ✅ | -
|
||||||
|
Options API: `asyncData` | ✅ | 🚧 | ?
|
||||||
|
Options API: `fetch` | ✅ | 🚧 | ?
|
||||||
|
|
||||||
|
|
||||||
|
### Nuxt Module Compatibility
|
||||||
|
|
||||||
|
- All Nuxt 2 modules should be forward compatible with Nuxt 3 as long as they migrate to bridge (see [migration](./migration)) or if they are already following guidelines
|
||||||
|
- All (upcoming) modules made with `@nuxt/kit` should be backward compatible with nuxt2 projects (even without bridge) as long as they are not depending on a nuxt3/bridge-only feature
|
||||||
|
|
||||||
|
### Nuxt Plugin Compatibility
|
||||||
|
|
||||||
|
- Most nuxt2 plugins should be forward compatible with nuxt3 with a magical compat layer we inject
|
||||||
|
- Nuxt3 plugins are **not** backward compatible with nuxt2
|
||||||
|
|
||||||
|
### Vue compatibility
|
||||||
|
|
||||||
|
For plugins and composition API and components, it needs exclusive vue2 or vue3 support from plugins.
|
||||||
|
By using [vue-demi](https://github.com/vueuse/vue-demi) they should be compatible with both nuxt2 and nuxt3.
|
@ -1,31 +0,0 @@
|
|||||||
# Nitro
|
|
||||||
|
|
||||||
> It is possible to use the Nuxt3 rendering engine (Nitro) with Nuxt2 via a compatibility module.
|
|
||||||
|
|
||||||
1. Install `@nuxt/nitro` as a devDependency:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn add --dev @nuxt/nitro
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Add `@nuxt/nitro/compat` to `buildModules` inside `nuxt.config`:
|
|
||||||
|
|
||||||
```ts [nuxt.config.js]
|
|
||||||
export default {
|
|
||||||
buildModules: [
|
|
||||||
'@nuxt/nitro/compat'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
1. If you have selected `target: 'static'` in your `nuxt.config`, update the `build` script in package.json to be `nuxt generate`:
|
|
||||||
|
|
||||||
```json [package.json]
|
|
||||||
{
|
|
||||||
"scripts": {
|
|
||||||
"build": "nuxt generate"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Now, when you build your project, Nitro will generate an optimized server bundle for fast, next-generation edge rendering.
|
|
130
docs/content/7.bridge/2.migration.md
Normal file
130
docs/content/7.bridge/2.migration.md
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# Bridge Migration
|
||||||
|
|
||||||
|
> ⚠️ This section is work-in-progress and can change. Please regulary check this page.
|
||||||
|
|
||||||
|
## ... I have a nuxt2 project
|
||||||
|
|
||||||
|
Migration to nuxt-bridge, should be almost straight forward!
|
||||||
|
|
||||||
|
**Why migrate:**
|
||||||
|
|
||||||
|
- It is risk-free! You can roll back by just commenting out one line in config
|
||||||
|
- Makes your project almost ready for nuxt3 migration
|
||||||
|
- Enjoy new DX improvements without major rewrites for vue3
|
||||||
|
- Use nitro engine for platform agnostic and optimized deployments
|
||||||
|
- Help us stabilize nuxt3 and discover flows
|
||||||
|
- Bridge is more stable than nuxt3 at the moment for migration
|
||||||
|
|
||||||
|
### **Step 1:** Ensure using latest version of nuxt
|
||||||
|
|
||||||
|
Remove package lock file (`package-lock.json` and `yarn.lock`) and update to latest version of nuxt2 ([releases](https://github.com/nuxt/nuxt.js/releases)) or use `nuxt-edge` for latest updates and fixes.
|
||||||
|
|
||||||
|
### **Step 2:** Install bridge module
|
||||||
|
|
||||||
|
Install `@nuxt/bridge` as a devDependency:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using npm
|
||||||
|
npm install -D @nuxt/bridge
|
||||||
|
|
||||||
|
# Using yarn
|
||||||
|
yarn add --dev @nuxt/bridge
|
||||||
|
```
|
||||||
|
|
||||||
|
Add `@nuxt/bridge` to `buildModules` inside `nuxt.config`:
|
||||||
|
|
||||||
|
```ts [nuxt.config.js]
|
||||||
|
export default {
|
||||||
|
buildModules: [
|
||||||
|
'@nuxt/bridge'
|
||||||
|
],
|
||||||
|
bridge: {
|
||||||
|
nitro: true,
|
||||||
|
// vite: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have a project with `target: 'static'`, update "build" script to use `nuxt generate`
|
||||||
|
|
||||||
|
```json [package.json]
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"build": "nuxt generate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Step 3:** Avoid CommonJS synax
|
||||||
|
|
||||||
|
See [Migrating from CommonJS](#step-2-avoid-commonjs-syntax) from module author section.
|
||||||
|
We need same steps for `plugins`, `store`, `pages`, `serverMiddleware` and `nuxt.config.js`.
|
||||||
|
|
||||||
|
### **Step 4:** Ensure everything goes well
|
||||||
|
|
||||||
|
Try with both `nuxt dev`, `nuxt build` and `nuxt start` if everything goes as expected
|
||||||
|
If there is an issue, please report it to us or to relavant module repository.
|
||||||
|
|
||||||
|
If you cannot take the risk of using experimental code, you can comment out the module and regularly check back to ensure your project stays ready for nuxt3 compatibily.
|
||||||
|
|
||||||
|
### 🥳 Enjoy new possibilities!
|
||||||
|
|
||||||
|
Everything goes well? Congratulations! You are welcome to enjoy new features from nuxt3 without full migration. See table in intro section for more.
|
||||||
|
|
||||||
|
## ... I am a module author
|
||||||
|
|
||||||
|
When users of nuxt3 use your module, a compatible module container layer from `@nuxt/kit` is automatically injected
|
||||||
|
so as long as your code is following below guidelines, it should continue working as is.
|
||||||
|
|
||||||
|
### **Step 1:** Test it with `@nuxt/bridge`:
|
||||||
|
|
||||||
|
Migrating to `@nuxt/bridge` is the first and most important step for supporting nuxt3.
|
||||||
|
|
||||||
|
If you have a fixture in your module, add `@nuxt/bridge` package to its config (same steps as previous section for nuxt2 projects)
|
||||||
|
|
||||||
|
### **Step 2:** Avoid CommonJS syntax:
|
||||||
|
|
||||||
|
Nuxt natively supports Typescript and ECMAScript Modules. In every file make sure to:
|
||||||
|
|
||||||
|
- Change `require('lib')` to `import lib from 'lib'` or `await import('lib').then(e => e.default || e)`
|
||||||
|
- Change `module.exports` to `export default` or `export const`
|
||||||
|
- Avoid usage of `__dirname` and `__filename` as much as possible
|
||||||
|
|
||||||
|
### **Step 3:** Ensure plugins have default export
|
||||||
|
|
||||||
|
If you inject a nuxt plugin that does not have `export default` (such as global Vue plugins), ensure you add `export default {}` to the end of it
|
||||||
|
|
||||||
|
### **Step 4:** Avoid runtime modules
|
||||||
|
|
||||||
|
With nuxt3 and nitro project, we started to rethink how the nuxt build process should work and modules hooking into the Nuxt runtime is now considered an anti-pattern and will not work wtih nuxt3.
|
||||||
|
|
||||||
|
Your module should work fine by adding only to `buildModules[]` (instead of `modules[]`):
|
||||||
|
|
||||||
|
- Avoid updating `process.env` within nuxt module and reading by a nuxt plugin. Use `runtimeConfig` instead
|
||||||
|
- (*) Avoid depending on runtime hooks like `vue-renderer:*` for production
|
||||||
|
- (*) Avoid adding `serverMiddleware` by importing them inside module. Add them by referencing to file path so that they are independent of module context
|
||||||
|
|
||||||
|
(*) Unless it is for `nuxt dev` purpose only and guarded with `if (nuxt.options.dev) { }`.
|
||||||
|
|
||||||
|
### **Step 5**: Add module meta
|
||||||
|
|
||||||
|
Ensure your module is exporting meta object.
|
||||||
|
|
||||||
|
[TODO]
|
||||||
|
|
||||||
|
### **Step 6:** Migrate to typescript (optional)
|
||||||
|
|
||||||
|
While it is not essential, most of nuxt ecosystem is shifitng to use Typescript, it is highly recommended to consider migration.
|
||||||
|
|
||||||
|
**Tip:** You can start migration by simply renaming `.js` files, to `.ts`. Typescript is designed to be progressive!
|
||||||
|
|
||||||
|
**Tip:** You can use typescript syntax for nuxt 2/3 modules and plugins without any extra dependencies.
|
||||||
|
|
||||||
|
### 🛣️ Next Steps
|
||||||
|
|
||||||
|
While we are evolving nuxt3 and modules, you are welcome to share any ideas in Discussions section.
|
||||||
|
|
||||||
|
A brand new exprience of defining nuxt modules is coming with `@nuxt/kit` project but it is still not ready so it is advised only to try it and not release to stable versions of your module.
|
||||||
|
|
||||||
|
Please regularly check this section for latest updates.
|
||||||
|
|
@ -19,7 +19,7 @@
|
|||||||
"lint": "eslint --ext .vue,.ts,.js .",
|
"lint": "eslint --ext .vue,.ts,.js .",
|
||||||
"test": "yarn lint && yarn test:presets",
|
"test": "yarn lint && yarn test:presets",
|
||||||
"test:presets": "mocha test/presets/*.mjs",
|
"test:presets": "mocha test/presets/*.mjs",
|
||||||
"test:compat": "TEST_COMPAT=1 yarn test:presets",
|
"test:bridge": "TEST_BRIDGE=1 yarn test:presets",
|
||||||
"test:unit": "mocha -r jiti/register packages/**/test/*.test.*",
|
"test:unit": "mocha -r jiti/register packages/**/test/*.test.*",
|
||||||
"version": "yarn && git add yarn.lock"
|
"version": "yarn && git add yarn.lock"
|
||||||
},
|
},
|
||||||
|
7
packages/bridge/build.config.ts
Normal file
7
packages/bridge/build.config.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { defineBuildConfig } from 'unbuild'
|
||||||
|
|
||||||
|
export default defineBuildConfig({
|
||||||
|
entries: [
|
||||||
|
'src/module'
|
||||||
|
]
|
||||||
|
})
|
32
packages/bridge/package.json
Normal file
32
packages/bridge/package.json
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "@nuxt/bridge",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"repository": "nuxt/framework",
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "./dist/module.js",
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"prepack": "unbuild"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@nuxt/kit": "^0.10.0",
|
||||||
|
"@nuxt/nitro": "^0.10.0",
|
||||||
|
"@nuxt/postcss8": "^1.1.3",
|
||||||
|
"@vue/composition-api": "^1.1.3",
|
||||||
|
"fs-extra": "^10.0.0",
|
||||||
|
"node-fetch": "^2.6.1",
|
||||||
|
"nuxi": "^0.10.0",
|
||||||
|
"nuxt-swc": "^0.0.3",
|
||||||
|
"nuxt-vite": "^0.2.1",
|
||||||
|
"ufo": "^0.7.9",
|
||||||
|
"upath": "^2.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/fs-extra": "^9.0.12",
|
||||||
|
"@types/node-fetch": "^2.5.12",
|
||||||
|
"unbuild": "^0.4.2"
|
||||||
|
}
|
||||||
|
}
|
39
packages/bridge/src/app.ts
Normal file
39
packages/bridge/src/app.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { useNuxt, resolveModule } from '@nuxt/kit'
|
||||||
|
import { resolve } from 'upath'
|
||||||
|
import { distDir } from './dirs'
|
||||||
|
|
||||||
|
export function setupAppBridge () {
|
||||||
|
const nuxt = useNuxt()
|
||||||
|
|
||||||
|
// Setup aliases
|
||||||
|
nuxt.options.alias['#app'] = resolve(distDir, 'runtime/index.mjs')
|
||||||
|
nuxt.options.alias['#build'] = nuxt.options.buildDir
|
||||||
|
|
||||||
|
// Resolve to same vue2 path
|
||||||
|
nuxt.options.alias.vue = nuxt.options.alias.vue || resolveModule('vue/dist/vue.runtime.esm.js', { paths: nuxt.options.modulesDir })
|
||||||
|
|
||||||
|
// Transpile runtime/
|
||||||
|
nuxt.options.build.transpile.push(resolve(distDir, 'runtime'))
|
||||||
|
|
||||||
|
// Add composition-api support
|
||||||
|
// nuxt.options.alias['@vue/composition-api'] = require.resolve('@vue/composition-api/dist/vue-composition-api.mjs')
|
||||||
|
// const capiPluginPath = resolve(distDir, 'runtime/capi.plugin.mjs')
|
||||||
|
// addPluginTemplate({ filename: 'capi.plugin.mjs', src: capiPluginPath })
|
||||||
|
// nuxt.hook('webpack:config', (configs) => {
|
||||||
|
// // @ts-ignore
|
||||||
|
// configs.forEach(config => config.entry.app.unshift(capiPluginPath))
|
||||||
|
// })
|
||||||
|
|
||||||
|
// Fix wp4 esm
|
||||||
|
nuxt.hook('webpack:config', (configs) => {
|
||||||
|
for (const config of configs.filter(c => c.module)) {
|
||||||
|
for (const rule of config.module.rules) {
|
||||||
|
// @ts-ignore
|
||||||
|
if (rule.test instanceof RegExp && rule.test.test('index.mjs')) {
|
||||||
|
// @ts-ignore
|
||||||
|
rule.type = 'javascript/auto'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
import { Compiler } from 'webpack'
|
import { Compiler } from 'webpack'
|
||||||
import Template from 'webpack/lib/Template'
|
import Template from 'webpack/lib/Template'
|
||||||
|
|
||||||
export default class AsyncLoadingPlugin {
|
export class AsyncLoadingPlugin {
|
||||||
apply (compiler: Compiler) {
|
apply (compiler: Compiler) {
|
||||||
compiler.hooks.compilation.tap('AsyncLoading', (compilation) => {
|
compiler.hooks.compilation.tap('AsyncLoading', (compilation) => {
|
||||||
const mainTemplate = compilation.mainTemplate
|
const mainTemplate = compilation.mainTemplate
|
4
packages/bridge/src/dirs.ts
Normal file
4
packages/bridge/src/dirs.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { resolve } from 'upath'
|
||||||
|
|
||||||
|
export const distDir = __dirname
|
||||||
|
export const pkgDir = resolve(distDir, '..')
|
33
packages/bridge/src/module.ts
Normal file
33
packages/bridge/src/module.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { defineNuxtModule, installModule } from '@nuxt/kit'
|
||||||
|
import { setupNitroBridge } from './nitro'
|
||||||
|
import { setupAppBridge } from './app'
|
||||||
|
|
||||||
|
export default defineNuxtModule({
|
||||||
|
name: 'nuxt-bridge',
|
||||||
|
configKey: 'bridge',
|
||||||
|
defaults: {
|
||||||
|
nitro: true,
|
||||||
|
vite: false,
|
||||||
|
app: true,
|
||||||
|
// TODO: Remove from 2.16
|
||||||
|
postcss8: true,
|
||||||
|
swc: true
|
||||||
|
},
|
||||||
|
async setup (opts, nuxt) {
|
||||||
|
if (opts.nitro) {
|
||||||
|
await setupNitroBridge()
|
||||||
|
}
|
||||||
|
if (opts.app) {
|
||||||
|
await setupAppBridge()
|
||||||
|
}
|
||||||
|
if (opts.vite) {
|
||||||
|
await installModule(nuxt, require.resolve('nuxt-vite'))
|
||||||
|
}
|
||||||
|
if (opts.postcss8) {
|
||||||
|
await installModule(nuxt, require.resolve('@nuxt/postcss8'))
|
||||||
|
}
|
||||||
|
if (opts.swc) {
|
||||||
|
await installModule(nuxt, require.resolve('nuxt-swc'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
@ -1,16 +1,14 @@
|
|||||||
import fetch from 'node-fetch'
|
import fetch from 'node-fetch'
|
||||||
|
import { addPluginTemplate, useNuxt } from '@nuxt/kit'
|
||||||
|
import { stringifyQuery } from 'ufo'
|
||||||
import { resolve } from 'upath'
|
import { resolve } from 'upath'
|
||||||
import { move, readFile, writeFile } from 'fs-extra'
|
import { readFile, writeFile } from 'fs-extra'
|
||||||
import type { ModuleContainer } from '@nuxt/kit'
|
import { build, generate, prepare, getNitroContext, NitroContext, createDevServer, wpfs, resolveMiddleware } from '@nuxt/nitro'
|
||||||
import { build, generate, prepare } from './build'
|
import { AsyncLoadingPlugin } from './async-loading'
|
||||||
import { getNitroContext, NitroContext } from './context'
|
import { distDir } from './dirs'
|
||||||
import { createDevServer } from './server/dev'
|
|
||||||
import { wpfs } from './utils/wpfs'
|
|
||||||
import { resolveMiddleware } from './server/middleware'
|
|
||||||
import AsyncLoadingPlugin from './webpack/wp4'
|
|
||||||
|
|
||||||
export default function nuxt2CompatModule (this: ModuleContainer) {
|
export function setupNitroBridge () {
|
||||||
const { nuxt } = this
|
const nuxt = useNuxt()
|
||||||
|
|
||||||
// Ensure we're not just building with 'static' target
|
// Ensure we're not just building with 'static' target
|
||||||
if (!nuxt.options.dev && nuxt.options.target === 'static' && !nuxt.options._export && !nuxt.options._legacyGenerate) {
|
if (!nuxt.options.dev && nuxt.options.target === 'static' && !nuxt.options._export && !nuxt.options._legacyGenerate) {
|
||||||
@ -73,15 +71,15 @@ export default function nuxt2CompatModule (this: ModuleContainer) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Nitro client plugin
|
// Nitro client plugin
|
||||||
this.addPlugin({
|
addPluginTemplate({
|
||||||
fileName: 'nitro.client.mjs',
|
filename: 'nitro.client.mjs',
|
||||||
src: resolve(nitroContext._internal.runtimeDir, 'app/nitro.client.mjs')
|
src: resolve(nitroContext._internal.runtimeDir, 'app/nitro.client.mjs')
|
||||||
})
|
})
|
||||||
|
|
||||||
// Nitro server plugin (for vue-meta)
|
// Nitro server plugin (for vue-meta)
|
||||||
this.addPlugin({
|
addPluginTemplate({
|
||||||
fileName: 'nitro-compat.server.js',
|
filename: 'nitro-bridge.server.mjs',
|
||||||
src: resolve(nitroContext._internal.runtimeDir, 'app/nitro-compat.server.js')
|
src: resolve(distDir, 'runtime/nitro-bridge.server.mjs')
|
||||||
})
|
})
|
||||||
|
|
||||||
// Fix module resolution
|
// Fix module resolution
|
||||||
@ -98,7 +96,7 @@ export default function nuxt2CompatModule (this: ModuleContainer) {
|
|||||||
nuxt.hook('build:compiled', async ({ name }) => {
|
nuxt.hook('build:compiled', async ({ name }) => {
|
||||||
if (name === 'server') {
|
if (name === 'server') {
|
||||||
const jsServerEntry = resolve(nuxt.options.buildDir, 'dist/server/server.js')
|
const jsServerEntry = resolve(nuxt.options.buildDir, 'dist/server/server.js')
|
||||||
await move(jsServerEntry, jsServerEntry.replace(/.js$/, '.cjs'))
|
await writeFile(jsServerEntry.replace(/.js$/, '.cjs'), 'module.exports = require("./server.js")', 'utf8')
|
||||||
await writeFile(jsServerEntry.replace(/.js$/, '.mjs'), 'export { default } from "./server.cjs"', 'utf8')
|
await writeFile(jsServerEntry.replace(/.js$/, '.mjs'), 'export { default } from "./server.cjs"', 'utf8')
|
||||||
} else if (name === 'client') {
|
} else if (name === 'client') {
|
||||||
const manifest = await readFile(resolve(nuxt.options.buildDir, 'dist/server/client.manifest.json'), 'utf8')
|
const manifest = await readFile(resolve(nuxt.options.buildDir, 'dist/server/client.manifest.json'), 'utf8')
|
||||||
@ -185,7 +183,7 @@ function createNuxt2DevServer (nitroContext: NitroContext) {
|
|||||||
throw new Error('There is no server listener to call `server.renderRoute()`')
|
throw new Error('There is no server listener to call `server.renderRoute()`')
|
||||||
}
|
}
|
||||||
const html = await fetch(listener.url + route, {
|
const html = await fetch(listener.url + route, {
|
||||||
headers: { 'nuxt-render-context': encodeQuery(renderContext) }
|
headers: { 'nuxt-render-context': stringifyQuery(renderContext) }
|
||||||
}).then(r => r.text())
|
}).then(r => r.text())
|
||||||
|
|
||||||
return { html }
|
return { html }
|
||||||
@ -200,9 +198,3 @@ function createNuxt2DevServer (nitroContext: NitroContext) {
|
|||||||
ready () { }
|
ready () { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function encodeQuery (obj) {
|
|
||||||
return Object.entries(obj).map(
|
|
||||||
([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(val))}`
|
|
||||||
).join('&')
|
|
||||||
}
|
|
6
packages/bridge/src/runtime/capi.plugin.mjs
Normal file
6
packages/bridge/src/runtime/capi.plugin.mjs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import Vue from 'vue' // eslint-disable-line import/default
|
||||||
|
import VueCompositionAPI from '@vue/composition-api'
|
||||||
|
|
||||||
|
Vue.use(VueCompositionAPI.default || VueCompositionAPI)
|
||||||
|
|
||||||
|
export default function () {}
|
10
packages/bridge/src/runtime/composables.mjs
Normal file
10
packages/bridge/src/runtime/composables.mjs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const mock = () => () => { throw new Error('not implemented') }
|
||||||
|
|
||||||
|
export const useAsyncData = mock()
|
||||||
|
export const asyncData = mock()
|
||||||
|
export const defineNuxtComponent = mock()
|
||||||
|
export const useSSRRef = mock()
|
||||||
|
export const useData = mock()
|
||||||
|
export const useGlobalData = mock()
|
||||||
|
export const useHydration = mock()
|
||||||
|
export const defineNuxtPlugin = mock()
|
1
packages/bridge/src/runtime/index.mjs
Normal file
1
packages/bridge/src/runtime/index.mjs
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './composables'
|
@ -252,3 +252,10 @@ export function addVitePlugin (plugin: VitePlugin, options?: ExtendViteConfigOpt
|
|||||||
config.plugins.push(plugin)
|
config.plugins.push(plugin)
|
||||||
}, options)
|
}, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if current nuxt instance is version 2 legacy
|
||||||
|
*/
|
||||||
|
export function isNuxt2 (nuxt?: any) {
|
||||||
|
return (nuxt || useNuxt()).version?.startsWith('v2')
|
||||||
|
}
|
||||||
|
@ -55,7 +55,7 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
|||||||
return nuxt
|
return nuxt
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compat
|
// Nuxt 2
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const { loadNuxt } = tryRequireModule('nuxt-edge', resolveOpts) || requireModule('nuxt', resolveOpts)
|
const { loadNuxt } = tryRequireModule('nuxt-edge', resolveOpts) || requireModule('nuxt', resolveOpts)
|
||||||
const nuxt = await loadNuxt({
|
const nuxt = await loadNuxt({
|
||||||
@ -76,7 +76,7 @@ export function buildNuxt (nuxt: Nuxt): Promise<any> {
|
|||||||
return build(nuxt)
|
return build(nuxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compat
|
// Nuxt 2
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const { build } = tryRequireModule('nuxt-edge', resolveOpts) || requireModule('nuxt', resolveOpts)
|
const { build } = tryRequireModule('nuxt-edge', resolveOpts) || requireModule('nuxt', resolveOpts)
|
||||||
return build(nuxt)
|
return build(nuxt)
|
||||||
|
@ -4,7 +4,6 @@ export default defineBuildConfig({
|
|||||||
declaration: true,
|
declaration: true,
|
||||||
entries: [
|
entries: [
|
||||||
'src/index',
|
'src/index',
|
||||||
'src/compat',
|
|
||||||
{ input: 'src/runtime/', outDir: 'dist/runtime', format: 'esm' },
|
{ input: 'src/runtime/', outDir: 'dist/runtime', format: 'esm' },
|
||||||
{ input: 'src/runtime/', outDir: 'dist/runtime', format: 'cjs', declaration: false }
|
{ input: 'src/runtime/', outDir: 'dist/runtime', format: 'cjs', declaration: false }
|
||||||
],
|
],
|
||||||
|
@ -1 +1,3 @@
|
|||||||
module.exports = require('./dist/compat')
|
export default function () {
|
||||||
|
throw new Error('Nitro compat for nuxt2 moved to nuxt bridge. Please check documentation for more details.')
|
||||||
|
}
|
||||||
|
@ -65,7 +65,7 @@ export function dynamicRequire ({ dir, ignore, inline }: Options): Plugin {
|
|||||||
src: resolve(dir, id).replace(/\\/g, '/'),
|
src: resolve(dir, id).replace(/\\/g, '/'),
|
||||||
name: '_' + id.replace(/[^a-zA-Z0-9_]/g, '_'),
|
name: '_' + id.replace(/[^a-zA-Z0-9_]/g, '_'),
|
||||||
meta: getWebpackChunkMeta(resolve(dir, id))
|
meta: getWebpackChunkMeta(resolve(dir, id))
|
||||||
}))
|
})).filter(chunk => chunk.meta)
|
||||||
|
|
||||||
return inline ? TMPL_INLINE({ chunks }) : TMPL_LAZY({ chunks })
|
return inline ? TMPL_INLINE({ chunks }) : TMPL_LAZY({ chunks })
|
||||||
}
|
}
|
||||||
@ -75,10 +75,13 @@ export function dynamicRequire ({ dir, ignore, inline }: Options): Plugin {
|
|||||||
function getWebpackChunkMeta (src: string) {
|
function getWebpackChunkMeta (src: string) {
|
||||||
const chunk = require(src) || {}
|
const chunk = require(src) || {}
|
||||||
const { id, ids, modules } = chunk
|
const { id, ids, modules } = chunk
|
||||||
|
if (!id && !ids) {
|
||||||
|
return null // Not a webpack chunk
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
ids,
|
ids,
|
||||||
moduleIds: Object.keys(modules)
|
moduleIds: Object.keys(modules || {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
test/fixtures/basic/package.json
vendored
2
test/fixtures/basic/package.json
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "fixture-compat",
|
"name": "fixture-bridge",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nuxt build"
|
"build": "nuxt build"
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ global.__NUXT_PREPATHS__ = (global.__NUXT_PREPATHS__ || []).concat(__dirname)
|
|||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
buildModules: [
|
buildModules: [
|
||||||
'@nuxt/nitro/compat'
|
'@nuxt/bridge'
|
||||||
],
|
],
|
||||||
serverMiddleware: [
|
serverMiddleware: [
|
||||||
{
|
{
|
3
test/fixtures/bridge/pages/index.vue
vendored
Normal file
3
test/fixtures/bridge/pages/index.vue
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<div>Hello Vue!</div>
|
||||||
|
</template>
|
3
test/fixtures/compat/pages/index.vue
vendored
3
test/fixtures/compat/pages/index.vue
vendored
@ -1,3 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>Hello Vue</div>
|
|
||||||
</template>
|
|
@ -7,14 +7,14 @@ import execa from 'execa'
|
|||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { fixtureDir, resolveWorkspace } from '../utils.mjs'
|
import { fixtureDir, resolveWorkspace } from '../utils.mjs'
|
||||||
|
|
||||||
const isCompat = Boolean(process.env.TEST_COMPAT)
|
const isBridge = Boolean(process.env.TEST_BRIDGE)
|
||||||
|
|
||||||
export function importModule (path) {
|
export function importModule (path) {
|
||||||
return import(pathToFileURL(path).href)
|
return import(pathToFileURL(path).href)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setupTest (preset) {
|
export function setupTest (preset) {
|
||||||
const fixture = isCompat ? 'compat' : 'basic'
|
const fixture = isBridge ? 'bridge' : 'basic'
|
||||||
const rootDir = fixtureDir(fixture)
|
const rootDir = fixtureDir(fixture)
|
||||||
const buildDir = resolve(rootDir, '.nuxt-' + preset)
|
const buildDir = resolve(rootDir, '.nuxt-' + preset)
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ export function setupTest (preset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
it('nitro build', async () => {
|
it('nitro build', async () => {
|
||||||
const nuxtCLI = isCompat
|
const nuxtCLI = isBridge
|
||||||
? resolve(ctx.rootDir, 'node_modules/nuxt/bin/nuxt.js')
|
? resolve(ctx.rootDir, 'node_modules/nuxt/bin/nuxt.js')
|
||||||
: resolveWorkspace('packages/nuxi/bin/nuxi.js')
|
: resolveWorkspace('packages/nuxi/bin/nuxi.js')
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user