mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
fix(vite): handle emitted assets with relative urls and dynamic base (#2851)
This commit is contained in:
parent
0b0e56ae4f
commit
b803fdb4f9
@ -5,14 +5,14 @@ import vuePlugin from '@vitejs/plugin-vue'
|
|||||||
import viteJsxPlugin from '@vitejs/plugin-vue-jsx'
|
import viteJsxPlugin from '@vitejs/plugin-vue-jsx'
|
||||||
import type { Connect } from 'vite'
|
import type { Connect } from 'vite'
|
||||||
|
|
||||||
import { joinURL, withoutLeadingSlash } from 'ufo'
|
import { joinURL } from 'ufo'
|
||||||
import { cacheDirPlugin } from './plugins/cache-dir'
|
import { cacheDirPlugin } from './plugins/cache-dir'
|
||||||
import { analyzePlugin } from './plugins/analyze'
|
import { analyzePlugin } from './plugins/analyze'
|
||||||
import { wpfs } from './utils/wpfs'
|
import { wpfs } from './utils/wpfs'
|
||||||
import type { ViteBuildContext, ViteOptions } from './vite'
|
import type { ViteBuildContext, ViteOptions } from './vite'
|
||||||
import { writeManifest } from './manifest'
|
import { writeManifest } from './manifest'
|
||||||
import { devStyleSSRPlugin } from './plugins/dev-ssr-css'
|
import { devStyleSSRPlugin } from './plugins/dev-ssr-css'
|
||||||
import { DynamicBasePlugin } from './plugins/dynamic-base'
|
import { DynamicBasePlugin, RelativeAssetPlugin } from './plugins/dynamic-base'
|
||||||
|
|
||||||
export async function buildClient (ctx: ViteBuildContext) {
|
export async function buildClient (ctx: ViteBuildContext) {
|
||||||
const clientConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
const clientConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
||||||
@ -27,7 +27,6 @@ export async function buildClient (ctx: ViteBuildContext) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
assetsDir: ctx.nuxt.options.dev ? withoutLeadingSlash(ctx.nuxt.options.app.buildAssetsDir) : '.',
|
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
output: {
|
output: {
|
||||||
chunkFileNames: ctx.nuxt.options.dev ? undefined : '[name]-[hash].mjs',
|
chunkFileNames: ctx.nuxt.options.dev ? undefined : '[name]-[hash].mjs',
|
||||||
@ -42,6 +41,7 @@ export async function buildClient (ctx: ViteBuildContext) {
|
|||||||
vuePlugin(ctx.config.vue),
|
vuePlugin(ctx.config.vue),
|
||||||
viteJsxPlugin(),
|
viteJsxPlugin(),
|
||||||
DynamicBasePlugin.vite({ env: 'client', devAppConfig: ctx.nuxt.options.app }),
|
DynamicBasePlugin.vite({ env: 'client', devAppConfig: ctx.nuxt.options.app }),
|
||||||
|
RelativeAssetPlugin(),
|
||||||
devStyleSSRPlugin({
|
devStyleSSRPlugin({
|
||||||
rootDir: ctx.nuxt.options.rootDir,
|
rootDir: ctx.nuxt.options.rootDir,
|
||||||
buildAssetsURL: joinURL(ctx.nuxt.options.app.baseURL, ctx.nuxt.options.app.buildAssetsDir)
|
buildAssetsURL: joinURL(ctx.nuxt.options.app.baseURL, ctx.nuxt.options.app.buildAssetsDir)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { createUnplugin } from 'unplugin'
|
import { createUnplugin } from 'unplugin'
|
||||||
|
import type { Plugin } from 'vite'
|
||||||
|
|
||||||
interface DynamicBasePluginOptions {
|
interface DynamicBasePluginOptions {
|
||||||
env: 'dev' | 'server' | 'client'
|
env: 'dev' | 'server' | 'client'
|
||||||
@ -6,6 +7,31 @@ interface DynamicBasePluginOptions {
|
|||||||
globalPublicPath?: string
|
globalPublicPath?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const escapeRE = (str: string) => str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
|
||||||
|
|
||||||
|
export const RelativeAssetPlugin = function (): Plugin {
|
||||||
|
return {
|
||||||
|
name: 'nuxt:vite-relative-asset',
|
||||||
|
generateBundle (_, bundle) {
|
||||||
|
const generatedAssets = Object.entries(bundle).filter(([_, asset]) => asset.type === 'asset').map(([key]) => escapeRE(key))
|
||||||
|
const assetRE = new RegExp(`\\/__NUXT_BASE__\\/(${generatedAssets.join('|')})`, 'g')
|
||||||
|
|
||||||
|
for (const file in bundle) {
|
||||||
|
const asset = bundle[file]
|
||||||
|
if (asset.type === 'asset') {
|
||||||
|
const depth = file.split('/').length - 1
|
||||||
|
const assetBase = depth === 0 ? '.' : Array.from({ length: depth }).map(() => '..').join('/')
|
||||||
|
asset.source = asset.source.toString().replace(assetRE, r => r.replace(/\/__NUXT_BASE__/g, assetBase))
|
||||||
|
const publicBase = Array.from({ length: depth + 1 }).map(() => '..').join('/')
|
||||||
|
asset.source = asset.source.toString().replace(/\/__NUXT_BASE__/g, publicBase)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const VITE_ASSET_RE = /^export default ["'](__VITE_ASSET.*)["']$/
|
||||||
|
|
||||||
export const DynamicBasePlugin = createUnplugin(function (options: DynamicBasePluginOptions) {
|
export const DynamicBasePlugin = createUnplugin(function (options: DynamicBasePluginOptions) {
|
||||||
return {
|
return {
|
||||||
name: 'nuxt:dynamic-base-path',
|
name: 'nuxt:dynamic-base-path',
|
||||||
@ -13,6 +39,7 @@ export const DynamicBasePlugin = createUnplugin(function (options: DynamicBasePl
|
|||||||
if (id.startsWith('/__NUXT_BASE__')) {
|
if (id.startsWith('/__NUXT_BASE__')) {
|
||||||
return id.replace('/__NUXT_BASE__', '')
|
return id.replace('/__NUXT_BASE__', '')
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
},
|
},
|
||||||
enforce: 'post',
|
enforce: 'post',
|
||||||
transform (code, id) {
|
transform (code, id) {
|
||||||
@ -21,6 +48,12 @@ export const DynamicBasePlugin = createUnplugin(function (options: DynamicBasePl
|
|||||||
`${options.globalPublicPath} = joinURL(NUXT_BASE, NUXT_CONFIG.app.buildAssetsDir);` + code
|
`${options.globalPublicPath} = joinURL(NUXT_BASE, NUXT_CONFIG.app.buildAssetsDir);` + code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const assetId = code.match(VITE_ASSET_RE)
|
||||||
|
if (assetId) {
|
||||||
|
code = 'import { joinURL } from "ufo";' +
|
||||||
|
`export default joinURL(NUXT_BASE, NUXT_CONFIG.app.buildAssetsDir, "${assetId[1]}".replace("/__NUXT_BASE__", ""));`
|
||||||
|
}
|
||||||
|
|
||||||
if (code.includes('NUXT_BASE') && !code.includes('const NUXT_BASE =')) {
|
if (code.includes('NUXT_BASE') && !code.includes('const NUXT_BASE =')) {
|
||||||
code = 'const NUXT_BASE = NUXT_CONFIG.app.cdnURL || NUXT_CONFIG.app.baseURL;' + code
|
code = 'const NUXT_BASE = NUXT_CONFIG.app.cdnURL || NUXT_CONFIG.app.baseURL;' + code
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ export async function bundle (nuxt: Nuxt) {
|
|||||||
},
|
},
|
||||||
clearScreen: false,
|
clearScreen: false,
|
||||||
build: {
|
build: {
|
||||||
assetsDir: withoutLeadingSlash(nuxt.options.app.buildAssetsDir),
|
assetsDir: nuxt.options.dev ? withoutLeadingSlash(nuxt.options.app.buildAssetsDir) : '.',
|
||||||
emptyOutDir: false,
|
emptyOutDir: false,
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
input: resolve(nuxt.options.appDir, 'entry'),
|
input: resolve(nuxt.options.appDir, 'entry'),
|
||||||
|
Loading…
Reference in New Issue
Block a user