Skip to content

Commit

Permalink
feat: nuxt bridge (nuxt#459)
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 authored Sep 5, 2021
1 parent de57626 commit 44458fc
Show file tree
Hide file tree
Showing 32 changed files with 2,299 additions and 126 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
- name: Test (presets)
run: yarn test:presets

test-compat:
test-bridge:
runs-on: ${{ matrix.os }}

strategy:
Expand All @@ -73,24 +73,24 @@ jobs:
cache: 'yarn'
cache-dependency-path: |
yarn.lock
test/fixtures/compat/yarn.lock
test/fixtures/bridge/yarn.lock
- name: Install dependencies
run: yarn --immutable

- name: Install dependencies (compat fixture)
run: yarn --immutable && cd test/fixtures/compat && yarn --immutable
- name: Install dependencies (bridge fixture)
run: yarn --immutable && cd test/fixtures/bridge && yarn --immutable

- name: Stub
run: yarn stub

- name: Test (presets compat)
run: yarn test:compat
- name: Test (presets bridge)
run: yarn test:bridge

build-release:
needs:
- test
- test-compat
- test-bridge
- lint
runs-on: ${{ matrix.os }}

Expand Down
2 changes: 2 additions & 0 deletions docs/content/1.get-started/1.installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

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

Before installing Nuxt, you'll need to have a local development environment.
Expand Down
2 changes: 0 additions & 2 deletions docs/content/3.server/1.intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ Nuxt3 is powered by a new server engine, code-named Nitro. It has:
- Hybrid mode for static + serverless sites
- A development mode with hot module reloading

In addition it is backwards compatible with Nuxt2 via [a compatibility module](/server/compat).

## API Layer

Server [API endpoints](/server/api) and [Middleware](/server/middleware) are added by Nitro that internally uses [h3](https://github.com/unjs/h3).
Expand Down
81 changes: 81 additions & 0 deletions docs/content/7.bridge/1.intro.md
Original file line number Diff line number Diff line change
@@ -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.
31 changes: 0 additions & 31 deletions docs/content/7.bridge/1.nitro.md

This file was deleted.

130 changes: 130 additions & 0 deletions docs/content/7.bridge/2.migration.md
Original file line number Diff line number Diff line change
@@ -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.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"lint": "eslint --ext .vue,.ts,.js .",
"test": "yarn lint && yarn test:presets",
"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.*",
"version": "yarn && git add yarn.lock"
},
Expand Down
7 changes: 7 additions & 0 deletions packages/bridge/build.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineBuildConfig } from 'unbuild'

export default defineBuildConfig({
entries: [
'src/module'
]
})
32 changes: 32 additions & 0 deletions packages/bridge/package.json
Original file line number Diff line number Diff line change
@@ -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 changes: 39 additions & 0 deletions packages/bridge/src/app.ts
Original file line number Diff line number Diff line change
@@ -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'
}
}
}
})
}
Loading

0 comments on commit 44458fc

Please sign in to comment.