fix(vite): ensure newly created pages do not return 404 (#18447)

Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
This commit is contained in:
Daniel Roe 2023-01-25 04:24:58 -08:00 committed by GitHub
parent fdb31f418f
commit 23e5f980ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 77 additions and 120 deletions

View File

@ -73,7 +73,7 @@
"ufo": "^1.0.1",
"unbuild": "^1.1.1",
"vite": "^4.0.4",
"vitest": "^0.27.2",
"vitest": "^0.28.2",
"vue-tsc": "^1.0.24"
},
"packageManager": "pnpm@7.25.1",

View File

@ -26,7 +26,7 @@
"devDependencies": {
"playwright": "^1.29.2",
"unbuild": "latest",
"vitest": "^0.27.2"
"vitest": "^0.28.2"
},
"peerDependencies": {
"vue": "^3.2.45"

View File

@ -49,7 +49,7 @@
"ufo": "^1.0.1",
"unplugin": "^1.0.1",
"vite": "~4.0.4",
"vite-node": "^0.27.2",
"vite-node": "^0.28.2",
"vite-plugin-checker": "^0.5.4",
"vue-bundle-renderer": "^1.0.0"
},

View File

@ -18,12 +18,18 @@ import { transpile } from './utils/transpile'
export function viteNodePlugin (ctx: ViteBuildContext): VitePlugin {
// Store the invalidates for the next rendering
const invalidates = new Set<string>()
function markInvalidate (mod: ModuleNode) {
if (!mod.id) { return }
if (invalidates.has(mod.id)) { return }
invalidates.add(mod.id)
for (const importer of mod.importers) {
markInvalidate(importer)
markInvalidates(mod.importers)
}
function markInvalidates (mods?: ModuleNode[] | Set<ModuleNode>) {
if (!mods) { return }
for (const mod of mods) {
markInvalidate(mod)
}
}
@ -31,21 +37,34 @@ export function viteNodePlugin (ctx: ViteBuildContext): VitePlugin {
name: 'nuxt:vite-node-server',
enforce: 'post',
configureServer (server) {
server.middlewares.use('/__nuxt_vite_node__', toNodeListener(createViteNodeApp(ctx, invalidates)))
// Invalidate all virtual modules when templates are regenerated
ctx.nuxt.hook('app:templatesGenerated', () => {
function invalidateVirtualModules () {
for (const [id, mod] of server.moduleGraph.idToModuleMap) {
if (id.startsWith('virtual:')) {
markInvalidate(mod)
}
}
})
},
handleHotUpdate ({ file, server }) {
const mods = server.moduleGraph.getModulesByFile(file) || []
for (const mod of mods) {
markInvalidate(mod)
for (const plugin of ctx.nuxt.options.plugins) {
markInvalidates(server.moduleGraph.getModulesByFile(typeof plugin === 'string' ? plugin : plugin.src))
}
for (const template of ctx.nuxt.options.build.templates) {
markInvalidates(server.moduleGraph.getModulesByFile(template?.src))
}
}
server.middlewares.use('/__nuxt_vite_node__', toNodeListener(createViteNodeApp(ctx, invalidates)))
// Invalidate all virtual modules when templates are regenerated
ctx.nuxt.hook('app:templatesGenerated', () => {
invalidateVirtualModules()
})
server.watcher.on('all', (event, file) => {
markInvalidates(server.moduleGraph.getModulesByFile(file))
// Invalidate all virtual modules when a file is added or removed
if (event === 'add' || event === 'unlink') {
invalidateVirtualModules()
}
})
}
}
}

View File

@ -50,7 +50,7 @@ importers:
ufo: ^1.0.1
unbuild: ^1.1.1
vite: ^4.0.4
vitest: ^0.27.2
vitest: ^0.28.2
vue-tsc: ^1.0.24
devDependencies:
'@actions/core': 1.10.0
@ -86,7 +86,7 @@ importers:
ufo: 1.0.1
unbuild: 1.1.1
vite: 4.0.4_@types+node@18.11.18
vitest: 0.27.3
vitest: 0.28.2
vue-tsc: 1.0.24_typescript@4.9.4
examples/advanced/config-extends:
@ -121,7 +121,7 @@ importers:
devDependencies:
'@nuxt/test-utils': link:../../../packages/test-utils
nuxt: link:../../../packages/nuxt
vitest: 0.28.1
vitest: 0.28.2
examples/app-config:
specifiers:
@ -566,7 +566,7 @@ importers:
pathe: ^1.0.0
playwright: ^1.29.2
unbuild: ^1.1.1
vitest: ^0.27.2
vitest: ^0.28.2
dependencies:
'@nuxt/kit': link:../kit
'@nuxt/schema': link:../schema
@ -580,7 +580,7 @@ importers:
devDependencies:
playwright: 1.29.2
unbuild: 1.1.1
vitest: 0.27.3
vitest: 0.28.2
packages/vite:
specifiers:
@ -617,7 +617,7 @@ importers:
unbuild: ^1.1.1
unplugin: ^1.0.1
vite: ^4.0.4
vite-node: ^0.27.2
vite-node: ^0.28.2
vite-plugin-checker: ^0.5.4
vue: 3.2.45
vue-bundle-renderer: ^1.0.0
@ -652,7 +652,7 @@ importers:
ufo: 1.0.1
unplugin: 1.0.1
vite: 4.0.4
vite-node: 0.27.3
vite-node: 0.28.2
vite-plugin-checker: 0.5.4_vite@4.0.4
vue-bundle-renderer: 1.0.0
devDependencies:
@ -2575,30 +2575,30 @@ packages:
vue: 3.2.45
dev: false
/@vitest/expect/0.28.1:
resolution: {integrity: sha512-BOvWjBoocKrrTTTC0opIvzOEa7WR/Ovx4++QYlbjYKjnQJfWRSEQkTpAIEfOURtZ/ICcaLk5jvsRshXvjarZew==}
/@vitest/expect/0.28.2:
resolution: {integrity: sha512-syEAK7I24/aGR2lXma98WNnvMwAJ+fMx32yPcj8eLdCEWjZI3SH8ozMaKQMy65B/xZCZAl6MXmfjtJb2CpWPMg==}
dependencies:
'@vitest/spy': 0.28.1
'@vitest/utils': 0.28.1
'@vitest/spy': 0.28.2
'@vitest/utils': 0.28.2
chai: 4.3.7
dev: true
/@vitest/runner/0.28.1:
resolution: {integrity: sha512-kOdmgiNe+mAxZhvj2eUTqKnjfvzzknmrcS+SZXV7j6VgJuWPFAMCv3TWOe03nF9dkqDfVLCDRw/hwFuCzmzlQg==}
/@vitest/runner/0.28.2:
resolution: {integrity: sha512-BJ9CtfPwWM8uc5p7Ty0OprwApyh8RIaSK7QeQPhwfDYA59AAE009OytqA3aX0yj1Qy5+k/mYFJS8RJZgsueSGA==}
dependencies:
'@vitest/utils': 0.28.1
'@vitest/utils': 0.28.2
p-limit: 4.0.0
pathe: 1.1.0
dev: true
/@vitest/spy/0.28.1:
resolution: {integrity: sha512-XGlD78cG3IxXNnGwEF121l0MfTNlHSdI25gS2ik0z6f/D9wWUOru849QkJbuNl4CMlZCtNkx3b5IS6MRwKGKuA==}
/@vitest/spy/0.28.2:
resolution: {integrity: sha512-KlLzTzi5E6tHcI12VT+brlY1Pdi7sUzLf9+YXgh80+CfLu9DqPZi38doBBAUhqEnW/emoLCMinPMMoJlNAQZXA==}
dependencies:
tinyspy: 1.0.2
dev: true
/@vitest/utils/0.28.1:
resolution: {integrity: sha512-a7cV1fs5MeU+W+8sn8gM9gV+q7V/wYz3/4y016w/icyJEKm9AMdSHnrzxTWaElJ07X40pwU6m5353Jlw6Rbd8w==}
/@vitest/utils/0.28.2:
resolution: {integrity: sha512-wcVTNnVdr22IGxZHDgiXrxWYcXsNg0iX2iBuOH3tVs9eme6fXJ0wxjn0/gCpp0TofQSoUwo3tX8LNACFVseDuA==}
dependencies:
cli-truncate: 3.1.0
diff: 5.1.0
@ -6665,9 +6665,6 @@ packages:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
/pathe/0.2.0:
resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==}
/pathe/0.3.9:
resolution: {integrity: sha512-6Y6s0vT112P3jD8dGfuS6r+lpa0qqNrLyHPOwvXMnyNTQaYiwgau2DP3aNDsR13xqtGj7rrPo+jFUATpU6/s+g==}
dev: true
@ -8381,15 +8378,15 @@ packages:
extsprintf: 1.3.0
dev: true
/vite-node/0.27.3:
resolution: {integrity: sha512-eyJYOO64o5HIp8poc4bJX+ZNBwMZeI3f6/JdiUmJgW02Mt7LnoCtDMRVmLaY9S05SIsjGe339ZK4uo2wQ+bF9g==}
/vite-node/0.28.2:
resolution: {integrity: sha512-zyiJ3DLs9zXign4P2MD4PQk+7rdT+JkHukgmmS0KuImbCQ7WnCdea5imQVeT6OtUsBwsLztJxQODUsinVr91tg==}
engines: {node: '>=v14.16.0'}
hasBin: true
dependencies:
cac: 6.7.14
debug: 4.3.4
mlly: 1.1.0
pathe: 0.2.0
pathe: 1.1.0
picocolors: 1.0.0
source-map: 0.6.1
source-map-support: 0.5.21
@ -8404,31 +8401,8 @@ packages:
- terser
dev: false
/vite-node/0.27.3_@types+node@18.11.18:
resolution: {integrity: sha512-eyJYOO64o5HIp8poc4bJX+ZNBwMZeI3f6/JdiUmJgW02Mt7LnoCtDMRVmLaY9S05SIsjGe339ZK4uo2wQ+bF9g==}
engines: {node: '>=v14.16.0'}
hasBin: true
dependencies:
cac: 6.7.14
debug: 4.3.4
mlly: 1.1.0
pathe: 0.2.0
picocolors: 1.0.0
source-map: 0.6.1
source-map-support: 0.5.21
vite: 4.0.4_@types+node@18.11.18
transitivePeerDependencies:
- '@types/node'
- less
- sass
- stylus
- sugarss
- supports-color
- terser
dev: true
/vite-node/0.28.1_@types+node@18.11.18:
resolution: {integrity: sha512-Mmab+cIeElkVn4noScCRjy8nnQdh5LDIR4QCH/pVWtY15zv5Z1J7u6/471B9JZ2r8CEIs42vTbngaamOVkhPLA==}
/vite-node/0.28.2_@types+node@18.11.18:
resolution: {integrity: sha512-zyiJ3DLs9zXign4P2MD4PQk+7rdT+JkHukgmmS0KuImbCQ7WnCdea5imQVeT6OtUsBwsLztJxQODUsinVr91tg==}
engines: {node: '>=v14.16.0'}
hasBin: true
dependencies:
@ -8565,8 +8539,8 @@ packages:
fsevents: 2.3.2
dev: true
/vitest/0.27.3:
resolution: {integrity: sha512-Ld3UVgRVhJUtqvQ3dW89GxiApFAgBsWJZBCWzK+gA3w2yG68csXlGZZ4WDJURf+8ecNfgrScga6xY+8YSOpiMg==}
/vitest/0.28.2:
resolution: {integrity: sha512-HJBlRla4Mng0OiZ8aWunCecJ6BzLDA4yuzuxiBuBU2MXjGB6I4zT7QgIBL/UrwGKlNxLwaDC5P/4OpeuTlW8yQ==}
engines: {node: '>=v14.16.0'}
hasBin: true
peerDependencies:
@ -8590,60 +8564,10 @@ packages:
'@types/chai': 4.3.4
'@types/chai-subset': 1.3.3
'@types/node': 18.11.18
acorn: 8.8.2
acorn-walk: 8.2.0
cac: 6.7.14
chai: 4.3.7
debug: 4.3.4
local-pkg: 0.4.3
picocolors: 1.0.0
source-map: 0.6.1
std-env: 3.3.1
strip-literal: 1.0.0
tinybench: 2.3.1
tinypool: 0.3.0
tinyspy: 1.0.2
vite: 4.0.4_@types+node@18.11.18
vite-node: 0.27.3_@types+node@18.11.18
why-is-node-running: 2.2.2
transitivePeerDependencies:
- less
- sass
- stylus
- sugarss
- supports-color
- terser
dev: true
/vitest/0.28.1:
resolution: {integrity: sha512-F6wAO3K5+UqJCCGt0YAl3Ila2f+fpBrJhl9n7qWEhREwfzQeXlMkkCqGqGtzBxCSa8kv5QHrkshX8AaPTXYACQ==}
engines: {node: '>=v14.16.0'}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@vitest/browser': '*'
'@vitest/ui': '*'
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
'@edge-runtime/vm':
optional: true
'@vitest/browser':
optional: true
'@vitest/ui':
optional: true
happy-dom:
optional: true
jsdom:
optional: true
dependencies:
'@types/chai': 4.3.4
'@types/chai-subset': 1.3.3
'@types/node': 18.11.18
'@vitest/expect': 0.28.1
'@vitest/runner': 0.28.1
'@vitest/spy': 0.28.1
'@vitest/utils': 0.28.1
'@vitest/expect': 0.28.2
'@vitest/runner': 0.28.2
'@vitest/spy': 0.28.2
'@vitest/utils': 0.28.2
acorn: 8.8.2
acorn-walk: 8.2.0
cac: 6.7.14
@ -8659,7 +8583,7 @@ packages:
tinypool: 0.3.0
tinyspy: 1.0.2
vite: 4.0.4_@types+node@18.11.18
vite-node: 0.28.1_@types+node@18.11.18
vite-node: 0.28.2_@types+node@18.11.18
why-is-node-running: 2.2.2
transitivePeerDependencies:
- less

View File

@ -1029,5 +1029,19 @@ if (isDev() && !isWindows) {
expect(consoleLogErrors).toEqual([])
expect(consoleLogWarnings).toEqual([])
}, 60_000)
it('should detect new routes', async () => {
const html = await $fetch('/some-404')
expect(html).toContain('404 at some-404')
// write new page route
const indexVue = await fsp.readFile(join(fixturePath, 'pages/index.vue'), 'utf8')
await fsp.writeFile(join(fixturePath, 'pages/some-404.vue'), indexVue)
await expectWithPolling(
() => $fetch('/some-404').then(r => r.includes('Hello Nuxt 3') ? 'ok' : 'fail'),
'ok'
)
})
})
}