This commit is contained in:
julien huang 2023-12-23 07:14:43 +01:00
parent 4dcc48f4e6
commit 5aac596833
9 changed files with 102 additions and 33 deletions

View File

@ -40,7 +40,7 @@ export default defineComponent({
inheritAttrs: false,
props: {
name: {
type: [String, Boolean, Object] as unknown as () => unknown extends PageMeta['layout'] ? MaybeRef<string | false> : PageMeta['layout'],
type: [String, Boolean, Object] as unknown as () => unknown extends ['layout'] ? MaybeRef<string | false> : PageMeta['layout'],
default: null
},
fallback: {

View File

@ -8,7 +8,6 @@ import type { Nuxt, NuxtApp, NuxtPage } from 'nuxt/schema'
import { createRoutesContext } from 'unplugin-vue-router'
import { resolveOptions } from 'unplugin-vue-router/options'
import type { EditableTreeNode, Options as TypedRouterOptions } from 'unplugin-vue-router'
import type { NitroRouteConfig } from 'nitropack'
import { defu } from 'defu'
import { distDir } from '../dirs'
@ -322,7 +321,8 @@ export default defineNuxtModule({
// Extract macros from pages
const pageMetaOptions: PageMetaPluginOptions = {
dev: nuxt.options.dev,
sourcemap: !!nuxt.options.sourcemap.server || !!nuxt.options.sourcemap.client
sourcemap: !!nuxt.options.sourcemap.server || !!nuxt.options.sourcemap.client,
updateTemplates
}
nuxt.hook('modules:done', () => {
addVitePlugin(() => PageMetaPlugin.vite(pageMetaOptions))
@ -364,7 +364,18 @@ export default defineNuxtModule({
filename: 'routes.mjs',
getContents ({ app }) {
const { routes, imports } = normalizeRoutes(app.pages)
return [...imports, `export default ${routes}`].join('\n')
return `
${
[...imports, `const routes = ${routes}`, `export default routes`].join('\n')
}
if (import.meta.hot) {
import.meta.hot.accept((mod) => {
console.log('up', mod.default)
Object.assign(routes, mod.default)
})
}
`
}
})

View File

@ -8,11 +8,12 @@ import type { Node } from 'estree-walker'
import { walk } from 'estree-walker'
import MagicString from 'magic-string'
import { isAbsolute } from 'pathe'
import { logger } from '@nuxt/kit'
import { logger, updateTemplates as _updateTemplate } from '@nuxt/kit'
import { } from "vite"
export interface PageMetaPluginOptions {
dev?: boolean
sourcemap?: boolean
updateTemplates: typeof _updateTemplate
}
const HAS_MACRO_RE = /\bdefinePageMeta\s*\(\s*/
@ -26,7 +27,7 @@ const CODE_HMR = `
// Vite
if (import.meta.hot) {
import.meta.hot.accept(mod => {
Object.assign(__nuxt_page_meta, mod)
import.meta.hot.invalidate()
})
}
// webpack
@ -40,15 +41,15 @@ export const PageMetaPlugin = createUnplugin((options: PageMetaPluginOptions) =>
return {
name: 'nuxt:pages-macros-transform',
enforce: 'post',
transformInclude (id) {
transformInclude(id) {
return !!parseMacroQuery(id).macro
},
transform (code, id) {
transform(code, id) {
const query = parseMacroQuery(id)
if (query.type && query.type !== 'script') { return }
const s = new MagicString(code)
function result () {
function result() {
if (s.hasChanged()) {
return {
code: s.toString(),
@ -116,7 +117,7 @@ export const PageMetaPlugin = createUnplugin((options: PageMetaPluginOptions) =>
sourceType: 'module',
ecmaVersion: 'latest'
}) as Node, {
enter (_node) {
enter(_node) {
if (_node.type !== 'CallExpression' || (_node as CallExpression).callee.type !== 'Identifier') { return }
const node = _node as CallExpression & { start: number, end: number }
const name = 'name' in node.callee && node.callee.name
@ -126,7 +127,7 @@ export const PageMetaPlugin = createUnplugin((options: PageMetaPluginOptions) =>
let contents = `const __nuxt_page_meta = ${code!.slice(meta.start, meta.end) || 'null'}\nexport default __nuxt_page_meta` + (options.dev ? CODE_HMR : '')
function addImport (name: string | false) {
function addImport(name: string | false) {
if (name && importMap.has(name)) {
const importValue = importMap.get(name)!.code
if (!addedImports.has(importValue)) {
@ -137,7 +138,7 @@ export const PageMetaPlugin = createUnplugin((options: PageMetaPluginOptions) =>
}
walk(meta, {
enter (_node) {
enter(_node) {
if (_node.type === 'CallExpression') {
const node = _node as CallExpression & { start: number, end: number }
addImport('name' in node.callee && node.callee.name)
@ -162,11 +163,22 @@ export const PageMetaPlugin = createUnplugin((options: PageMetaPluginOptions) =>
vite: {
handleHotUpdate: {
order: 'pre',
handler: ({ modules }) => {
handler: async (ctx) => {
const { modules } = ctx
// Remove macro file from modules list to prevent HMR overrides
const index = modules.findIndex(i => i.id?.includes('?macro=true'))
if (index !== -1) {
modules.splice(index, 1)
const [macroFile] = modules.splice(index, 1)
if (macroFile) {
await console.log(await ctx.read())
debugger
ctx.server.moduleGraph.invalidateModule(macroFile)
ctx.server.reloadModule(macroFile)
// update the macro file
}
}
}
}
@ -176,11 +188,11 @@ export const PageMetaPlugin = createUnplugin((options: PageMetaPluginOptions) =>
// https://github.com/vuejs/vue-loader/pull/1911
// https://github.com/vitejs/vite/issues/8473
function rewriteQuery (id: string) {
function rewriteQuery(id: string) {
return id.replace(/\?.+$/, r => '?macro=true&' + r.replace(/^\?/, '').replace(/&macro=true/, ''))
}
function parseMacroQuery (id: string) {
function parseMacroQuery(id: string) {
const { search } = parseURL(decodeURIComponent(isAbsolute(id) ? pathToFileURL(id).href : id).replace(/\?macro=true$/, ''))
const query = parseQuery(search)
if (id.includes('?macro=true')) {
@ -189,6 +201,6 @@ function parseMacroQuery (id: string) {
return query
}
function getQuotedSpecifier (id: string) {
function getQuotedSpecifier(id: string) {
return id.match(/(["']).*\1/)?.[0]
}

View File

@ -91,6 +91,40 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
previousRoute.value = from
})
if(import.meta.hot) {
console.log(import.meta.hot)
import.meta.hot.accept( () => {
console.log('hot reload self accept')
})
import.meta.hot.accept( '/pages/index.vue?macro=true', () => {
console.log('hot reload')
})
import.meta.hot.accept( '/pages/index.vue', () => {
console.log('hot reload')
})
import.meta.hot.accept( '/pages/index.vue?macro=true', () => {
console.log('hot reload')
})
import.meta.hot.accept( '#build/routes', () => {
console.log('hot reload')
})
import.meta.hot.accept( '/@id/virtual:nuxt:G:/repo/nuxt/playground/.nuxt/routes.mjs', () => {
console.log('hot reload')
})
import.meta.hot.accept( '/@id/virtual:nuxt:G:/repo/nuxt/playground/.nuxt/routes.mjs', () => {
console.log('hot reload')
})
import.meta.hot.accept("/_nuxt/@id/virtual:nuxt:G:/repo/nuxt/playground/.nuxt/routes.mjs", () => {
console.log('hot reload mod')
})
}
Object.defineProperty(nuxtApp.vueApp.config.globalProperties, 'previousRoute', {
get: () => previousRoute.value
})

View File

@ -1,13 +0,0 @@
<script setup lang="ts">
</script>
<template>
<!-- Edit this file to play around with Nuxt but never commit changes! -->
<div>
Nuxt 3 Playground
</div>
</template>
<style scoped>
</style>

View File

@ -0,0 +1,6 @@
<template>
<div class="blue" style="border: solid blue 1px;">
<slot />
</div>
</template>

View File

@ -0,0 +1,6 @@
<template>
<div class="red">
<slot />
</div>
</template>

View File

@ -0,0 +1,10 @@
<template>
<div>Index Page</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: 'blue',
});
</script>

View File

@ -188,8 +188,11 @@ export default defineNuxtConfig({
compilerOptions: {
isCustomElement: (tag) => {
return tag === 'custom-component'
}
}
},
prefixIdentifiers: false,
},
},
experimental: {
typedPages: true,