mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 23:22:02 +00:00
refactor(bridge): align bridge with vite and inline systemjs polyfill in entry (#4005)
This commit is contained in:
parent
59b319b492
commit
ade3378a00
@ -5,11 +5,14 @@ import PluginLegacy from '@vitejs/plugin-legacy'
|
|||||||
import { logger } from '@nuxt/kit'
|
import { logger } from '@nuxt/kit'
|
||||||
import { joinURL } from 'ufo'
|
import { joinURL } from 'ufo'
|
||||||
import { devStyleSSRPlugin } from '../../../vite/src/plugins/dev-ssr-css'
|
import { devStyleSSRPlugin } from '../../../vite/src/plugins/dev-ssr-css'
|
||||||
|
import { RelativeAssetPlugin } from '../../../vite/src/plugins/dynamic-base'
|
||||||
import { jsxPlugin } from './plugins/jsx'
|
import { jsxPlugin } from './plugins/jsx'
|
||||||
import { ViteBuildContext, ViteOptions } from './types'
|
import { ViteBuildContext, ViteOptions } from './types'
|
||||||
|
|
||||||
export async function buildClient (ctx: ViteBuildContext) {
|
export async function buildClient (ctx: ViteBuildContext) {
|
||||||
const alias = {}
|
const alias = {
|
||||||
|
'#_config': resolve(ctx.nuxt.options.buildDir, 'config.client.mjs')
|
||||||
|
}
|
||||||
for (const p of ctx.builder.plugins) {
|
for (const p of ctx.builder.plugins) {
|
||||||
alias[p.name] = p.mode === 'server'
|
alias[p.name] = p.mode === 'server'
|
||||||
? `defaultexport:${resolve(ctx.nuxt.options.buildDir, 'empty.js')}`
|
? `defaultexport:${resolve(ctx.nuxt.options.buildDir, 'empty.js')}`
|
||||||
@ -18,27 +21,27 @@ export async function buildClient (ctx: ViteBuildContext) {
|
|||||||
|
|
||||||
const clientConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
const clientConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
||||||
define: {
|
define: {
|
||||||
'process.client': 'true',
|
'process.client': true,
|
||||||
'process.server': 'false',
|
'process.server': false,
|
||||||
'process.static': 'false',
|
'process.static': false,
|
||||||
'module.hot': 'false'
|
'module.hot': false
|
||||||
},
|
},
|
||||||
cacheDir: resolve(ctx.nuxt.options.rootDir, 'node_modules/.cache/vite/client'),
|
cacheDir: resolve(ctx.nuxt.options.rootDir, 'node_modules/.cache/vite/client'),
|
||||||
resolve: {
|
resolve: {
|
||||||
alias
|
alias
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
outDir: resolve(ctx.nuxt.options.buildDir, 'dist/client'),
|
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
input: resolve(ctx.nuxt.options.buildDir, 'client.js')
|
input: resolve(ctx.nuxt.options.buildDir, 'client.js')
|
||||||
},
|
},
|
||||||
manifest: true,
|
manifest: true,
|
||||||
ssrManifest: true
|
outDir: resolve(ctx.nuxt.options.buildDir, 'dist/client')
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
jsxPlugin(),
|
jsxPlugin(),
|
||||||
createVuePlugin(ctx.config.vue),
|
createVuePlugin(ctx.config.vue),
|
||||||
PluginLegacy(),
|
PluginLegacy(),
|
||||||
|
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)
|
||||||
@ -67,10 +70,6 @@ export async function buildClient (ctx: ViteBuildContext) {
|
|||||||
const viteMiddleware = (req, res, next) => {
|
const viteMiddleware = (req, res, next) => {
|
||||||
// Workaround: vite devmiddleware modifies req.url
|
// Workaround: vite devmiddleware modifies req.url
|
||||||
const originalURL = req.url
|
const originalURL = req.url
|
||||||
req.url = req.url.replace('/_nuxt/', '/.nuxt/')
|
|
||||||
if (req.url.includes('@vite/client')) {
|
|
||||||
req.url = '/@vite/client'
|
|
||||||
}
|
|
||||||
viteServer.middlewares.handle(req, res, (err) => {
|
viteServer.middlewares.handle(req, res, (err) => {
|
||||||
req.url = originalURL
|
req.url = originalURL
|
||||||
next(err)
|
next(err)
|
||||||
|
@ -56,22 +56,27 @@ export async function generateBuildManifest (ctx: ViteBuildContext) {
|
|||||||
|
|
||||||
// Search for polyfill file, we don't include it in the client entry
|
// Search for polyfill file, we don't include it in the client entry
|
||||||
const polyfillName = initialEntries.find(id => id.startsWith('polyfills-legacy.'))
|
const polyfillName = initialEntries.find(id => id.startsWith('polyfills-legacy.'))
|
||||||
|
const polyfill = await fse.readFile(rDist('client/' + polyfillName), 'utf-8')
|
||||||
|
|
||||||
// @vitejs/plugin-legacy uses SystemJS which need to call `System.import` to load modules
|
// @vitejs/plugin-legacy uses SystemJS which need to call `System.import` to load modules
|
||||||
const clientImports = initialJs.filter(id => id !== polyfillName)
|
const clientImports = initialJs.filter(id => id !== polyfillName)
|
||||||
const clientEntryCode = `var imports = ${JSON.stringify(clientImports)}\nimports.reduce((p, id) => p.then(() => System.import(id)), Promise.resolve())`
|
const clientEntryCode = [
|
||||||
|
polyfill,
|
||||||
|
'var appConfig = window?.__NUXT__?.config.app || {}',
|
||||||
|
'var publicBase = appConfig.cdnURL || ("." + appConfig.baseURL)',
|
||||||
|
`var imports = ${JSON.stringify(clientImports)};`,
|
||||||
|
'imports.reduce((p, id) => p.then(() => System.import(publicBase + appConfig.buildAssetsDir.slice(1) + id)), Promise.resolve())'
|
||||||
|
].join('\n')
|
||||||
const clientEntryName = 'entry-legacy.' + hash(clientEntryCode) + '.js'
|
const clientEntryName = 'entry-legacy.' + hash(clientEntryCode) + '.js'
|
||||||
|
|
||||||
const clientManifest = {
|
const clientManifest = {
|
||||||
// This publicPath will be ignored by Nitro and computed dynamically
|
// This publicPath will be ignored by Nitro and computed dynamically
|
||||||
publicPath: ctx.nuxt.options.app.buildAssetsDir,
|
publicPath: ctx.nuxt.options.app.buildAssetsDir,
|
||||||
all: uniq([
|
all: uniq([
|
||||||
polyfillName,
|
|
||||||
clientEntryName,
|
clientEntryName,
|
||||||
...clientEntries.flatMap(getModuleIds)
|
...clientEntries.flatMap(getModuleIds)
|
||||||
]).filter(Boolean),
|
]).filter(Boolean),
|
||||||
initial: [
|
initial: [
|
||||||
polyfillName,
|
|
||||||
clientEntryName,
|
clientEntryName,
|
||||||
...initialAssets
|
...initialAssets
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { logger, addPluginTemplate, defineNuxtModule } from '@nuxt/kit'
|
import { logger, addPluginTemplate, defineNuxtModule, addTemplate } from '@nuxt/kit'
|
||||||
|
import { publicPathTemplate, clientConfigTemplate } from '../../../nuxt3/src/core/templates'
|
||||||
import { version } from '../../package.json'
|
import { version } from '../../package.json'
|
||||||
import { middlewareTemplate, storeTemplate } from './templates'
|
import { middlewareTemplate, storeTemplate } from './templates'
|
||||||
import type { ViteOptions } from './types'
|
import type { ViteOptions } from './types'
|
||||||
@ -43,6 +44,12 @@ export default defineNuxtModule<ViteOptions>({
|
|||||||
}
|
}
|
||||||
addPluginTemplate(middlewareTemplate)
|
addPluginTemplate(middlewareTemplate)
|
||||||
|
|
||||||
|
addTemplate(clientConfigTemplate)
|
||||||
|
addTemplate({
|
||||||
|
...publicPathTemplate,
|
||||||
|
options: { nuxt }
|
||||||
|
})
|
||||||
|
|
||||||
nuxt.hook('builder:prepared', async (builder) => {
|
nuxt.hook('builder:prepared', async (builder) => {
|
||||||
if (nuxt.options._prepare) { return }
|
if (nuxt.options._prepare) { return }
|
||||||
builder.bundleBuilder.close()
|
builder.bundleBuilder.close()
|
||||||
|
@ -45,7 +45,11 @@ export async function buildServer (ctx: ViteBuildContext) {
|
|||||||
'axios'
|
'axios'
|
||||||
],
|
],
|
||||||
noExternal: [
|
noExternal: [
|
||||||
|
// TODO: Use externality for production (rollup) build
|
||||||
|
/\/esm\/.*\.js$/,
|
||||||
/\.(es|esm|esm-browser|esm-bundler).js$/,
|
/\.(es|esm|esm-browser|esm-bundler).js$/,
|
||||||
|
'#app',
|
||||||
|
/@nuxt\/nitro\/(dist|src)/,
|
||||||
...ctx.nuxt.options.build.transpile.filter(i => typeof i === 'string')
|
...ctx.nuxt.options.build.transpile.filter(i => typeof i === 'string')
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -54,11 +58,14 @@ export async function buildServer (ctx: ViteBuildContext) {
|
|||||||
ssr: ctx.nuxt.options.ssr ?? true,
|
ssr: ctx.nuxt.options.ssr ?? true,
|
||||||
ssrManifest: true,
|
ssrManifest: true,
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
|
// Private nitro alias: packages/nitro/src/rollup/config.ts#L234
|
||||||
|
external: ['#_config'],
|
||||||
input: resolve(ctx.nuxt.options.buildDir, 'server.js'),
|
input: resolve(ctx.nuxt.options.buildDir, 'server.js'),
|
||||||
output: {
|
output: {
|
||||||
format: 'esm',
|
|
||||||
entryFileNames: 'server.mjs',
|
entryFileNames: 'server.mjs',
|
||||||
chunkFileNames: 'chunks/[name].mjs'
|
chunkFileNames: 'chunks/[name].mjs',
|
||||||
|
preferConst: true,
|
||||||
|
format: 'module'
|
||||||
},
|
},
|
||||||
onwarn (warning, rollupWarn) {
|
onwarn (warning, rollupWarn) {
|
||||||
if (!['UNUSED_EXTERNAL_IMPORT'].includes(warning.code)) {
|
if (!['UNUSED_EXTERNAL_IMPORT'].includes(warning.code)) {
|
||||||
@ -67,6 +74,10 @@ export async function buildServer (ctx: ViteBuildContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
server: {
|
||||||
|
// https://github.com/vitest-dev/vitest/issues/229#issuecomment-1002685027
|
||||||
|
preTransformRequests: false
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
jsxPlugin(),
|
jsxPlugin(),
|
||||||
vuePlugin
|
vuePlugin
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import { resolve } from 'pathe'
|
import { resolve } from 'pathe'
|
||||||
import * as vite from 'vite'
|
import * as vite from 'vite'
|
||||||
import { logger } from '@nuxt/kit'
|
import { isIgnored, logger } from '@nuxt/kit'
|
||||||
import { withoutLeadingSlash } from 'ufo'
|
import { sanitizeFilePath } from 'mlly'
|
||||||
|
import { getPort } from 'get-port-please'
|
||||||
|
import { joinURL, withoutLeadingSlash } from 'ufo'
|
||||||
import { distDir } from '../dirs'
|
import { distDir } from '../dirs'
|
||||||
import { warmupViteServer } from '../../../vite/src/utils/warmup'
|
import { warmupViteServer } from '../../../vite/src/utils/warmup'
|
||||||
|
import { DynamicBasePlugin } from '../../../vite/src/plugins/dynamic-base'
|
||||||
import { buildClient } from './client'
|
import { buildClient } from './client'
|
||||||
import { buildServer } from './server'
|
import { buildServer } from './server'
|
||||||
import { defaultExportPlugin } from './plugins/default-export'
|
import { defaultExportPlugin } from './plugins/default-export'
|
||||||
@ -18,20 +21,43 @@ async function bundle (nuxt: Nuxt, builder: any) {
|
|||||||
p.src = nuxt.resolver.resolvePath(resolve(nuxt.options.buildDir, p.src))
|
p.src = nuxt.resolver.resolvePath(resolve(nuxt.options.buildDir, p.src))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hmrPortDefault = 24678 // Vite's default HMR port
|
||||||
|
const hmrPort = await getPort({
|
||||||
|
port: hmrPortDefault,
|
||||||
|
ports: Array.from({ length: 20 }, (_, i) => hmrPortDefault + 1 + i)
|
||||||
|
})
|
||||||
|
|
||||||
const ctx: ViteBuildContext = {
|
const ctx: ViteBuildContext = {
|
||||||
nuxt,
|
nuxt,
|
||||||
builder,
|
builder,
|
||||||
config: vite.mergeConfig(
|
config: vite.mergeConfig(
|
||||||
{
|
{
|
||||||
root: nuxt.options.rootDir,
|
// defaults from packages/schema/src/config/vite
|
||||||
|
root: nuxt.options.srcDir,
|
||||||
mode: nuxt.options.dev ? 'development' : 'production',
|
mode: nuxt.options.dev ? 'development' : 'production',
|
||||||
logLevel: 'warn',
|
logLevel: 'warn',
|
||||||
|
base: nuxt.options.dev
|
||||||
|
? joinURL(nuxt.options.app.baseURL, nuxt.options.app.buildAssetsDir)
|
||||||
|
: '/__NUXT_BASE__/',
|
||||||
|
publicDir: resolve(nuxt.options.rootDir, nuxt.options.srcDir, nuxt.options.dir.static),
|
||||||
|
vue: {
|
||||||
|
isProduction: !nuxt.options.dev,
|
||||||
|
template: {
|
||||||
|
compilerOptions: nuxt.options.vue.compilerOptions
|
||||||
|
}
|
||||||
|
},
|
||||||
|
esbuild: {
|
||||||
|
jsxFactory: 'h',
|
||||||
|
jsxFragment: 'Fragment',
|
||||||
|
tsconfigRaw: '{}'
|
||||||
|
},
|
||||||
|
clearScreen: false,
|
||||||
define: {
|
define: {
|
||||||
|
'process.dev': nuxt.options.dev,
|
||||||
'process.static': nuxt.options.target === 'static',
|
'process.static': nuxt.options.target === 'static',
|
||||||
'process.env.NODE_ENV': JSON.stringify(nuxt.options.dev ? 'development' : 'production'),
|
'process.env.NODE_ENV': JSON.stringify(nuxt.options.dev ? 'development' : 'production'),
|
||||||
'process.mode': JSON.stringify(nuxt.options.dev ? 'development' : 'production'),
|
'process.mode': JSON.stringify(nuxt.options.dev ? 'development' : 'production'),
|
||||||
'process.target': JSON.stringify(nuxt.options.target),
|
'process.target': JSON.stringify(nuxt.options.target)
|
||||||
'process.dev': nuxt.options.dev
|
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
|
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
|
||||||
@ -39,22 +65,17 @@ async function bundle (nuxt: Nuxt, builder: any) {
|
|||||||
...nuxt.options.alias,
|
...nuxt.options.alias,
|
||||||
'#build': nuxt.options.buildDir,
|
'#build': nuxt.options.buildDir,
|
||||||
'.nuxt': nuxt.options.buildDir,
|
'.nuxt': nuxt.options.buildDir,
|
||||||
'/.nuxt/entry.mjs': resolve(nuxt.options.buildDir, 'client.js'),
|
'/entry.mjs': resolve(nuxt.options.buildDir, 'client.js'),
|
||||||
'web-streams-polyfill/ponyfill/es2018': resolve(distDir, 'runtime/vite/mock/web-streams-polyfill.mjs'),
|
'web-streams-polyfill/ponyfill/es2018': resolve(distDir, 'runtime/vite/mock/web-streams-polyfill.mjs'),
|
||||||
'whatwg-url': resolve(distDir, 'runtime/vite/mock/whatwg-url.mjs'),
|
'whatwg-url': resolve(distDir, 'runtime/vite/mock/whatwg-url.mjs'),
|
||||||
// Cannot destructure property 'AbortController' of ..
|
// Cannot destructure property 'AbortController' of ..
|
||||||
'abort-controller': resolve(distDir, 'runtime/vite/mock/abort-controller.mjs')
|
'abort-controller': resolve(distDir, 'runtime/vite/mock/abort-controller.mjs')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
vue: {},
|
|
||||||
server: {
|
|
||||||
fs: {
|
|
||||||
strict: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
css: resolveCSSOptions(nuxt),
|
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
exclude: [
|
exclude: [
|
||||||
|
...nuxt.options.build.transpile.filter(i => typeof i === 'string'),
|
||||||
|
'vue-demi',
|
||||||
'ufo',
|
'ufo',
|
||||||
'date-fns',
|
'date-fns',
|
||||||
'nanoid',
|
'nanoid',
|
||||||
@ -64,26 +85,42 @@ async function bundle (nuxt: Nuxt, builder: any) {
|
|||||||
// 'vue-demi'
|
// 'vue-demi'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
esbuild: {
|
css: resolveCSSOptions(nuxt),
|
||||||
jsxFactory: 'h',
|
|
||||||
jsxFragment: 'Fragment',
|
|
||||||
tsconfigRaw: '{}'
|
|
||||||
},
|
|
||||||
publicDir: resolve(nuxt.options.srcDir, nuxt.options.dir.static),
|
|
||||||
clearScreen: false,
|
|
||||||
build: {
|
build: {
|
||||||
assetsDir: withoutLeadingSlash(nuxt.options.app.buildAssetsDir),
|
assetsDir: nuxt.options.dev ? withoutLeadingSlash(nuxt.options.app.buildAssetsDir) : '.',
|
||||||
emptyOutDir: false
|
emptyOutDir: false,
|
||||||
|
rollupOptions: {
|
||||||
|
output: { sanitizeFileName: sanitizeFilePath }
|
||||||
|
}
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
replace({
|
replace({
|
||||||
__webpack_public_path__: 'globalThis.__webpack_public_path__'
|
__webpack_public_path__: 'globalThis.__webpack_public_path__'
|
||||||
}),
|
}),
|
||||||
jsxPlugin(),
|
jsxPlugin(),
|
||||||
|
DynamicBasePlugin.vite(),
|
||||||
defaultExportPlugin()
|
defaultExportPlugin()
|
||||||
|
],
|
||||||
|
server: {
|
||||||
|
watch: {
|
||||||
|
ignored: isIgnored
|
||||||
|
},
|
||||||
|
hmr: {
|
||||||
|
clientPort: hmrPort,
|
||||||
|
port: hmrPort
|
||||||
|
},
|
||||||
|
fs: {
|
||||||
|
strict: false,
|
||||||
|
allow: [
|
||||||
|
nuxt.options.buildDir,
|
||||||
|
nuxt.options.srcDir,
|
||||||
|
nuxt.options.rootDir,
|
||||||
|
...nuxt.options.modulesDir
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
} as ViteOptions,
|
} as ViteOptions,
|
||||||
nuxt.options.vite || {}
|
nuxt.options.vite
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ 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, RelativeAssetPlugin } from './plugins/dynamic-base'
|
import { RelativeAssetPlugin } from './plugins/dynamic-base'
|
||||||
import { viteNodePlugin } from './vite-node'
|
import { viteNodePlugin } from './vite-node'
|
||||||
|
|
||||||
export async function buildClient (ctx: ViteBuildContext) {
|
export async function buildClient (ctx: ViteBuildContext) {
|
||||||
@ -41,7 +41,6 @@ export async function buildClient (ctx: ViteBuildContext) {
|
|||||||
cacheDirPlugin(ctx.nuxt.options.rootDir, 'client'),
|
cacheDirPlugin(ctx.nuxt.options.rootDir, 'client'),
|
||||||
vuePlugin(ctx.config.vue),
|
vuePlugin(ctx.config.vue),
|
||||||
viteJsxPlugin(),
|
viteJsxPlugin(),
|
||||||
DynamicBasePlugin.vite({ env: 'client', devAppConfig: ctx.nuxt.options.app }),
|
|
||||||
RelativeAssetPlugin(),
|
RelativeAssetPlugin(),
|
||||||
devStyleSSRPlugin({
|
devStyleSSRPlugin({
|
||||||
rootDir: ctx.nuxt.options.rootDir,
|
rootDir: ctx.nuxt.options.rootDir,
|
||||||
|
@ -4,8 +4,6 @@ import type { Plugin } from 'vite'
|
|||||||
import MagicString from 'magic-string'
|
import MagicString from 'magic-string'
|
||||||
|
|
||||||
interface DynamicBasePluginOptions {
|
interface DynamicBasePluginOptions {
|
||||||
env: 'dev' | 'server' | 'client'
|
|
||||||
devAppConfig?: Record<string, any>
|
|
||||||
globalPublicPath?: string
|
globalPublicPath?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,6 +16,15 @@ export const RelativeAssetPlugin = function (): Plugin {
|
|||||||
|
|
||||||
for (const file in bundle) {
|
for (const file in bundle) {
|
||||||
const asset = bundle[file]
|
const asset = bundle[file]
|
||||||
|
if (asset.fileName.includes('legacy') && asset.type === 'chunk' && asset.code.includes('innerHTML')) {
|
||||||
|
for (const delimiter of ['`', '"', "'"]) {
|
||||||
|
asset.code = asset.code.replace(
|
||||||
|
new RegExp(`(?<=innerHTML=)${delimiter}([^${delimiter}]*)\\/__NUXT_BASE__\\/([^${delimiter}]*)${delimiter}`, 'g'),
|
||||||
|
/* eslint-disable-next-line no-template-curly-in-string */
|
||||||
|
'`$1${(window?.__NUXT__?.config.app.cdnURL || window?.__NUXT__?.config.app.baseURL) + window?.__NUXT__?.config.app.buildAssetsDir.slice(1)}$2`'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
if (asset.type === 'asset' && typeof asset.source === 'string' && asset.fileName.endsWith('.css')) {
|
if (asset.type === 'asset' && typeof asset.source === 'string' && asset.fileName.endsWith('.css')) {
|
||||||
const depth = file.split('/').length - 1
|
const depth = file.split('/').length - 1
|
||||||
const assetBase = depth === 0 ? '.' : Array.from({ length: depth }).map(() => '..').join('/')
|
const assetBase = depth === 0 ? '.' : Array.from({ length: depth }).map(() => '..').join('/')
|
||||||
@ -33,7 +40,7 @@ export const RelativeAssetPlugin = function (): Plugin {
|
|||||||
|
|
||||||
const VITE_ASSET_RE = /^export default ["'](__VITE_ASSET.*)["']$/
|
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',
|
||||||
resolveId (id) {
|
resolveId (id) {
|
||||||
|
@ -10,7 +10,6 @@ import { ViteBuildContext, ViteOptions } from './vite'
|
|||||||
import { wpfs } from './utils/wpfs'
|
import { wpfs } from './utils/wpfs'
|
||||||
import { cacheDirPlugin } from './plugins/cache-dir'
|
import { cacheDirPlugin } from './plugins/cache-dir'
|
||||||
import { prepareDevServerEntry } from './vite-node'
|
import { prepareDevServerEntry } from './vite-node'
|
||||||
import { DynamicBasePlugin } from './plugins/dynamic-base'
|
|
||||||
import { isCSS, isDirectory, readDirRecursively } from './utils'
|
import { isCSS, isDirectory, readDirRecursively } from './utils'
|
||||||
import { bundleRequest } from './dev-bundler'
|
import { bundleRequest } from './dev-bundler'
|
||||||
import { writeManifest } from './manifest'
|
import { writeManifest } from './manifest'
|
||||||
@ -76,7 +75,6 @@ export async function buildServer (ctx: ViteBuildContext) {
|
|||||||
plugins: [
|
plugins: [
|
||||||
cacheDirPlugin(ctx.nuxt.options.rootDir, 'server'),
|
cacheDirPlugin(ctx.nuxt.options.rootDir, 'server'),
|
||||||
vuePlugin(ctx.config.vue),
|
vuePlugin(ctx.config.vue),
|
||||||
DynamicBasePlugin.vite({ env: ctx.nuxt.options.dev ? 'dev' : 'server', devAppConfig: ctx.nuxt.options.app }),
|
|
||||||
viteJsxPlugin()
|
viteJsxPlugin()
|
||||||
]
|
]
|
||||||
} as ViteOptions)
|
} as ViteOptions)
|
||||||
|
@ -9,6 +9,7 @@ import { getPort } from 'get-port-please'
|
|||||||
import { buildClient } from './client'
|
import { buildClient } from './client'
|
||||||
import { buildServer } from './server'
|
import { buildServer } from './server'
|
||||||
import virtual from './plugins/virtual'
|
import virtual from './plugins/virtual'
|
||||||
|
import { DynamicBasePlugin } from './plugins/dynamic-base'
|
||||||
import { warmupViteServer } from './utils/warmup'
|
import { warmupViteServer } from './utils/warmup'
|
||||||
import { resolveCSSOptions } from './css'
|
import { resolveCSSOptions } from './css'
|
||||||
|
|
||||||
@ -25,7 +26,6 @@ export interface ViteBuildContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function bundle (nuxt: Nuxt) {
|
export async function bundle (nuxt: Nuxt) {
|
||||||
// TODO: After nitropack refactor, try if we can resuse the same server port as Nuxt
|
|
||||||
const hmrPortDefault = 24678 // Vite's default HMR port
|
const hmrPortDefault = 24678 // Vite's default HMR port
|
||||||
const hmrPort = await getPort({
|
const hmrPort = await getPort({
|
||||||
port: hmrPortDefault,
|
port: hmrPortDefault,
|
||||||
@ -64,7 +64,8 @@ export async function bundle (nuxt: Nuxt) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
virtual(nuxt.vfs)
|
virtual(nuxt.vfs),
|
||||||
|
DynamicBasePlugin.vite()
|
||||||
],
|
],
|
||||||
vue: {
|
vue: {
|
||||||
reactivityTransform: nuxt.options.experimental.reactivityTransform
|
reactivityTransform: nuxt.options.experimental.reactivityTransform
|
||||||
|
@ -34,8 +34,6 @@ export async function bundle (nuxt: Nuxt) {
|
|||||||
// Configure compilers
|
// Configure compilers
|
||||||
const compilers = webpackConfigs.map((config) => {
|
const compilers = webpackConfigs.map((config) => {
|
||||||
config.plugins.push(DynamicBasePlugin.webpack({
|
config.plugins.push(DynamicBasePlugin.webpack({
|
||||||
env: nuxt.options.dev ? 'dev' : config.name as 'client',
|
|
||||||
devAppConfig: nuxt.options.app,
|
|
||||||
globalPublicPath: '__webpack_public_path__'
|
globalPublicPath: '__webpack_public_path__'
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
import { describe, expect, it } from 'vitest'
|
import { describe, expect, it } from 'vitest'
|
||||||
import { setup, $fetch } from '@nuxt/test-utils'
|
import { setup, $fetch, startServer } from '@nuxt/test-utils'
|
||||||
|
|
||||||
describe('fixtures:bridge', async () => {
|
describe('fixtures:bridge', async () => {
|
||||||
await setup({
|
await setup({
|
||||||
@ -23,4 +23,60 @@ describe('fixtures:bridge', async () => {
|
|||||||
expect(html).toContain('Hello Vue 2!')
|
expect(html).toContain('Hello Vue 2!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('dynamic paths', () => {
|
||||||
|
if (process.env.TEST_WITH_WEBPACK) {
|
||||||
|
// TODO:
|
||||||
|
it.todo('work with webpack')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
it('should work with no overrides', async () => {
|
||||||
|
const html = await $fetch('/assets')
|
||||||
|
for (const match of html.matchAll(/(href|src)="(.*?)"/g)) {
|
||||||
|
const url = match[2]
|
||||||
|
expect(url.startsWith('/_nuxt/') || url === '/public.svg').toBeTruthy()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('adds relative paths to CSS', async () => {
|
||||||
|
const html = await $fetch('/assets')
|
||||||
|
const urls = Array.from(html.matchAll(/(href|src)="(.*?)"/g)).map(m => m[2])
|
||||||
|
const cssURL = urls.find(u => /_nuxt\/assets.*\.css$/.test(u))
|
||||||
|
const css = await $fetch(cssURL)
|
||||||
|
const imageUrls = Array.from(css.matchAll(/url\(([^)]*)\)/g)).map(m => m[1].replace(/[-.][\w]{8}\./g, '.'))
|
||||||
|
expect(imageUrls).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
"./logo.svg",
|
||||||
|
"../public.svg",
|
||||||
|
]
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow setting base URL and build assets directory', async () => {
|
||||||
|
process.env.NUXT_APP_BUILD_ASSETS_DIR = '/_other/'
|
||||||
|
process.env.NUXT_APP_BASE_URL = '/foo/'
|
||||||
|
await startServer()
|
||||||
|
|
||||||
|
const html = await $fetch('/assets')
|
||||||
|
for (const match of html.matchAll(/(href|src)="(.*?)"/g)) {
|
||||||
|
const url = match[2]
|
||||||
|
// TODO: should be /foo/public.svg
|
||||||
|
expect(url.startsWith('/foo/_other/') || url === '/public.svg').toBeTruthy()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow setting CDN URL', async () => {
|
||||||
|
process.env.NUXT_APP_BASE_URL = '/foo/'
|
||||||
|
process.env.NUXT_APP_CDN_URL = 'https://example.com/'
|
||||||
|
process.env.NUXT_APP_BUILD_ASSETS_DIR = '/_cdn/'
|
||||||
|
await startServer()
|
||||||
|
|
||||||
|
const html = await $fetch('/assets')
|
||||||
|
for (const match of html.matchAll(/(href|src)="(.*?)"/g)) {
|
||||||
|
const url = match[2]
|
||||||
|
// TODO: should be https://example.com/public.svg
|
||||||
|
expect(url.startsWith('https://example.com/_cdn/') || url === '/public.svg').toBeTruthy()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
18
test/fixtures/bridge/assets/logo.svg
vendored
Normal file
18
test/fixtures/bridge/assets/logo.svg
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<svg viewBox="0 0 221 65" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-8">
|
||||||
|
<g clip-path="url(#a)">
|
||||||
|
<path fill="currentColor"
|
||||||
|
d="M82.5623 18.5705h7.3017l15.474 24.7415V18.5705h6.741v35.0576h-7.252L89.3025 28.938v24.6901h-6.7402V18.5705ZM142.207 53.628h-6.282v-3.916c-1.429 2.7559-4.339 4.3076-8.015 4.3076-5.822 0-9.603-4.1069-9.603-10.0175V28.3847h6.282v14.3251c0 3.4558 2.146 5.8592 5.362 5.8592 3.524 0 5.974-2.7044 5.974-6.4099V28.3847h6.282V53.628ZM164.064 53.2289l-6.026-8.4144-6.027 8.4144h-6.69l9.296-13.1723-8.58-12.0709h6.843l5.158 7.2641 5.106-7.2641h6.895l-8.632 12.0709 9.295 13.1723h-6.638ZM183.469 20.7726v7.6116h7.149v5.1593h-7.149v12.5311c0 .4208.17.8245.473 1.1223.303.2978.715.4654 1.144.4661h5.532v5.9547h-4.137c-5.617 0-9.293-3.2062-9.293-8.8109V33.5484h-5.056v-5.1642h3.172c1.479 0 2.34-.8639 2.34-2.2932v-5.3184h5.825Z">
|
||||||
|
</path>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||||
|
d="M30.1185 11.5456c-1.8853-3.24168-6.5987-3.24169-8.484 0L1.08737 46.8747c-1.885324 3.2417.47133 7.2938 4.24199 7.2938H21.3695c-1.6112-1.4081-2.2079-3.8441-.9886-5.9341l15.5615-26.675-5.8239-10.0138Z"
|
||||||
|
fill="#80EEC0"></path>
|
||||||
|
<path
|
||||||
|
d="M43.1374 19.2952c1.5603-2.6523 5.461-2.6523 7.0212 0l17.0045 28.9057c1.5603 2.6522-.39 5.9676-3.5106 5.9676h-34.009c-3.1206 0-5.0709-3.3154-3.5106-5.9676l17.0045-28.9057ZM209.174 53.8005H198.483c0-1.8514.067-3.4526 0-6.0213h10.641c1.868 0 3.353.1001 4.354-.934 1-1.0341 1.501-2.3351 1.501-3.9029 0-1.8347-.667-3.2191-2.002-4.1532-1.301-.9674-2.985-1.4511-5.054-1.4511h-2.601v-5.2539h2.652c1.701 0 3.119-.4003 4.253-1.2009 1.134-.8006 1.701-1.9849 1.701-3.5527 0-1.301-.434-2.3351-1.301-3.1023-.834-.8007-2.001-1.201-3.503-1.201-1.634 0-2.918.4837-3.853 1.4511-.9.9674-1.401 2.1517-1.501 3.5527h-6.254c.133-3.2358 1.251-5.7877 3.352-7.6558 2.135-1.868 4.887-2.8021 8.256-2.8021 2.402 0 4.42.4337 6.055 1.301 1.668.834 2.919 1.9515 3.753 3.3525.867 1.4011 1.301 2.9523 1.301 4.6536 0 1.9681-.551 3.636-1.651 5.0037-1.068 1.3344-2.402 2.235-4.004 2.7021 1.969.4003 3.57 1.3677 4.804 2.9022 1.234 1.5011 1.852 3.4025 1.852 5.7043 0 1.9347-.468 3.7028-1.402 5.304-.934 1.6012-2.301 2.8855-4.103 3.8529-1.768.9674-3.953 1.4511-6.555 1.4511Z"
|
||||||
|
fill="#00DC82"></path>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="a">
|
||||||
|
<path fill="#fff" d="M0 0h221v65H0z"></path>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
20
test/fixtures/bridge/pages/assets.vue
vendored
Normal file
20
test/fixtures/bridge/pages/assets.vue
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<img src="~/assets/logo.svg" class="h-20 mb-4">
|
||||||
|
<img src="/public.svg" class="h-20 mb-4">
|
||||||
|
<img :src="logo" class="h-20 mb-4">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import logo from '~/assets/logo.svg'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#__nuxt {
|
||||||
|
background-image: url('~/assets/logo.svg');
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background-image: url('/public.svg');
|
||||||
|
}
|
||||||
|
</style>
|
18
test/fixtures/bridge/static/public.svg
vendored
Normal file
18
test/fixtures/bridge/static/public.svg
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<svg viewBox="0 0 221 65" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-8">
|
||||||
|
<g clip-path="url(#a)">
|
||||||
|
<path fill="currentColor"
|
||||||
|
d="M82.5623 18.5705h7.3017l15.474 24.7415V18.5705h6.741v35.0576h-7.252L89.3025 28.938v24.6901h-6.7402V18.5705ZM142.207 53.628h-6.282v-3.916c-1.429 2.7559-4.339 4.3076-8.015 4.3076-5.822 0-9.603-4.1069-9.603-10.0175V28.3847h6.282v14.3251c0 3.4558 2.146 5.8592 5.362 5.8592 3.524 0 5.974-2.7044 5.974-6.4099V28.3847h6.282V53.628ZM164.064 53.2289l-6.026-8.4144-6.027 8.4144h-6.69l9.296-13.1723-8.58-12.0709h6.843l5.158 7.2641 5.106-7.2641h6.895l-8.632 12.0709 9.295 13.1723h-6.638ZM183.469 20.7726v7.6116h7.149v5.1593h-7.149v12.5311c0 .4208.17.8245.473 1.1223.303.2978.715.4654 1.144.4661h5.532v5.9547h-4.137c-5.617 0-9.293-3.2062-9.293-8.8109V33.5484h-5.056v-5.1642h3.172c1.479 0 2.34-.8639 2.34-2.2932v-5.3184h5.825Z">
|
||||||
|
</path>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||||
|
d="M30.1185 11.5456c-1.8853-3.24168-6.5987-3.24169-8.484 0L1.08737 46.8747c-1.885324 3.2417.47133 7.2938 4.24199 7.2938H21.3695c-1.6112-1.4081-2.2079-3.8441-.9886-5.9341l15.5615-26.675-5.8239-10.0138Z"
|
||||||
|
fill="#80EEC0"></path>
|
||||||
|
<path
|
||||||
|
d="M43.1374 19.2952c1.5603-2.6523 5.461-2.6523 7.0212 0l17.0045 28.9057c1.5603 2.6522-.39 5.9676-3.5106 5.9676h-34.009c-3.1206 0-5.0709-3.3154-3.5106-5.9676l17.0045-28.9057ZM209.174 53.8005H198.483c0-1.8514.067-3.4526 0-6.0213h10.641c1.868 0 3.353.1001 4.354-.934 1-1.0341 1.501-2.3351 1.501-3.9029 0-1.8347-.667-3.2191-2.002-4.1532-1.301-.9674-2.985-1.4511-5.054-1.4511h-2.601v-5.2539h2.652c1.701 0 3.119-.4003 4.253-1.2009 1.134-.8006 1.701-1.9849 1.701-3.5527 0-1.301-.434-2.3351-1.301-3.1023-.834-.8007-2.001-1.201-3.503-1.201-1.634 0-2.918.4837-3.853 1.4511-.9.9674-1.401 2.1517-1.501 3.5527h-6.254c.133-3.2358 1.251-5.7877 3.352-7.6558 2.135-1.868 4.887-2.8021 8.256-2.8021 2.402 0 4.42.4337 6.055 1.301 1.668.834 2.919 1.9515 3.753 3.3525.867 1.4011 1.301 2.9523 1.301 4.6536 0 1.9681-.551 3.636-1.651 5.0037-1.068 1.3344-2.402 2.235-4.004 2.7021 1.969.4003 3.57 1.3677 4.804 2.9022 1.234 1.5011 1.852 3.4025 1.852 5.7043 0 1.9347-.468 3.7028-1.402 5.304-.934 1.6012-2.301 2.8855-4.103 3.8529-1.768.9674-3.953 1.4511-6.555 1.4511Z"
|
||||||
|
fill="#00DC82"></path>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="a">
|
||||||
|
<path fill="#fff" d="M0 0h221v65H0z"></path>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
Loading…
Reference in New Issue
Block a user