Skip to content

Commit

Permalink
fix(vite): ensure newly created pages do not return 404 (#18447)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
danielroe and antfu committed Jan 25, 2023
1 parent fdb31f4 commit 23e5f98
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 120 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion packages/test-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"devDependencies": {
"playwright": "^1.29.2",
"unbuild": "latest",
"vitest": "^0.27.2"
"vitest": "^0.28.2"
},
"peerDependencies": {
"vue": "^3.2.45"
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
41 changes: 30 additions & 11 deletions packages/vite/src/vite-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,53 @@ 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)
}
}

return {
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()
}
})
}
}
}
Expand Down
136 changes: 30 additions & 106 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions test/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
)
})
})
}

0 comments on commit 23e5f98

Please sign in to comment.