feat(nuxt): use build plugin to access nuxt route injection (#21585)

This commit is contained in:
Daniel Roe 2023-08-07 14:19:48 +01:00 committed by GitHub
parent f4ee12e6ba
commit 305d6de030
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 1 deletions

View File

@ -1,6 +1,6 @@
import { existsSync, readdirSync } from 'node:fs'
import { mkdir, readFile } from 'node:fs/promises'
import { addComponent, addPlugin, addTemplate, addVitePlugin, addWebpackPlugin, defineNuxtModule, findPath, updateTemplates } from '@nuxt/kit'
import { addBuildPlugin, addComponent, addPlugin, addTemplate, addVitePlugin, addWebpackPlugin, defineNuxtModule, findPath, updateTemplates } from '@nuxt/kit'
import { dirname, join, relative, resolve } from 'pathe'
import { genImport, genObjectFromRawEntries, genString } from 'knitwork'
import { joinURL } from 'ufo'
@ -13,6 +13,7 @@ import { distDir } from '../dirs'
import { normalizeRoutes, resolvePagesRoutes } from './utils'
import type { PageMetaPluginOptions } from './page-meta'
import { PageMetaPlugin } from './page-meta'
import { RouteInjectionPlugin } from './route-injection'
const OPTIONAL_PARAM_RE = /^\/?:.*(\?|\(\.\*\)\*)$/
@ -253,6 +254,11 @@ export default defineNuxtModule({
// Add prefetching support for middleware & layouts
addPlugin(resolve(runtimeDir, 'plugins/prefetch.client'))
// Add build plugin to ensure template $route is kept in sync with `<NuxtPage>`
if (nuxt.options.experimental.templateRouteInjection) {
addBuildPlugin(RouteInjectionPlugin(nuxt), { server: false })
}
// Add router plugin
addPlugin(resolve(runtimeDir, 'plugins/router'))

View File

@ -0,0 +1,39 @@
import { createUnplugin } from 'unplugin'
import MagicString from 'magic-string'
import type { Nuxt } from '@nuxt/schema'
import { isVue } from '../core/utils'
const INJECTION_RE = /\b_ctx\.\$route\b/g
const INJECTION_SINGLE_RE = /\b_ctx\.\$route\b/
export const RouteInjectionPlugin = (nuxt: Nuxt) => createUnplugin(() => {
return {
name: 'nuxt:route-injection-plugin',
enforce: 'post',
transformInclude (id) {
return isVue(id, { type: ['template', 'script'] })
},
transform (code) {
if (!INJECTION_SINGLE_RE.test(code)) { return }
let replaced = false
const s = new MagicString(code)
s.replace(INJECTION_RE, () => {
replaced = true
return '_ctx._.provides[__nuxt_route_symbol]'
})
if (replaced) {
s.prepend('import { PageRouteSymbol as __nuxt_route_symbol } from \'#app/components/injections\';\n')
}
if (s.hasChanged()) {
return {
code: s.toString(),
map: nuxt.options.sourcemap.client || nuxt.options.sourcemap.server
? s.generateMap({ hires: true })
: undefined
}
}
}
}
})

View File

@ -58,6 +58,17 @@ export default defineUntypedSchema({
},
},
/**
* By default the route object returned by the auto-imported `useRoute()` composable
* is kept in sync with the current page in view in `<NuxtPage>`. This is not true for
* `vue-router`'s exported `useRoute` or for the default `$route` object available in your
* Vue templates.
*
* By enabling this option a mixin will be injected to keep the `$route` template object
* in sync with Nuxt's managed `useRoute()`.
*/
templateRouteInjection: true,
/**
* Whether to restore Nuxt app state from `sessionStorage` when reloading the page
* after a chunk error or manual `reloadNuxtApp()` call.