From 1e1d7c58177ebc73413bc176ff87a15fcc2240a9 Mon Sep 17 00:00:00 2001 From: patak-dev Date: Thu, 2 Jun 2022 22:24:20 +0200 Subject: [PATCH 01/12] feat: build.baseOptions (dynamic base support) --- packages/plugin-legacy/src/index.ts | 17 +- packages/plugin-react/src/index.ts | 6 +- packages/plugin-vue/src/template.ts | 3 +- packages/vite/src/node/build.ts | 107 +++++++- packages/vite/src/node/config.ts | 45 +++- packages/vite/src/node/logger.ts | 9 +- packages/vite/src/node/plugins/asset.ts | 58 +++-- .../vite/src/node/plugins/clientInjections.ts | 5 +- packages/vite/src/node/plugins/css.ts | 37 +-- packages/vite/src/node/plugins/html.ts | 53 ++-- .../src/node/plugins/importAnalysisBuild.ts | 20 +- packages/vite/src/node/plugins/worker.ts | 42 ++-- packages/vite/src/node/preview.ts | 8 +- packages/vite/src/node/server/index.ts | 7 +- .../vite/src/node/server/middlewares/base.ts | 12 +- .../src/node/server/middlewares/indexHtml.ts | 7 +- .../vite/src/node/ssr/ssrManifestPlugin.ts | 4 +- packages/vite/src/node/utils.ts | 4 - .../dynamic-base/dynamic-base-assets.spec.ts | 235 ++++++++++++++++++ .../__tests__/dynamic-base/vite.config.js | 1 + playground/assets/package.json | 5 +- playground/assets/vite.config-dynamic-base.js | 56 +++++ playground/lib/__tests__/serve.ts | 4 +- playground/vitestSetup.ts | 13 +- 24 files changed, 615 insertions(+), 143 deletions(-) create mode 100644 playground/assets/__tests__/dynamic-base/dynamic-base-assets.spec.ts create mode 100644 playground/assets/__tests__/dynamic-base/vite.config.js create mode 100644 playground/assets/vite.config-dynamic-base.js diff --git a/packages/plugin-legacy/src/index.ts b/packages/plugin-legacy/src/index.ts index 05e276ca3b1ff8..a392820da8e6bd 100644 --- a/packages/plugin-legacy/src/index.ts +++ b/packages/plugin-legacy/src/index.ts @@ -31,6 +31,16 @@ async function loadBabel() { return babel } +// TODO:base +function toAssetPathFromHtml(filename: string, config: ResolvedConfig): string { + const nonBareBase = config.base === '' ? './' : config.base + return nonBareBase + filename + /* + const { baseOptions } = config.build.baseOptions + return baseOptions.relative ? 'TODO:base' : `${base.assets}${filename}` + */ +} + // https://gist.github.com/samthor/64b114e4a4f539915a95b91ffd340acc // DO NOT ALTER THIS CONTENT const safari10NoModuleFix = `!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();` @@ -360,7 +370,7 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { tag: 'script', attrs: { type: 'module', - src: `${config.base}${modernPolyfillFilename}` + src: toAssetPathFromHtml(modernPolyfillFilename, config) } }) } else if (modernPolyfills.size) { @@ -391,7 +401,7 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { attrs: { nomodule: true, id: legacyPolyfillId, - src: `${config.base}${legacyPolyfillFilename}` + src: toAssetPathFromHtml(legacyPolyfillFilename, config) }, injectTo: 'body' }) @@ -407,7 +417,6 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { ) if (legacyEntryFilename) { // `assets/foo.js` means importing "named register" in SystemJS - const nonBareBase = config.base === '' ? './' : config.base tags.push({ tag: 'script', attrs: { @@ -416,7 +425,7 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { // script content will stay consistent - which allows using a constant // hash value for CSP. id: legacyEntryId, - 'data-src': nonBareBase + legacyEntryFilename + 'data-src': toAssetPathFromHtml(legacyEntryFilename, config) }, children: systemJSInlineCode, injectTo: 'body' diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index 562b8291112297..f140a69bdf841d 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -91,7 +91,7 @@ declare module 'vite' { export default function viteReact(opts: Options = {}): PluginOption[] { // Provide default values for Rollup compat. - let base = '/' + let devBase = '/' let resolvedCacheDir: string let filter = createFilter(opts.include, opts.exclude) let isProduction = true @@ -119,7 +119,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] { name: 'vite:react-babel', enforce: 'pre', configResolved(config) { - base = config.base + devBase = config.base projectRoot = config.root resolvedCacheDir = normalizePath(path.resolve(config.cacheDir)) filter = createFilter(opts.include, opts.exclude, { @@ -355,7 +355,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] { { tag: 'script', attrs: { type: 'module' }, - children: preambleCode.replace(`__BASE__`, base) + children: preambleCode.replace(`__BASE__`, devBase) } ] } diff --git a/packages/plugin-vue/src/template.ts b/packages/plugin-vue/src/template.ts index 6fcbefa056fefe..ad71fbece848ab 100644 --- a/packages/plugin-vue/src/template.ts +++ b/packages/plugin-vue/src/template.ts @@ -116,10 +116,11 @@ export function resolveTemplateCompilerOptions( // relative paths directly to absolute paths without incurring an extra import // request if (filename.startsWith(options.root)) { + const devBase = options.devServer.config.base assetUrlOptions = { base: (options.devServer.config.server?.origin ?? '') + - options.devServer.config.base + + devBase + slash(path.relative(options.root, path.dirname(filename))) } } diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index 705465400ca5ca..59db3f2848399a 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -22,7 +22,7 @@ import type { RollupCommonJSOptions } from 'types/commonjs' import type { RollupDynamicImportVarsOptions } from 'types/dynamicImportVars' import type { TransformOptions } from 'esbuild' import type { InlineConfig, ResolvedConfig } from './config' -import { isDepsOptimizerEnabled, resolveConfig } from './config' +import { isDepsOptimizerEnabled, resolveBaseUrl, resolveConfig } from './config' import { buildReporterPlugin } from './plugins/reporter' import { buildEsbuildPlugin } from './plugins/esbuild' import { terserPlugin } from './plugins/terser' @@ -49,6 +49,53 @@ import { watchPackageDataPlugin } from './packages' import { ensureWatchPlugin } from './plugins/ensureWatch' import { VERSION } from './constants' +export type BuildBasePath = + | string + | { url?: string; dynamic?: (filename: string) => string } + +export function getBuildBasePathUrl( + basePath: BuildBasePath | undefined, + config: ResolvedConfig +): string | undefined { + let baseUrl = + basePath && (typeof basePath === 'string' ? basePath : basePath?.url) + if (!baseUrl && config.base !== './' && config.base !== '') { + // Default non-relative base + baseUrl = config.base + } + return baseUrl +} + +export interface BuildBaseOptions { + /** + * Relative base. If true, every generated URL is relative and the dist folder + * can be deployed to any base or subdomain. Use this option when the base + * is unkown at build time + * @default false + */ + relative?: boolean + /** + * Base for assets and public files paths when served in production + */ + assets?: BuildBasePath + public?: BuildBasePath + /** + * If defined, these functions will be called for assets and public files + * paths which are generated in JS assets. Examples: + * + * assets: { dynamic: (url: string) => `window.__assetsPath(${url})` } + * public: { dynamic: (url: string) => `window.__publicPath + ${url}` } + * + * For assets and public files paths in CSS or HTML, the corresponding + * `assets.url` and `public.url` base urls or global base will be used. + * + * When using relative base, the assets.dynamic function isn't needed as + * all the asset paths will be computed using import.meta.url + * The public.dynamic function is still useful if the public files aren't + * deployed in the same base as the hashed assets + */ +} + export interface BuildOptions { /** * Compatibility transform target. The transform is performed with esbuild @@ -85,6 +132,10 @@ export interface BuildOptions { * @default 'assets' */ assetsDir?: string + /** + * Build base options. + */ + baseOptions?: BuildBaseOptions /** * Static asset files smaller than this number (in bytes) will be inlined as * base64 strings. Default limit is `4096` (4kb). Set to `0` to disable. @@ -229,7 +280,11 @@ export type LibraryFormats = 'es' | 'cjs' | 'umd' | 'iife' export type ResolvedBuildOptions = Required -export function resolveBuildOptions(raw?: BuildOptions): ResolvedBuildOptions { +export function resolveBuildOptions( + raw: BuildOptions | undefined, + isBuild: boolean, + logger: Logger +): ResolvedBuildOptions { const resolved: ResolvedBuildOptions = { target: 'modules', polyfillModulePreload: true, @@ -261,7 +316,8 @@ export function resolveBuildOptions(raw?: BuildOptions): ResolvedBuildOptions { warnOnError: true, exclude: [/node_modules/], ...raw?.dynamicImportVarsOptions - } + }, + baseOptions: resolveBuildBaseOptions(raw?.baseOptions, isBuild, logger) } // handle special build targets @@ -825,3 +881,48 @@ function injectSsrFlag>( ): T & { ssr: boolean } { return { ...(options ?? {}), ssr: true } as T & { ssr: boolean } } + +/** + * Resolve base. Note that some users use Vite to build for non-web targets like + * electron or expects to deploy + */ +function resolveBuildBaseOptions( + baseOptions: BuildBaseOptions | undefined, + isBuild: boolean, + logger: Logger +): BuildBaseOptions { + baseOptions ??= {} + const relative = !!baseOptions?.relative + if (relative && !isBuild) { + return { + relative: true + } + } + return { + relative, + assets: resolveBuildBasePath( + baseOptions?.assets, + isBuild, + logger, + 'build.baseOptions.assets' + ), + public: resolveBuildBasePath( + baseOptions?.public, + isBuild, + logger, + 'build.baseOptions.public' + ) + } +} + +function resolveBuildBasePath( + path: BuildBasePath | undefined, + isBuild: boolean, + logger: Logger, + optionName: string +): BuildBasePath | undefined { + if (typeof path === 'string') { + return resolveBaseUrl(path, isBuild, logger, optionName) + } + return path +} diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index d80f5a60583abc..13d3a4ae6e7a80 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -44,6 +44,8 @@ import { loadEnv, resolveEnvPrefix } from './env' const debug = createDebugger('vite:config') +export type { BuildBaseOptions, BuildBasePath } from './build' + // NOTE: every export in this file is re-exported from ./index.ts so it will // be part of the public API. export interface ConfigEnv { @@ -427,8 +429,24 @@ export async function resolveConfig( } // resolve public base url - const BASE_URL = resolveBaseUrl(config.base, command === 'build', logger) - const resolvedBuildOptions = resolveBuildOptions(config.build) + const isBuild = command === 'build' + const resolvedBuildOptions = resolveBuildOptions( + config.build, + isBuild, + logger + ) + const relativeBaseShortcut = config.base === '' || config.base === './' + // TODO:base should we deprecate the relative base shortcut? + const base = relativeBaseShortcut && !isBuild ? '/' : config.base ?? '/' + let resolvedBase = relativeBaseShortcut + ? base + : resolveBaseUrl(base, isBuild, logger) + if (relativeBaseShortcut && isBuild) { + resolvedBuildOptions.baseOptions.relative = true + } + if (resolvedBuildOptions.baseOptions.relative && config.base === undefined) { + resolvedBase = './' + } // resolve cache directory const pkgPath = lookupFile(resolvedRoot, [`package.json`], { pathOnly: true }) @@ -494,6 +512,8 @@ export async function resolveConfig( const optimizeDeps = config.optimizeDeps || {} + const BASE_URL = resolvedBase + const resolved: ResolvedConfig = { ...config, configFile: configFile ? normalizePath(configFile) : undefined, @@ -502,7 +522,7 @@ export async function resolveConfig( ), inlineConfig, root: resolvedRoot, - base: BASE_URL, + base: resolvedBase, resolve: resolveOptions, publicDir: resolvedPublicDir, cacheDir, @@ -588,23 +608,20 @@ export async function resolveConfig( } /** - * Resolve base. Note that some users use Vite to build for non-web targets like + * Resolve base url. Note that some users use Vite to build for non-web targets like * electron or expects to deploy */ -function resolveBaseUrl( +export function resolveBaseUrl( base: UserConfig['base'] = '/', isBuild: boolean, - logger: Logger + logger: Logger, + optionName: string = 'base' ): string { - // #1669 special treatment for empty for same dir relative base - if (base === '' || base === './') { - return isBuild ? base : '/' - } if (base.startsWith('.')) { logger.warn( colors.yellow( colors.bold( - `(!) invalid "base" option: ${base}. The value can only be an absolute ` + + `(!) invalid "${optionName}" option: ${base}. The value can only be an absolute ` + `URL, ./, or an empty string.` ) ) @@ -624,7 +641,7 @@ function resolveBaseUrl( if (!base.startsWith('/')) { logger.warn( colors.yellow( - colors.bold(`(!) "base" option should start with a slash.`) + colors.bold(`(!) "${optionName}" option should start with a slash.`) ) ) base = '/' + base @@ -634,7 +651,9 @@ function resolveBaseUrl( // ensure ending slash if (!base.endsWith('/')) { logger.warn( - colors.yellow(colors.bold(`(!) "base" option should end with a slash.`)) + colors.yellow( + colors.bold(`(!) "${optionName}" option should end with a slash.`) + ) ) base += '/' } diff --git a/packages/vite/src/node/logger.ts b/packages/vite/src/node/logger.ts index 1176a265a4fcbe..2db04e59046869 100644 --- a/packages/vite/src/node/logger.ts +++ b/packages/vite/src/node/logger.ts @@ -154,13 +154,8 @@ export function printCommonServerUrls( if (isAddressInfo(address)) { const hostname = resolveHostname(options.host) const protocol = options.https ? 'https' : 'http' - printServerUrls( - hostname, - protocol, - address.port, - config.base, - config.logger.info - ) + const base = config.base === './' || config.base === '' ? '/' : config.base + printServerUrls(hostname, protocol, address.port, base, config.logger.info) } } diff --git a/packages/vite/src/node/plugins/asset.ts b/packages/vite/src/node/plugins/asset.ts index 4c1bcfea0fd50b..209354154a4ae0 100644 --- a/packages/vite/src/node/plugins/asset.ts +++ b/packages/vite/src/node/plugins/asset.ts @@ -4,9 +4,10 @@ import fs, { promises as fsp } from 'fs' import * as mrmime from 'mrmime' import type { OutputOptions, PluginContext } from 'rollup' import MagicString from 'magic-string' +import { getBuildBasePathUrl } from '../build' import type { Plugin } from '../plugin' -import type { ResolvedConfig } from '../config' -import { cleanUrl, getHash, isRelativeBase, normalizePath } from '../utils' +import type { BuildBasePath, ResolvedConfig } from '../config' +import { cleanUrl, getHash, normalizePath } from '../utils' import { FS_PREFIX } from '../constants' export const assetUrlRE = /__VITE_ASSET__([a-z\d]{8})__(?:\$_(.*?)__)?/g @@ -29,7 +30,7 @@ const emittedHashMap = new WeakMap>() export function assetPlugin(config: ResolvedConfig): Plugin { // assetHashToFilenameMap initialization in buildStart causes getAssetFilename to return undefined assetHashToFilenameMap.set(config, new Map()) - const relativeBase = isRelativeBase(config.base) + const { baseOptions } = config.build // add own dictionary entry by directly assigning mrmine // https://github.com/lukeed/mrmime/issues/3 @@ -88,6 +89,19 @@ export function assetPlugin(config: ResolvedConfig): Plugin { path.posix.relative(path.dirname(chunk.fileName), filename) )},import.meta.url).href+"` + const toOutputFilePathInString = ( + filename: string, + basePath: BuildBasePath | undefined + ) => { + const assetsBaseUrl = getBuildBasePathUrl(basePath, config) + const dynamicBase = typeof basePath === 'object' && basePath.dynamic + return dynamicBase + ? `"+${dynamicBase(JSON.stringify(filename))}+"` + : assetsBaseUrl + ? JSON.stringify(assetsBaseUrl + filename).slice(1, -1) + : absoluteUrlPathInterpolation(filename) + } + // Urls added with JS using e.g. // imgElement.src = "__VITE_ASSET__5aa0ddc0__" are using quotes @@ -104,27 +118,29 @@ export function assetPlugin(config: ResolvedConfig): Plugin { const file = getAssetFilename(hash, config) || this.getFileName(hash) chunk.viteMetadata.importedAssets.add(cleanUrl(file)) const filename = file + postfix - const outputFilepath = relativeBase - ? absoluteUrlPathInterpolation(filename) - : JSON.stringify(config.base + filename).slice(1, -1) - s.overwrite(match.index, match.index + full.length, outputFilepath, { + const replacement = toOutputFilePathInString( + filename, + baseOptions.assets + ) + s.overwrite(match.index, match.index + full.length, replacement, { contentOnly: true }) } // Replace __VITE_PUBLIC_ASSET__5aa0ddc0__ with absolute paths - if (relativeBase) { - const publicAssetUrlMap = publicAssetUrlCache.get(config)! - while ((match = publicAssetUrlRE.exec(code))) { - s = s || (s = new MagicString(code)) - const [full, hash] = match - const publicUrl = publicAssetUrlMap.get(hash)! - const replacement = absoluteUrlPathInterpolation(publicUrl.slice(1)) - s.overwrite(match.index, match.index + full.length, replacement, { - contentOnly: true - }) - } + const publicAssetUrlMap = publicAssetUrlCache.get(config)! + while ((match = publicAssetUrlRE.exec(code))) { + s = s || (s = new MagicString(code)) + const [full, hash] = match + const publicUrl = publicAssetUrlMap.get(hash)!.slice(1) + const replacement = toOutputFilePathInString( + publicUrl, + baseOptions.public + ) + s.overwrite(match.index, match.index + full.length, replacement, { + contentOnly: true + }) } if (s) { @@ -196,7 +212,8 @@ function fileToDevUrl(id: string, config: ResolvedConfig) { rtn = path.posix.join(FS_PREFIX + id) } const origin = config.server?.origin ?? '' - return origin + config.base + rtn.replace(/^\//, '') + const devBase = config.base + return origin + devBase + rtn.replace(/^\//, '') } export function getAssetFilename( @@ -294,7 +311,8 @@ export function publicFileToBuiltUrl( url: string, config: ResolvedConfig ): string { - if (!isRelativeBase(config.base)) { + if (config.command !== 'build') { + // We don't need relative base or build.baseOptions support during dev return config.base + url.slice(1) } const hash = getHash(url) diff --git a/packages/vite/src/node/plugins/clientInjections.ts b/packages/vite/src/node/plugins/clientInjections.ts index 84811dfc10df2a..3864f138e34b5c 100644 --- a/packages/vite/src/node/plugins/clientInjections.ts +++ b/packages/vite/src/node/plugins/clientInjections.ts @@ -32,7 +32,8 @@ export function clientInjectionsPlugin(config: ResolvedConfig): Plugin { } else { port = String(port || options.port || config.server.port!) } - let hmrBase = config.base + const devBase = config.base + let hmrBase = devBase if (options.path) { hmrBase = path.posix.join(hmrBase, options.path) } @@ -42,7 +43,7 @@ export function clientInjectionsPlugin(config: ResolvedConfig): Plugin { return code .replace(`__MODE__`, JSON.stringify(config.mode)) - .replace(`__BASE__`, JSON.stringify(config.base)) + .replace(`__BASE__`, JSON.stringify(devBase)) .replace(`__DEFINES__`, serializeDefine(config.define || {})) .replace(`__HMR_PROTOCOL__`, JSON.stringify(protocol)) .replace(`__HMR_HOSTNAME__`, JSON.stringify(host)) diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 1fa30f6a272ddd..20cf534ca7b192 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -37,7 +37,6 @@ import { isDataUrl, isExternalUrl, isObject, - isRelativeBase, normalizePath, parseRequest, processSrcSet @@ -146,6 +145,10 @@ const postcssConfigCache = new WeakMap< PostCSSConfigResult | null >() +function encodePublicUrlsInCSS(config: ResolvedConfig) { + return config.command === 'build' +} + /** * Plugin applied before user plugins */ @@ -187,7 +190,7 @@ export function cssPlugin(config: ResolvedConfig): Plugin { const urlReplacer: CssUrlReplacer = async (url, importer) => { if (checkPublicFile(url, config)) { - if (isRelativeBase(config.base)) { + if (encodePublicUrlsInCSS(config)) { return publicFileToBuiltUrl(url, config) } else { return config.base + url.slice(1) @@ -229,6 +232,7 @@ export function cssPlugin(config: ResolvedConfig): Plugin { // server only logic for handling CSS @import dependency hmr const { moduleGraph } = server const thisModule = moduleGraph.getModuleById(id) + const devBase = config.base if (thisModule) { // CSS modules cannot self-accept since it exports values const isSelfAccepting = @@ -244,10 +248,7 @@ export function cssPlugin(config: ResolvedConfig): Plugin { : await moduleGraph.ensureEntryFromUrl( ( await fileToUrl(file, config, this) - ).replace( - (config.server?.origin ?? '') + config.base, - '/' - ), + ).replace((config.server?.origin ?? '') + devBase, '/'), ssr ) ) @@ -291,8 +292,6 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { let outputToExtractedCSSMap: Map let hasEmitted = false - const relativeBase = isRelativeBase(config.base) - const rollupOptionsOutput = config.build.rollupOptions.output const assetFileNames = ( Array.isArray(rollupOptionsOutput) @@ -367,9 +366,10 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { } const cssContent = await getContentWithSourcemap(css) + const devBase = config.base return [ `import { updateStyle as __vite__updateStyle, removeStyle as __vite__removeStyle } from ${JSON.stringify( - path.posix.join(config.base, CLIENT_PUBLIC_PATH) + path.posix.join(devBase, CLIENT_PUBLIC_PATH) )}`, `const __vite__id = ${JSON.stringify(id)}`, `const __vite__css = ${JSON.stringify(cssContent)}`, @@ -448,19 +448,23 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { return null } + const { baseOptions } = config.build + const publicAssetUrlMap = publicAssetUrlCache.get(config)! // resolve asset URL placeholders to their built file URLs function resolveAssetUrlsInCss(chunkCSS: string, cssAssetName: string) { - const cssAssetDirname = relativeBase - ? getCssAssetDirname(cssAssetName) - : undefined + const encodedPublicUrls = encodePublicUrlsInCSS(config) + const cssAssetDirname = + encodedPublicUrls || baseOptions.relative + ? getCssAssetDirname(cssAssetName) + : undefined // replace asset url references with resolved url. chunkCSS = chunkCSS.replace(assetUrlRE, (_, fileHash, postfix = '') => { const filename = getAssetFilename(fileHash, config) + postfix chunk.viteMetadata.importedAssets.add(cleanUrl(filename)) - if (relativeBase) { + if (baseOptions.relative) { // relative base + extracted CSS const relativePath = path.posix.relative(cssAssetDirname!, filename) return relativePath.startsWith('.') @@ -468,11 +472,14 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { : './' + relativePath } else { // absolute base - return config.base + filename + if (typeof baseOptions.assets === 'function') { + config.logger.error('Error TODO:base') + } + return (baseOptions.assets ?? config.base) + filename } }) // resolve public URL from CSS paths - if (relativeBase) { + if (encodedPublicUrls) { const relativePathToPublicFromCSS = path.posix.relative( cssAssetDirname!, '' diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index 9d06d6e168f2e1..38070310a2f72c 100644 --- a/packages/vite/src/node/plugins/html.ts +++ b/packages/vite/src/node/plugins/html.ts @@ -24,12 +24,13 @@ import { getHash, isDataUrl, isExternalUrl, - isRelativeBase, normalizePath, processSrcSet, slash } from '../utils' import type { ResolvedConfig } from '../config' +import { getBuildBasePathUrl } from '../build' +import type { BuildBasePath } from '../build' import { assetUrlRE, checkPublicFile, @@ -535,7 +536,7 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { const toScriptTag = ( chunk: OutputChunk, - publicBase: string, + assetsBase: string, isAsync: boolean ): HtmlTagDescriptor => ({ tag: 'script', @@ -543,25 +544,25 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { ...(isAsync ? { async: true } : {}), type: 'module', crossorigin: true, - src: toPublicPath(chunk.fileName, publicBase) + src: toPublicPath(chunk.fileName, assetsBase) } }) const toPreloadTag = ( chunk: OutputChunk, - publicBase: string + assetsBase: string ): HtmlTagDescriptor => ({ tag: 'link', attrs: { rel: 'modulepreload', crossorigin: true, - href: toPublicPath(chunk.fileName, publicBase) + href: toPublicPath(chunk.fileName, assetsBase) } }) const getCssTagsForChunk = ( chunk: OutputChunk, - publicBase: string, + assetsBase: string, seen: Set = new Set() ): HtmlTagDescriptor[] => { const tags: HtmlTagDescriptor[] = [] @@ -570,7 +571,7 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { chunk.imports.forEach((file) => { const importee = bundle[file] if (importee?.type === 'chunk') { - tags.push(...getCssTagsForChunk(importee, publicBase, seen)) + tags.push(...getCssTagsForChunk(importee, assetsBase, seen)) } }) } @@ -582,7 +583,7 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { tag: 'link', attrs: { rel: 'stylesheet', - href: toPublicPath(file, publicBase) + href: toPublicPath(file, assetsBase) } }) } @@ -593,7 +594,7 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { for (const [id, html] of processedHtml) { const relativeUrlPath = path.posix.relative(config.root, id) - const publicBase = getPublicBase(relativeUrlPath, config) + const assetsBase = getAssetsBase(relativeUrlPath, config) const isAsync = isAsyncScriptMap.get(config)!.get(id)! @@ -622,13 +623,13 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { // when inlined, discard entry chunk and inject diff --git a/playground/legacy/vite.config.js b/playground/legacy/vite.config.js index c21813971716b5..50b564c14da08f 100644 --- a/playground/legacy/vite.config.js +++ b/playground/legacy/vite.config.js @@ -15,12 +15,15 @@ module.exports = { cssCodeSplit: false, manifest: true, rollupOptions: { + input: { + main: path.resolve(__dirname, 'index.html'), + nested: path.resolve(__dirname, 'nested/index.html') + }, output: { chunkFileNames(chunkInfo) { if (chunkInfo.name === 'immutable-chunk') { return `assets/${chunkInfo.name}.js` } - return `assets/chunk-[name].[hash].js` } } From c6d292e09486885ae7823204104c0ef141efaff1 Mon Sep 17 00:00:00 2001 From: patak-dev Date: Sat, 18 Jun 2022 18:51:23 +0200 Subject: [PATCH 12/12] test: fix legacy build test --- playground/legacy/vite.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playground/legacy/vite.config.js b/playground/legacy/vite.config.js index 50b564c14da08f..f793980f365887 100644 --- a/playground/legacy/vite.config.js +++ b/playground/legacy/vite.config.js @@ -16,7 +16,7 @@ module.exports = { manifest: true, rollupOptions: { input: { - main: path.resolve(__dirname, 'index.html'), + index: path.resolve(__dirname, 'index.html'), nested: path.resolve(__dirname, 'nested/index.html') }, output: {