feat(vite): add vite's modulepreload polyfill (#31164)

This commit is contained in:
Daniel Roe 2025-02-28 23:20:14 +00:00
parent 5e61eb567d
commit cd83b74e1a
No known key found for this signature in database
GPG Key ID: CBC814C393D93268
6 changed files with 44 additions and 12 deletions

View File

@ -12,10 +12,11 @@ import { env, nodeless } from 'unenv'
import { defineEventHandler, handleCors, setHeader } from 'h3' import { defineEventHandler, handleCors, setHeader } from 'h3'
import type { ViteConfig } from '@nuxt/schema' import type { ViteConfig } from '@nuxt/schema'
import type { ViteBuildContext } from './vite' import type { ViteBuildContext } from './vite'
import { devStyleSSRPlugin } from './plugins/dev-ssr-css' import { DevStyleSSRPlugin } from './plugins/dev-ssr-css'
import { runtimePathsPlugin } from './plugins/paths' import { RuntimePathsPlugin } from './plugins/paths'
import { typeCheckPlugin } from './plugins/type-check' import { TypeCheckPlugin } from './plugins/type-check'
import { viteNodePlugin } from './vite-node' import { ModulePreloadPolyfillPlugin } from './plugins/module-preload-polyfill'
import { ViteNodePlugin } from './vite-node'
import { createViteLogger } from './utils/logger' import { createViteLogger } from './utils/logger'
export async function buildClient (ctx: ViteBuildContext) { export async function buildClient (ctx: ViteBuildContext) {
@ -131,14 +132,14 @@ export async function buildClient (ctx: ViteBuildContext) {
}, },
}, },
plugins: [ plugins: [
devStyleSSRPlugin({ DevStyleSSRPlugin({
srcDir: ctx.nuxt.options.srcDir, srcDir: ctx.nuxt.options.srcDir,
buildAssetsURL: joinURL(ctx.nuxt.options.app.baseURL, ctx.nuxt.options.app.buildAssetsDir), buildAssetsURL: joinURL(ctx.nuxt.options.app.baseURL, ctx.nuxt.options.app.buildAssetsDir),
}), }),
runtimePathsPlugin({ RuntimePathsPlugin({
sourcemap: !!ctx.nuxt.options.sourcemap.client, sourcemap: !!ctx.nuxt.options.sourcemap.client,
}), }),
viteNodePlugin(ctx), ViteNodePlugin(ctx),
], ],
appType: 'custom', appType: 'custom',
server: { server: {
@ -198,9 +199,14 @@ export async function buildClient (ctx: ViteBuildContext) {
// Add type checking client panel // Add type checking client panel
if (!ctx.nuxt.options.test && ctx.nuxt.options.typescript.typeCheck === true && ctx.nuxt.options.dev) { if (!ctx.nuxt.options.test && ctx.nuxt.options.typescript.typeCheck === true && ctx.nuxt.options.dev) {
clientConfig.plugins!.push(typeCheckPlugin({ sourcemap: !!ctx.nuxt.options.sourcemap.client })) clientConfig.plugins!.push(TypeCheckPlugin({ sourcemap: !!ctx.nuxt.options.sourcemap.client }))
} }
clientConfig.plugins!.push(ModulePreloadPolyfillPlugin({
sourcemap: !!ctx.nuxt.options.sourcemap.client,
entry: ctx.entry,
}))
await ctx.nuxt.callHook('vite:extendConfig', clientConfig, { isClient: true, isServer: false }) await ctx.nuxt.callHook('vite:extendConfig', clientConfig, { isClient: true, isServer: false })
clientConfig.plugins!.unshift( clientConfig.plugins!.unshift(

View File

@ -7,7 +7,7 @@ interface DevStyleSSRPluginOptions {
buildAssetsURL: string buildAssetsURL: string
} }
export function devStyleSSRPlugin (options: DevStyleSSRPluginOptions): Plugin { export function DevStyleSSRPlugin (options: DevStyleSSRPluginOptions): Plugin {
return { return {
name: 'nuxt:dev-style-ssr', name: 'nuxt:dev-style-ssr',
apply: 'serve', apply: 'serve',

View File

@ -0,0 +1,26 @@
import MagicString from 'magic-string'
import type { Plugin } from 'vite'
const QUERY_RE = /\?.+$/
export function ModulePreloadPolyfillPlugin (options: { sourcemap: boolean, entry: string }): Plugin {
let isDisabled = false
return {
name: 'nuxt:module-preload-polyfill',
configResolved (config) {
isDisabled = config.build.modulePreload === false || config.build.modulePreload.polyfill === false
},
transform (code, id) {
if (isDisabled || id.replace(QUERY_RE, '') !== options.entry) { return }
const s = new MagicString(code)
s.prepend('import "vite/modulepreload-polyfill";\n')
return {
code: s.toString(),
map: options.sourcemap ? s.generateMap({ hires: true }) : undefined,
}
},
}
}

View File

@ -10,7 +10,7 @@ interface RuntimePathsOptions {
const VITE_ASSET_RE = /__VITE_ASSET__|__VITE_PUBLIC_ASSET__/ const VITE_ASSET_RE = /__VITE_ASSET__|__VITE_PUBLIC_ASSET__/
export function runtimePathsPlugin (options: RuntimePathsOptions): Plugin { export function RuntimePathsPlugin (options: RuntimePathsOptions): Plugin {
return { return {
name: 'nuxt:runtime-paths-dep', name: 'nuxt:runtime-paths-dep',
enforce: 'post', enforce: 'post',

View File

@ -3,7 +3,7 @@ import type { Plugin } from 'vite'
const QUERY_RE = /\?.+$/ const QUERY_RE = /\?.+$/
export function typeCheckPlugin (options: { sourcemap?: boolean } = {}): Plugin { export function TypeCheckPlugin (options: { sourcemap?: boolean } = {}): Plugin {
let entry: string let entry: string
return { return {
name: 'nuxt:type-check', name: 'nuxt:type-check',

View File

@ -14,7 +14,7 @@ import { isCSS } from './utils'
// TODO: Remove this in favor of registerViteNodeMiddleware // TODO: Remove this in favor of registerViteNodeMiddleware
// after Nitropack or h3 allows adding middleware after setup // after Nitropack or h3 allows adding middleware after setup
export function viteNodePlugin (ctx: ViteBuildContext): VitePlugin { export function ViteNodePlugin (ctx: ViteBuildContext): VitePlugin {
// Store the invalidates for the next rendering // Store the invalidates for the next rendering
const invalidates = new Set<string>() const invalidates = new Set<string>()