Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

feat(nuxt): exclude page chunks from being prefetched #6662

Merged
merged 3 commits into from
Aug 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 19 additions & 1 deletion packages/nuxt/src/pages/module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { existsSync } from 'node:fs'
import { defineNuxtModule, addTemplate, addPlugin, addVitePlugin, addWebpackPlugin, findPath } from '@nuxt/kit'
import { resolve } from 'pathe'
import { relative, resolve } from 'pathe'
import { genString, genImport, genObjectFromRawEntries } from 'knitwork'
import escapeRE from 'escape-string-regexp'
import type { NuxtApp, NuxtPage } from '@nuxt/schema'
Expand Down Expand Up @@ -99,6 +99,24 @@ export default defineNuxtModule({
// Add router plugin
addPlugin(resolve(runtimeDir, 'router'))

const getSources = (pages: NuxtPage[]): string[] => pages.flatMap(p =>
[relative(nuxt.options.srcDir, p.file), ...getSources(p.children || [])]
)

// Do not prefetch page chunks
nuxt.hook('build:manifest', async (manifest) => {
const pages = await resolvePagesRoutes()
await nuxt.callHook('pages:extend', pages)

const sourceFiles = getSources(pages)
for (const key in manifest) {
if (manifest[key].isEntry) {
manifest[key].dynamicImports =
manifest[key].dynamicImports?.filter(i => !sourceFiles.includes(i))
}
}
})

// Add routes template
addTemplate({
filename: 'routes.mjs',
Expand Down
1 change: 1 addition & 0 deletions packages/schema/build.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default defineBuildConfig({
// Type imports
'vue-meta',
'vue-router',
'vue-bundle-renderer',
'vue',
'hookable',
'nitropack',
Expand Down
2 changes: 2 additions & 0 deletions packages/schema/src/types/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Server as HttpsServer } from 'node:https'
import type { Compiler, Configuration, Stats } from 'webpack'
import type { TSConfig } from 'pkg-types'
import type { InlineConfig as ViteInlineConfig, ViteDevServer } from 'vite'
import type { Manifest } from 'vue-bundle-renderer'
import type { ModuleContainer } from './module'
import type { NuxtTemplate, Nuxt, NuxtApp } from './nuxt'
import type { Preset as ImportPreset, Import } from 'unimport'
Expand Down Expand Up @@ -72,6 +73,7 @@ export interface NuxtHooks {
'app:templatesGenerated': (app: NuxtApp) => HookResult
'builder:generateApp': () => HookResult
'pages:extend': (pages: NuxtPage[]) => HookResult
'build:manifest': (manifest: Manifest) => HookResult

// Auto imports
'autoImports:sources': (presets: ImportPresetWithDeprecation[]) => HookResult
Expand Down
6 changes: 5 additions & 1 deletion packages/vite/src/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import fse from 'fs-extra'
import { resolve } from 'pathe'
import { withoutLeadingSlash, withTrailingSlash } from 'ufo'
import escapeRE from 'escape-string-regexp'
import { normalizeViteManifest, Manifest } from 'vue-bundle-renderer'
import { normalizeViteManifest } from 'vue-bundle-renderer'
import type { Manifest } from 'vue-bundle-renderer'
import type { ViteBuildContext } from './vite'

export async function writeManifest (ctx: ViteBuildContext, css: string[] = []) {
Expand Down Expand Up @@ -45,7 +46,10 @@ export async function writeManifest (ctx: ViteBuildContext, css: string[] = [])
}

await fse.mkdirp(serverDist)

const manifest = normalizeViteManifest(clientManifest)
await ctx.nuxt.callHook('build:manifest', manifest)

await fse.writeFile(resolve(serverDist, 'client.manifest.json'), JSON.stringify(manifest, null, 2), 'utf8')
await fse.writeFile(resolve(serverDist, 'client.manifest.mjs'), 'export default ' + JSON.stringify(manifest, null, 2), 'utf8')
}
27 changes: 17 additions & 10 deletions packages/webpack/src/plugins/vue/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ import hash from 'hash-sum'
import { uniq } from 'lodash-es'
import fse from 'fs-extra'

import type { Nuxt } from '@nuxt/schema'
import { isJS, isCSS, isHotUpdate } from './util'

interface PluginOptions {
filename: string
nuxt: Nuxt
}

export default class VueSSRClientPlugin {
options: {
filename: string
}
options: PluginOptions

constructor (options = {}) {
constructor (options: PluginOptions) {
this.options = Object.assign({
filename: null
}, options)
Expand Down Expand Up @@ -53,7 +57,7 @@ export default class VueSSRClientPlugin {
assetsMapping[componentHash].push(name)
})

const manifest = {
const webpackManifest = {
publicPath: stats.publicPath,
all: allFiles,
initial: initialFiles,
Expand All @@ -64,7 +68,7 @@ export default class VueSSRClientPlugin {

const { entrypoints, namedChunkGroups } = stats
const assetModules = stats.modules.filter(m => m.assets.length)
const fileToIndex = file => manifest.all.indexOf(file)
const fileToIndex = file => webpackManifest.all.indexOf(file)
stats.modules.forEach((m) => {
// Ignore modules duplicated in multiple chunks
if (m.chunks.length === 1) {
Expand All @@ -88,15 +92,15 @@ export default class VueSSRClientPlugin {
}

const files = Array.from(filesSet)
manifest.modules[hash(id)] = files
webpackManifest.modules[hash(id)] = files

// In production mode, modules may be concatenated by scope hoisting
// Include ConcatenatedModule for not losing module-component mapping
if (Array.isArray(m.modules)) {
for (const concatenatedModule of m.modules) {
const id = hash(concatenatedModule.identifier.replace(/\s\w+$/, ''))
if (!manifest.modules[id]) {
manifest.modules[id] = files
if (!webpackManifest.modules[id]) {
webpackManifest.modules[id] = files
}
}
}
Expand All @@ -110,7 +114,10 @@ export default class VueSSRClientPlugin {
}
})

const src = JSON.stringify(normalizeWebpackManifest(manifest), null, 2)
const manifest = normalizeWebpackManifest(webpackManifest)
await this.options.nuxt.callHook('build:manifest', manifest)

const src = JSON.stringify(manifest, null, 2)

await fse.mkdirp(dirname(this.options.filename))
await fse.writeFile(this.options.filename, src)
Expand Down
3 changes: 2 additions & 1 deletion packages/webpack/src/presets/vue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ export function vue (ctx: WebpackConfigContext) {

if (ctx.isClient) {
config.plugins.push(new VueSSRClientPlugin({
filename: resolve(options.buildDir, 'dist/server', `${ctx.name}.manifest.json`)
filename: resolve(options.buildDir, 'dist/server', `${ctx.name}.manifest.json`),
nuxt: ctx.nuxt
}))
} else {
config.plugins.push(new VueSSRServerPlugin({
Expand Down