From 1f011d8e02f699f8d548fd4b2efce0d8d4e4ffbf Mon Sep 17 00:00:00 2001 From: sun0day Date: Fri, 31 Mar 2023 01:22:08 +0800 Subject: [PATCH 01/96] test: throw element not found error (#12665) --- playground/test-utils.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/playground/test-utils.ts b/playground/test-utils.ts index b99daa846b2689..137abff2c4bd53 100644 --- a/playground/test-utils.ts +++ b/playground/test-utils.ts @@ -71,7 +71,11 @@ const timeout = (n: number) => new Promise((r) => setTimeout(r, n)) async function toEl(el: string | ElementHandle): Promise { if (typeof el === 'string') { - return await page.$(el) + const realEl = await page.$(el) + if (realEl == null) { + throw new Error(`Cannot find element: "${el}"`) + } + return realEl } return el } From c268cfaf0fdb0c82db22fcc67b790c00b2c248ac Mon Sep 17 00:00:00 2001 From: patak Date: Thu, 30 Mar 2023 20:07:50 +0200 Subject: [PATCH 02/96] perf: module graph url shortcuts (#12635) --- .../vite/src/node/plugins/importAnalysis.ts | 2 +- packages/vite/src/node/server/moduleGraph.ts | 66 ++++++++++++++++++- .../vite/src/node/server/transformRequest.ts | 4 +- 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index c1a7b6403502cb..8ee82040d21e7f 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -694,7 +694,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { const normalizedAcceptedUrls = new Set() for (const { url, start, end } of acceptedUrls) { const [normalized] = await moduleGraph.resolveUrl( - toAbsoluteUrl(markExplicitImport(url)), + toAbsoluteUrl(url), ssr, ) normalizedAcceptedUrls.add(normalized) diff --git a/packages/vite/src/node/server/moduleGraph.ts b/packages/vite/src/node/server/moduleGraph.ts index 4c3b8ad966388a..af254e38b62704 100644 --- a/packages/vite/src/node/server/moduleGraph.ts +++ b/packages/vite/src/node/server/moduleGraph.ts @@ -61,6 +61,15 @@ export class ModuleGraph { fileToModulesMap = new Map>() safeModulesPath = new Set() + /** + * @internal + */ + _unresolvedUrlToModuleMap = new Map() + /** + * @internal + */ + _ssrUnresolvedUrlToModuleMap = new Map() + constructor( private resolveId: ( url: string, @@ -72,7 +81,14 @@ export class ModuleGraph { rawUrl: string, ssr?: boolean, ): Promise { - const [url] = await this.resolveUrl(rawUrl, ssr) + // Quick path, if we already have a module for this rawUrl (even without extension) + rawUrl = removeImportQuery(removeTimestampQuery(rawUrl)) + const mod = this._getUnresolvedUrlToModule(rawUrl, ssr) + if (mod) { + return mod + } + + const [url] = await this._resolveUrl(rawUrl, ssr) return this.urlToModuleMap.get(url) } @@ -220,8 +236,15 @@ export class ModuleGraph { ssr?: boolean, setIsSelfAccepting = true, ): Promise { - const [url, resolvedId, meta] = await this.resolveUrl(rawUrl, ssr) - let mod = this.idToModuleMap.get(resolvedId) + // Quick path, if we already have a module for this rawUrl (even without extension) + rawUrl = removeImportQuery(removeTimestampQuery(rawUrl)) + let mod = this._getUnresolvedUrlToModule(rawUrl, ssr) + if (mod) { + return mod + } + + const [url, resolvedId, meta] = await this._resolveUrl(rawUrl, ssr) + mod = this.idToModuleMap.get(resolvedId) if (!mod) { mod = new ModuleNode(url, setIsSelfAccepting) if (meta) mod.meta = meta @@ -241,6 +264,11 @@ export class ModuleGraph { else if (!this.urlToModuleMap.has(url)) { this.urlToModuleMap.set(url, mod) } + + // Also register the clean url to the module, so that we can short-circuit + // resolving the same url twice + this._setUnresolvedUrlToModule(rawUrl, mod, ssr) + return mod } @@ -275,6 +303,38 @@ export class ModuleGraph { // the same module async resolveUrl(url: string, ssr?: boolean): Promise { url = removeImportQuery(removeTimestampQuery(url)) + const mod = this._getUnresolvedUrlToModule(url, ssr) + if (mod?.id) { + return [mod.url, mod.id, mod.meta] + } + return this._resolveUrl(url, ssr) + } + + /** + * @internal + */ + _getUnresolvedUrlToModule( + url: string, + ssr?: boolean, + ): ModuleNode | undefined { + return ( + ssr ? this._ssrUnresolvedUrlToModuleMap : this._unresolvedUrlToModuleMap + ).get(url) + } + /** + * @internal + */ + _setUnresolvedUrlToModule(url: string, mod: ModuleNode, ssr?: boolean): void { + ;(ssr + ? this._ssrUnresolvedUrlToModuleMap + : this._unresolvedUrlToModuleMap + ).set(url, mod) + } + + /** + * @internal + */ + async _resolveUrl(url: string, ssr?: boolean): Promise { const resolved = await this.resolveId(url, !!ssr) const resolvedId = resolved?.id || url if ( diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index 82bc7fabc20716..3762c69cfef3b3 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -144,7 +144,9 @@ async function doTransform( // resolve const id = - (await pluginContainer.resolveId(url, undefined, { ssr }))?.id || url + module?.id ?? + (await pluginContainer.resolveId(url, undefined, { ssr }))?.id ?? + url const result = loadAndTransform(id, url, server, options, timestamp) From 82137d6872adb61ffc2f8ce47924dd50626b3b64 Mon Sep 17 00:00:00 2001 From: patak Date: Thu, 30 Mar 2023 20:27:26 +0200 Subject: [PATCH 03/96] perf: shorcircuit resolve in ensure entry from url (#12655) --- .../vite/src/node/plugins/importAnalysis.ts | 4 ++- packages/vite/src/node/server/moduleGraph.ts | 28 ++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 8ee82040d21e7f..2c4ffeccd899a5 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -391,10 +391,12 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { // up-to-date version of this module. try { // delay setting `isSelfAccepting` until the file is actually used (#7870) - const depModule = await moduleGraph.ensureEntryFromUrl( + // We use an internal function to avoid resolving the url again + const depModule = await moduleGraph._ensureEntryFromUrl( unwrapId(url), ssr, canSkipImportAnalysis(url) || forceSkipImportAnalysis, + resolved, ) if (depModule.lastHMRTimestamp > 0) { url = injectQuery(url, `t=${depModule.lastHMRTimestamp}`) diff --git a/packages/vite/src/node/server/moduleGraph.ts b/packages/vite/src/node/server/moduleGraph.ts index af254e38b62704..8dda0e412a335a 100644 --- a/packages/vite/src/node/server/moduleGraph.ts +++ b/packages/vite/src/node/server/moduleGraph.ts @@ -235,6 +235,19 @@ export class ModuleGraph { rawUrl: string, ssr?: boolean, setIsSelfAccepting = true, + ): Promise { + return this._ensureEntryFromUrl(rawUrl, ssr, setIsSelfAccepting) + } + + /** + * @internal + */ + async _ensureEntryFromUrl( + rawUrl: string, + ssr?: boolean, + setIsSelfAccepting = true, + // Optimization, avoid resolving the same url twice if the caller already did it + resolved?: PartialResolvedId, ): Promise { // Quick path, if we already have a module for this rawUrl (even without extension) rawUrl = removeImportQuery(removeTimestampQuery(rawUrl)) @@ -242,8 +255,11 @@ export class ModuleGraph { if (mod) { return mod } - - const [url, resolvedId, meta] = await this._resolveUrl(rawUrl, ssr) + const [url, resolvedId, meta] = await this._resolveUrl( + rawUrl, + ssr, + resolved, + ) mod = this.idToModuleMap.get(resolvedId) if (!mod) { mod = new ModuleNode(url, setIsSelfAccepting) @@ -334,8 +350,12 @@ export class ModuleGraph { /** * @internal */ - async _resolveUrl(url: string, ssr?: boolean): Promise { - const resolved = await this.resolveId(url, !!ssr) + async _resolveUrl( + url: string, + ssr?: boolean, + alreadyResolved?: PartialResolvedId, + ): Promise { + const resolved = alreadyResolved ?? (await this.resolveId(url, !!ssr)) const resolvedId = resolved?.id || url if ( url !== resolvedId && From 49674b54fac4378faec8580b0a13e29e21d7900d Mon Sep 17 00:00:00 2001 From: chenfan <83797583+chenfan0@users.noreply.github.com> Date: Fri, 31 Mar 2023 04:11:55 +0800 Subject: [PATCH 04/96] fix: throws error when plugin tries to resolve ID to external URL (#11731) Co-authored-by: bluwy --- packages/vite/src/node/plugins/importAnalysis.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 2c4ffeccd899a5..d6d72308d42b44 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -601,7 +601,10 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { // record for HMR import chain analysis // make sure to unwrap and normalize away base const hmrUrl = unwrapId(stripBase(url, base)) - importedUrls.add(hmrUrl) + const isLocalImport = !isExternalUrl(hmrUrl) && !isDataUrl(hmrUrl) + if (isLocalImport) { + importedUrls.add(hmrUrl) + } if (enablePartialAccept && importedBindings) { extractImportedBindings( @@ -612,7 +615,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { ) } - if (!isDynamicImport) { + if (!isDynamicImport && isLocalImport) { // for pre-transforming staticImportedUrls.add({ url: hmrUrl, id: resolvedId }) } From 561227c63a6935e812ad59b532562f6c38d7563a Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Fri, 31 Mar 2023 15:40:12 +0800 Subject: [PATCH 05/96] refactor: clean up preTransformRequest (#12672) --- packages/vite/src/node/plugins/importAnalysis.ts | 11 +++++------ .../vite/src/node/server/middlewares/indexHtml.ts | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index d6d72308d42b44..0c41d7791ecf0e 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -53,7 +53,6 @@ import { cjsShouldExternalizeForSSR, shouldExternalizeForSSR, } from '../ssr/ssrExternal' -import { transformRequest } from '../server/transformRequest' import { getDepsOptimizer, optimizedDepNeedsInterop } from '../optimizer' import { checkPublicFile } from './asset' import { @@ -276,7 +275,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { let s: MagicString | undefined const str = () => s || (s = new MagicString(source)) const importedUrls = new Set() - const staticImportedUrls = new Set<{ url: string; id: string }>() + const staticImportedUrls = new Set() const acceptedUrls = new Set<{ url: string start: number @@ -617,7 +616,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { if (!isDynamicImport && isLocalImport) { // for pre-transforming - staticImportedUrls.add({ url: hmrUrl, id: resolvedId }) + staticImportedUrls.add(hmrUrl) } } else if (!importer.startsWith(clientDir)) { if (!isInNodeModules(importer)) { @@ -764,9 +763,9 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { // These requests will also be registered in transformRequest to be awaited // by the deps optimizer if (config.server.preTransformRequests && staticImportedUrls.size) { - staticImportedUrls.forEach(({ url }) => { + for (let url of staticImportedUrls) { url = removeImportQuery(url) - transformRequest(url, server, { ssr }).catch((e) => { + server.transformRequest(url, { ssr }).catch((e) => { if (e?.code === ERR_OUTDATED_OPTIMIZED_DEP) { // This are expected errors return @@ -774,7 +773,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { // Unexpected error, log the issue but avoid an unhandled exception config.logger.error(e.message) }) - }) + } } if (s) { diff --git a/packages/vite/src/node/server/middlewares/indexHtml.ts b/packages/vite/src/node/server/middlewares/indexHtml.ts index 64db1ba6838287..4ab0038333c2e6 100644 --- a/packages/vite/src/node/server/middlewares/indexHtml.ts +++ b/packages/vite/src/node/server/middlewares/indexHtml.ts @@ -326,6 +326,6 @@ function preTransformRequest(server: ViteDevServer, url: string, base: string) { // transform all url as non-ssr as html includes client-side assets only server.transformRequest(url).catch((e) => { // Unexpected error, log the issue but avoid an unhandled exception - server.config.logger.error(e) + server.config.logger.error(e.message) }) } From 15177a1885c33e319e0cebdc954edbed534ea941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnaud=20Barr=C3=A9?= Date: Fri, 31 Mar 2023 11:57:16 +0200 Subject: [PATCH 06/96] chore: set target in tsconfig.check.json (#12675) --- packages/vite/tsconfig.check.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/vite/tsconfig.check.json b/packages/vite/tsconfig.check.json index 3df61bd71010e7..457b452578f5e8 100644 --- a/packages/vite/tsconfig.check.json +++ b/packages/vite/tsconfig.check.json @@ -1,5 +1,7 @@ { "compilerOptions": { + "target": "ES2020", + "moduleResolution": "node", "noEmit": true, "strict": true, "exactOptionalPropertyTypes": true From 050c0f9661231737797290c1c1faa761d98e00f3 Mon Sep 17 00:00:00 2001 From: sun0day Date: Sat, 1 Apr 2023 04:56:40 +0800 Subject: [PATCH 07/96] fix(ssr): show ssr module loader error stack (#12651) --- packages/vite/src/node/ssr/ssrModuleLoader.ts | 72 ++++++++++--------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/packages/vite/src/node/ssr/ssrModuleLoader.ts b/packages/vite/src/node/ssr/ssrModuleLoader.ts index 466039d82b2ae2..cd234876a748e6 100644 --- a/packages/vite/src/node/ssr/ssrModuleLoader.ts +++ b/packages/vite/src/node/ssr/ssrModuleLoader.ts @@ -28,6 +28,7 @@ type SSRModule = Record const pendingModules = new Map>() const pendingImports = new Map() +const importErrors = new WeakMap() export async function ssrLoadModule( url: string, @@ -131,32 +132,39 @@ async function instantiateModule( const pendingDeps: string[] = [] const ssrImport = async (dep: string) => { - if (dep[0] !== '.' && dep[0] !== '/') { - return nodeImport(dep, mod.file!, resolveOptions) - } - // convert to rollup URL because `pendingImports`, `moduleGraph.urlToModuleMap` requires that - dep = unwrapId(dep) - if (!isCircular(dep) && !pendingImports.get(dep)?.some(isCircular)) { - pendingDeps.push(dep) - if (pendingDeps.length === 1) { - pendingImports.set(url, pendingDeps) + try { + if (dep[0] !== '.' && dep[0] !== '/') { + return await nodeImport(dep, mod.file!, resolveOptions) } - const mod = await ssrLoadModule( - dep, - server, - context, - urlStack, - fixStacktrace, - ) - if (pendingDeps.length === 1) { - pendingImports.delete(url) - } else { - pendingDeps.splice(pendingDeps.indexOf(dep), 1) + // convert to rollup URL because `pendingImports`, `moduleGraph.urlToModuleMap` requires that + dep = unwrapId(dep) + if (!isCircular(dep) && !pendingImports.get(dep)?.some(isCircular)) { + pendingDeps.push(dep) + if (pendingDeps.length === 1) { + pendingImports.set(url, pendingDeps) + } + const mod = await ssrLoadModule( + dep, + server, + context, + urlStack, + fixStacktrace, + ) + if (pendingDeps.length === 1) { + pendingImports.delete(url) + } else { + pendingDeps.splice(pendingDeps.indexOf(dep), 1) + } + // return local module to avoid race condition #5470 + return mod } - // return local module to avoid race condition #5470 - return mod + return moduleGraph.urlToModuleMap.get(dep)?.ssrModule + } catch (err) { + // tell external error handler which mod was imported with error + importErrors.set(err, { importee: dep }) + + throw err } - return moduleGraph.urlToModuleMap.get(dep)?.ssrModule } const ssrDynamicImport = (dep: string) => { @@ -204,6 +212,7 @@ async function instantiateModule( ) } catch (e) { mod.ssrError = e + const errorData = importErrors.get(e) if (e.stack && fixStacktrace) { ssrFixStacktrace(e, moduleGraph) @@ -212,7 +221,10 @@ async function instantiateModule( server.config.logger.error( colors.red( `Error when evaluating SSR module ${url}:` + - (e.importee ? ` failed to import "${e.importee}"\n` : '\n'), + (errorData?.importee + ? ` failed to import "${errorData.importee}"` + : '') + + `\n|- ${e.stack}\n`, ), { timestamp: true, @@ -221,7 +233,6 @@ async function instantiateModule( }, ) - delete e.importee throw e } @@ -262,15 +273,8 @@ async function nodeImport( } } - try { - const mod = await dynamicImport(url) - return proxyESM(mod) - } catch (err) { - // tell external error handler which mod was imported with error - err.importee = id - - throw err - } + const mod = await dynamicImport(url) + return proxyESM(mod) } // rollup-style default import interop for cjs From a3150ee1b67c96f8bf88a20c2a7c4d2befed7b97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Sun, 2 Apr 2023 08:08:36 +0900 Subject: [PATCH 08/96] refactor: remove `ensureVolumeInPath` (#12690) --- packages/vite/src/node/plugins/resolve.ts | 4 +--- packages/vite/src/node/server/middlewares/transform.ts | 5 +---- packages/vite/src/node/utils.ts | 4 ---- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 7a85aa84b24426..92965078e9e816 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -20,7 +20,6 @@ import { cleanUrl, createDebugger, deepImportRE, - ensureVolumeInPath, fsPathFromId, injectQuery, isBuiltin, @@ -203,7 +202,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { if (asSrc && depsOptimizer?.isOptimizedDepUrl(id)) { const optimizedPath = id.startsWith(FS_PREFIX) ? fsPathFromId(id) - : normalizePath(ensureVolumeInPath(path.resolve(root, id.slice(1)))) + : normalizePath(path.resolve(root, id.slice(1))) return optimizedPath } @@ -1250,7 +1249,6 @@ function equalWithoutSuffix(path: string, key: string, suffix: string) { } function getRealPath(resolved: string, preserveSymlinks?: boolean): string { - resolved = ensureVolumeInPath(resolved) if (!preserveSymlinks && browserExternalId !== resolved) { resolved = safeRealpathSync(resolved) } diff --git a/packages/vite/src/node/server/middlewares/transform.ts b/packages/vite/src/node/server/middlewares/transform.ts index 8fb184181c417d..b149c8e89fe9eb 100644 --- a/packages/vite/src/node/server/middlewares/transform.ts +++ b/packages/vite/src/node/server/middlewares/transform.ts @@ -7,7 +7,6 @@ import type { ViteDevServer } from '..' import { cleanUrl, createDebugger, - ensureVolumeInPath, fsPathFromId, injectQuery, isImportRequest, @@ -79,9 +78,7 @@ export function transformMiddleware( // means that the dependency has already been pre-bundled and loaded const sourcemapPath = url.startsWith(FS_PREFIX) ? fsPathFromId(url) - : normalizePath( - ensureVolumeInPath(path.resolve(root, url.slice(1))), - ) + : normalizePath(path.resolve(root, url.slice(1))) try { const map = JSON.parse( await fsp.readFile(sourcemapPath, 'utf-8'), diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 68f26d95cf18cc..3f52cda0e53565 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -255,10 +255,6 @@ export function isParentDirectory(dir: string, file: string): boolean { ) } -export function ensureVolumeInPath(file: string): string { - return isWindows ? path.resolve(file) : file -} - export const queryRE = /\?.*$/s const postfixRE = /[?#].*$/s From 1638ebd655f44020e95d7a4147191a935cc5facb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Sun, 2 Apr 2023 08:09:11 +0900 Subject: [PATCH 09/96] fix(import-analysis): escape quotes correctly (#12688) --- packages/vite/src/node/plugins/importAnalysis.ts | 7 ++++--- packages/vite/src/node/plugins/importAnalysisBuild.ts | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 0c41d7791ecf0e..acd85a1402aa2a 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -589,9 +589,10 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { rewriteDone = true } if (!rewriteDone) { - let rewrittenUrl = JSON.stringify(url) - if (!isDynamicImport) rewrittenUrl = rewrittenUrl.slice(1, -1) - str().overwrite(start, end, rewrittenUrl, { + const rewrittenUrl = JSON.stringify(url) + const s = isDynamicImport ? start : start - 1 + const e = isDynamicImport ? end : end + 1 + str().overwrite(s, e, rewrittenUrl, { contentOnly: true, }) } diff --git a/packages/vite/src/node/plugins/importAnalysisBuild.ts b/packages/vite/src/node/plugins/importAnalysisBuild.ts index 0f49bb44d10b71..8913ff5970dbc9 100644 --- a/packages/vite/src/node/plugins/importAnalysisBuild.ts +++ b/packages/vite/src/node/plugins/importAnalysisBuild.ts @@ -342,9 +342,10 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { rewriteDone = true } if (!rewriteDone) { - let rewrittenUrl = JSON.stringify(file) - if (!isDynamicImport) rewrittenUrl = rewrittenUrl.slice(1, -1) - str().update(start, end, rewrittenUrl) + const rewrittenUrl = JSON.stringify(file) + const s = isDynamicImport ? start : start - 1 + const e = isDynamicImport ? end : end + 1 + str().update(s, e, rewrittenUrl) } } } From 7ce9b002755b2b226eee7a39b8a55e3e8ae96243 Mon Sep 17 00:00:00 2001 From: Jecelyn Yeen <5917927+jecfish@users.noreply.github.com> Date: Sun, 2 Apr 2023 10:00:38 +0200 Subject: [PATCH 10/96] docs: update x_google_ignoreList documentation url (#12694) --- docs/config/server-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config/server-options.md b/docs/config/server-options.md index 49c766cba59d5a..ab0f1b261ddb7c 100644 --- a/docs/config/server-options.md +++ b/docs/config/server-options.md @@ -324,7 +324,7 @@ export default defineConfig({ - **Type:** `false | (sourcePath: string, sourcemapPath: string) => boolean` - **Default:** `(sourcePath) => sourcePath.includes('node_modules')` -Whether or not to ignore source files in the server sourcemap, used to populate the [`x_google_ignoreList` source map extension](https://developer.chrome.com/blog/devtools-better-angular-debugging/#the-x_google_ignorelist-source-map-extension). +Whether or not to ignore source files in the server sourcemap, used to populate the [`x_google_ignoreList` source map extension](https://developer.chrome.com/articles/x-google-ignore-list/). `server.sourcemapIgnoreList` is the equivalent of [`build.rollupOptions.output.sourcemapIgnoreList`](https://rollupjs.org/configuration-options/#output-sourcemapignorelist) for the dev server. A difference between the two config options is that the rollup function is called with a relative path for `sourcePath` while `server.sourcemapIgnoreList` is called with an absolute path. During dev, most modules have the map and the source in the same folder, so the relative path for `sourcePath` is the file name itself. In these cases, absolute paths makes it convenient to be used instead. From 81e44dda57e815c71ea3b2dcdd3dfbd05ef35e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Sun, 2 Apr 2023 17:56:54 +0900 Subject: [PATCH 11/96] fix: take in relative assets path fixes from rollup (#12695) --- packages/vite/src/node/build.ts | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index 912129b6f70fb9..8216b1a3294971 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -1033,7 +1033,7 @@ function injectSsrFlag>( /* The following functions are copied from rollup - https://github.com/rollup/rollup/blob/c5269747cd3dd14c4b306e8cea36f248d9c1aa01/src/ast/nodes/MetaProperty.ts#L189-L232 + https://github.com/rollup/rollup/blob/0bcf0a672ac087ff2eb88fbba45ec62389a4f45f/src/ast/nodes/MetaProperty.ts#L145-L193 https://github.com/rollup/rollup The MIT License (MIT) @@ -1042,15 +1042,30 @@ function injectSsrFlag>( The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +const needsEscapeRegEx = /[\n\r'\\\u2028\u2029]/ +const quoteNewlineRegEx = /([\n\r'\u2028\u2029])/g +const backSlashRegEx = /\\/g + +function escapeId(id: string): string { + if (!needsEscapeRegEx.test(id)) return id + return id.replace(backSlashRegEx, '\\\\').replace(quoteNewlineRegEx, '\\$1') +} + const getResolveUrl = (path: string, URL = 'URL') => `new ${URL}(${path}).href` const getRelativeUrlFromDocument = (relativePath: string, umd = false) => getResolveUrl( - `'${relativePath}', ${ + `'${escapeId(relativePath)}', ${ umd ? `typeof document === 'undefined' ? location.href : ` : '' }document.currentScript && document.currentScript.src || document.baseURI`, ) +const getFileUrlFromFullPath = (path: string) => + `require('u' + 'rl').pathToFileURL(${path}).href` + +const getFileUrlFromRelativePath = (path: string) => + getFileUrlFromFullPath(`__dirname + '/${path}'`) + const relativeUrlMechanisms: Record< InternalModuleFormat, (relativePath: string) => string @@ -1060,18 +1075,16 @@ const relativeUrlMechanisms: Record< return getResolveUrl(`require.toUrl('${relativePath}'), document.baseURI`) }, cjs: (relativePath) => - `(typeof document === 'undefined' ? ${getResolveUrl( - `'file:' + __dirname + '/${relativePath}'`, - `(require('u' + 'rl').URL)`, + `(typeof document === 'undefined' ? ${getFileUrlFromRelativePath( + relativePath, )} : ${getRelativeUrlFromDocument(relativePath)})`, es: (relativePath) => getResolveUrl(`'${relativePath}', import.meta.url`), iife: (relativePath) => getRelativeUrlFromDocument(relativePath), // NOTE: make sure rollup generate `module` params system: (relativePath) => getResolveUrl(`'${relativePath}', module.meta.url`), umd: (relativePath) => - `(typeof document === 'undefined' && typeof location === 'undefined' ? ${getResolveUrl( - `'file:' + __dirname + '/${relativePath}'`, - `(require('u' + 'rl').URL)`, + `(typeof document === 'undefined' && typeof location === 'undefined' ? ${getFileUrlFromRelativePath( + relativePath, )} : ${getRelativeUrlFromDocument(relativePath, true)})`, } /* end of copy */ From 65f5ed2e35a392524579a3ec9b94e040676825fc Mon Sep 17 00:00:00 2001 From: sun0day Date: Sun, 2 Apr 2023 16:58:15 +0800 Subject: [PATCH 12/96] fix(worker): worker import.meta.url should not depends on document in iife mode (#12629) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 翠 / green --- packages/vite/src/node/build.ts | 2 ++ packages/vite/src/node/plugins/worker.ts | 14 ++++++++++++++ playground/test-utils.ts | 9 +++++++-- .../worker/__tests__/iife/iife-worker.spec.ts | 9 ++++++--- playground/worker/url-worker.js | 9 ++++++++- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index 8216b1a3294971..aedbe282f11074 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -58,6 +58,7 @@ import { ESBUILD_MODULES_TARGET, VERSION } from './constants' import { resolveChokidarOptions } from './watch' import { completeSystemWrapPlugin } from './plugins/completeSystemWrap' import { mergeConfig } from './publicUtils' +import { webWorkerPostPlugin } from './plugins/worker' export interface BuildOptions { /** @@ -445,6 +446,7 @@ export async function resolveBuildPlugins(config: ResolvedConfig): Promise<{ : [rollupOptionsPlugins], ) ).filter(Boolean) as Plugin[]), + ...(config.isWorker ? [webWorkerPostPlugin()] : []), ], post: [ buildImportAnalysisPlugin(config), diff --git a/packages/vite/src/node/plugins/worker.ts b/packages/vite/src/node/plugins/worker.ts index 7fd7e328d6c301..4293b494937312 100644 --- a/packages/vite/src/node/plugins/worker.ts +++ b/packages/vite/src/node/plugins/worker.ts @@ -185,6 +185,20 @@ export async function workerFileToUrl( return encodeWorkerAssetFileName(fileName, workerMap) } +export function webWorkerPostPlugin(): Plugin { + return { + name: 'vite:worker-post', + resolveImportMeta(property, { chunkId, format }) { + // document is undefined in the worker, so we need to avoid it in iife + if (property === 'url' && format === 'iife') { + return 'self.location.href' + } + + return null + }, + } +} + export function webWorkerPlugin(config: ResolvedConfig): Plugin { const isBuild = config.command === 'build' let server: ViteDevServer diff --git a/playground/test-utils.ts b/playground/test-utils.ts index 137abff2c4bd53..6d3489ad66dd03 100644 --- a/playground/test-utils.ts +++ b/playground/test-utils.ts @@ -157,14 +157,19 @@ export function readManifest(base = ''): Manifest { */ export async function untilUpdated( poll: () => string | Promise, - expected: string, + expected: string | RegExp, runInBuild = false, ): Promise { if (isBuild && !runInBuild) return const maxTries = process.env.CI ? 200 : 50 for (let tries = 0; tries < maxTries; tries++) { const actual = (await poll()) ?? '' - if (actual.indexOf(expected) > -1 || tries === maxTries - 1) { + if ( + (typeof expected === 'string' + ? actual.indexOf(expected) > -1 + : actual.match(expected)) || + tries === maxTries - 1 + ) { expect(actual).toMatch(expected) break } else { diff --git a/playground/worker/__tests__/iife/iife-worker.spec.ts b/playground/worker/__tests__/iife/iife-worker.spec.ts index f37c70643f5fc4..196e8c9bece24b 100644 --- a/playground/worker/__tests__/iife/iife-worker.spec.ts +++ b/playground/worker/__tests__/iife/iife-worker.spec.ts @@ -84,16 +84,19 @@ describe.runIf(isBuild)('build', () => { test('module worker', async () => { await untilUpdated( - () => page.textContent('.worker-import-meta-url'), - 'A string', + async () => page.textContent('.worker-import-meta-url'), + /A\sstring.*\/iife\/.+url-worker\.js/, + true, ) await untilUpdated( () => page.textContent('.worker-import-meta-url-resolve'), - 'A string', + /A\sstring.*\/iife\/.+url-worker\.js/, + true, ) await untilUpdated( () => page.textContent('.shared-worker-import-meta-url'), 'A string', + true, ) }) diff --git a/playground/worker/url-worker.js b/playground/worker/url-worker.js index 1ba50225ee339d..bede21cc42cc49 100644 --- a/playground/worker/url-worker.js +++ b/playground/worker/url-worker.js @@ -1,4 +1,11 @@ -self.postMessage('A string' + import.meta.env.BASE_URL + self.location.url) +self.postMessage( + [ + 'A string', + import.meta.env.BASE_URL, + self.location.url, + import.meta.url, + ].join(' '), +) // for sourcemap console.log('url-worker.js') From fdef8fdb0f9e95d442660102432fae3a8c485136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Sun, 2 Apr 2023 18:00:40 +0900 Subject: [PATCH 13/96] refactor: `import.meta.url` condition from renderChunk hook of worker plugin (#12696) --- packages/vite/src/node/plugins/worker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/plugins/worker.ts b/packages/vite/src/node/plugins/worker.ts index 4293b494937312..f1e1e4420453a5 100644 --- a/packages/vite/src/node/plugins/worker.ts +++ b/packages/vite/src/node/plugins/worker.ts @@ -366,7 +366,7 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin { } ) } - if (code.match(workerAssetUrlRE) || code.includes('import.meta.url')) { + if (code.match(workerAssetUrlRE)) { const toRelativeRuntime = createToImportMetaURLBasedRelativeRuntime( outputOptions.format, ) From 56802b1a0b6e39cbc4cca683539631fc1132c9a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Sun, 2 Apr 2023 21:21:16 +0900 Subject: [PATCH 14/96] fix: leave fully dynamic import.meta.url asset (fixes #10306) (#10549) --- .../src/node/plugins/assetImportMetaUrl.ts | 12 ++++++++++-- playground/assets/index.html | 19 ++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/vite/src/node/plugins/assetImportMetaUrl.ts b/packages/vite/src/node/plugins/assetImportMetaUrl.ts index 3f61d2ddbd0b46..7a22de3e31814b 100644 --- a/packages/vite/src/node/plugins/assetImportMetaUrl.ts +++ b/packages/vite/src/node/plugins/assetImportMetaUrl.ts @@ -56,7 +56,13 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin { const ast = this.parse(rawUrl) const templateLiteral = (ast as any).body[0].expression if (templateLiteral.expressions.length) { - const pattern = JSON.stringify(buildGlobPattern(templateLiteral)) + const pattern = buildGlobPattern(templateLiteral) + if (pattern.startsWith('**')) { + // don't transform for patterns like this + // because users won't intend to do that in most cases + continue + } + // Note: native import.meta.url is not supported in the baseline // target so we use the global location here. It can be // window.location or self.location in case it is used in a Web Worker. @@ -64,7 +70,9 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin { s.update( index, index + exp.length, - `new URL((import.meta.glob(${pattern}, { eager: true, import: 'default', as: 'url' }))[${rawUrl}], self.location)`, + `new URL((import.meta.glob(${JSON.stringify( + pattern, + )}, { eager: true, import: 'default', as: 'url' }))[${rawUrl}], self.location)`, ) continue } diff --git a/playground/assets/index.html b/playground/assets/index.html index 6b9c2f87a96d3c..57caa90f4f552d 100644 --- a/playground/assets/index.html +++ b/playground/assets/index.html @@ -226,6 +226,11 @@

new URL(`non-existent`, import.meta.url)

+

new URL(`${dynamic}`, import.meta.url)

+

+ +

+

simple script tag import-expression

@@ -427,9 +432,17 @@

assets in noscript

testDynamicImportMetaUrlWithComma('icon', 1) testDynamicImportMetaUrlWithComma('asset', 2) - const name = 'test' - const js = new URL(`./nested/${name}.js`, import.meta.url).href - text('.dynamic-import-meta-url-js', js) + { + const name = 'test' + const js = new URL(`./nested/${name}.js`, import.meta.url).href + text('.dynamic-import-meta-url-js', js) + } + + { + const name = './nested/icon' + const metaUrl = new URL(`${name}.png`, import.meta.url) + text(`.dynamic-import-meta-url-all`, metaUrl) + } function text(el, text) { document.querySelector(el).textContent = text From 621bb2f11b774772456917279a295ca4035dae3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Mon, 3 Apr 2023 16:17:22 +0900 Subject: [PATCH 15/96] chore: revert custom license resolve (#12709) --- packages/vite/rollupLicensePlugin.ts | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/packages/vite/rollupLicensePlugin.ts b/packages/vite/rollupLicensePlugin.ts index f1d24f4b7c8e82..d3dce56a7dfeb6 100644 --- a/packages/vite/rollupLicensePlugin.ts +++ b/packages/vite/rollupLicensePlugin.ts @@ -1,9 +1,6 @@ import fs from 'node:fs' -import path from 'node:path' import license from 'rollup-plugin-license' import colors from 'picocolors' -import fg from 'fast-glob' -import resolve from 'resolve' import type { Plugin } from 'rollup' export default function licensePlugin( @@ -66,21 +63,6 @@ export default function licensePlugin( typeof repository === 'string' ? repository : repository.url }\n` } - if (!licenseText && name) { - try { - const pkgDir = path.dirname( - resolve.sync(path.join(name, 'package.json'), { - preserveSymlinks: false, - }), - ) - const licenseFile = fg.sync(`${pkgDir}/LICENSE*`, { - caseSensitiveMatch: false, - })[0] - if (licenseFile) { - licenseText = fs.readFileSync(licenseFile, 'utf-8') - } - } catch {} - } if (licenseText) { text += '\n' + From 466b6e9419d48dfc338a6e09d54223195c64f342 Mon Sep 17 00:00:00 2001 From: sun0day Date: Mon, 3 Apr 2023 15:44:02 +0800 Subject: [PATCH 16/96] test(worker): add test for not emitting worker manifest (#12705) --- playground/worker/__tests__/iife/iife-worker.spec.ts | 7 ++++++- playground/worker/vite.config-iife.js | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/playground/worker/__tests__/iife/iife-worker.spec.ts b/playground/worker/__tests__/iife/iife-worker.spec.ts index 196e8c9bece24b..f3e5f230a9b1ed 100644 --- a/playground/worker/__tests__/iife/iife-worker.spec.ts +++ b/playground/worker/__tests__/iife/iife-worker.spec.ts @@ -1,7 +1,7 @@ import fs from 'node:fs' import path from 'node:path' import { describe, expect, test } from 'vitest' -import { isBuild, page, testDir, untilUpdated } from '~utils' +import { isBuild, page, readManifest, testDir, untilUpdated } from '~utils' test('normal', async () => { await untilUpdated(() => page.textContent('.pong'), 'pong') @@ -80,6 +80,11 @@ describe.runIf(isBuild)('build', () => { '"type":"constructor"', ) }) + + test('should not emit worker manifest', async () => { + const manifest = readManifest('iife') + expect(manifest['index.html']).toBeDefined() + }) }) test('module worker', async () => { diff --git a/playground/worker/vite.config-iife.js b/playground/worker/vite.config-iife.js index 59ab1ded54736e..a0759906534f66 100644 --- a/playground/worker/vite.config-iife.js +++ b/playground/worker/vite.config-iife.js @@ -38,6 +38,7 @@ export default vite.defineConfig({ }, build: { outDir: 'dist/iife', + manifest: true, rollupOptions: { output: { assetFileNames: 'assets/[name].[ext]', From 2efd3ec45773e0d8986778688af8332a76e44d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Mon, 3 Apr 2023 18:14:09 +0900 Subject: [PATCH 17/96] docs: add a note about duplicate style by `additionalData` (#12716) --- docs/config/shared-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config/shared-options.md b/docs/config/shared-options.md index 4def2201ee891f..c8825044891c8b 100644 --- a/docs/config/shared-options.md +++ b/docs/config/shared-options.md @@ -232,7 +232,7 @@ Specify options to pass to CSS pre-processors. The file extensions are used as k - `less` - [Options](https://lesscss.org/usage/#less-options). - `styl`/`stylus` - Only [`define`](https://stylus-lang.com/docs/js.html#define-name-node) is supported, which can be passed as an object. -All preprocessor options also support the `additionalData` option, which can be used to inject extra code for each style content. +All preprocessor options also support the `additionalData` option, which can be used to inject extra code for each style content. Note that if you include actual styles and not just variables, those styles will be duplicated in the final bundle. Example: From 0ce0e937cf9a4692253e03ad240111652a5e9a8a Mon Sep 17 00:00:00 2001 From: sun0day Date: Mon, 3 Apr 2023 19:57:23 +0800 Subject: [PATCH 18/96] chore(optimizer): remove redundant setTimeout call in scan process (#12718) --- packages/vite/src/node/optimizer/optimizer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/vite/src/node/optimizer/optimizer.ts b/packages/vite/src/node/optimizer/optimizer.ts index e8b92b986ba3ef..56c960da34fdc0 100644 --- a/packages/vite/src/node/optimizer/optimizer.ts +++ b/packages/vite/src/node/optimizer/optimizer.ts @@ -213,8 +213,8 @@ async function createDepsOptimizer( if (!isBuild) { // Important, the scanner is dev only depsOptimizer.scanProcessing = new Promise((resolve) => { - // Ensure server listen is called before the scanner - setTimeout(async () => { + // Runs in the background in case blocking high priority tasks + ;(async () => { try { debug(colors.green(`scanning for dependencies...`)) @@ -244,7 +244,7 @@ async function createDepsOptimizer( resolve() depsOptimizer.scanProcessing = undefined } - }, 0) + })() }) } } From 2d30ae5a008c755f9220dd9ef57ec6e39dec4dc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Mon, 3 Apr 2023 20:58:33 +0900 Subject: [PATCH 19/96] fix: ignore pnp resolve error (#12719) --- packages/vite/src/node/packages.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/packages.ts b/packages/vite/src/node/packages.ts index b4a0d7948240e6..75c73c585d2c80 100644 --- a/packages/vite/src/node/packages.ts +++ b/packages/vite/src/node/packages.ts @@ -60,7 +60,12 @@ export function resolvePackageData( const cacheKey = getRpdCacheKey(pkgName, basedir, preserveSymlinks) if (packageCache?.has(cacheKey)) return packageCache.get(cacheKey)! - const pkg = pnp.resolveToUnqualified(pkgName, basedir) + let pkg: string | null + try { + pkg = pnp.resolveToUnqualified(pkgName, basedir) + } catch { + return null + } if (!pkg) return null const pkgData = loadPackageData(path.join(pkg, 'package.json')) From bedcd8ffacea794e66dcc817b124daccadb34241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Mon, 3 Apr 2023 22:44:57 +0900 Subject: [PATCH 20/96] feat: skip pinging the server when the tab is not shown (#12698) --- packages/vite/src/client/client.ts | 48 ++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index ee8cd5c855d544..1818dda65eef98 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -315,23 +315,53 @@ async function waitForSuccessfulPing( ) { const pingHostProtocol = socketProtocol === 'wss' ? 'https' : 'http' - // eslint-disable-next-line no-constant-condition - while (true) { + const ping = async () => { + // A fetch on a websocket URL will return a successful promise with status 400, + // but will reject a networking error. + // When running on middleware mode, it returns status 426, and an cors error happens if mode is not no-cors try { - // A fetch on a websocket URL will return a successful promise with status 400, - // but will reject a networking error. - // When running on middleware mode, it returns status 426, and an cors error happens if mode is not no-cors await fetch(`${pingHostProtocol}://${hostAndPath}`, { mode: 'no-cors', }) - break - } catch (e) { - // wait ms before attempting to ping again - await new Promise((resolve) => setTimeout(resolve, ms)) + return true + } catch {} + return false + } + + if (await ping()) { + return + } + await wait(ms) + + // eslint-disable-next-line no-constant-condition + while (true) { + if (document.visibilityState === 'visible') { + if (await ping()) { + break + } + await wait(ms) + } else { + await waitForWindowShow() } } } +function wait(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + +function waitForWindowShow() { + return new Promise((resolve) => { + const onChange = async () => { + if (document.visibilityState === 'visible') { + resolve() + document.removeEventListener('visibilitychange', onChange) + } + } + document.addEventListener('visibilitychange', onChange) + }) +} + const sheetsMap = new Map() // all css imports should be inserted at the same position // because after build it will be a single css file From 3f4d109ea4ca03c6506b7561c0520e45d8eacf42 Mon Sep 17 00:00:00 2001 From: patak Date: Mon, 3 Apr 2023 17:09:53 +0200 Subject: [PATCH 21/96] fix: avoid clean up while committing deps folder (#12722) --- packages/vite/src/node/optimizer/index.ts | 13 +++-- packages/vite/src/node/optimizer/optimizer.ts | 49 +++++++++---------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index d2079064004c69..a290e7a81eca5b 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -165,9 +165,6 @@ export interface DepOptimizationResult { * to be able to discard the result */ commit: () => Promise - /** - * @deprecated noop - */ cancel: () => void } @@ -510,8 +507,11 @@ export function runOptimizeDeps( const qualifiedIds = Object.keys(depsInfo) let cleaned = false + let committed = false const cleanUp = () => { - if (!cleaned) { + // If commit was already called, ignore the clean up even if a cancel was requested + // This minimizes the chances of leaving the deps cache in a corrupted state + if (!cleaned && !committed) { cleaned = true // No need to wait, we can clean up in the background because temp folders // are unique per run @@ -525,9 +525,12 @@ export function runOptimizeDeps( metadata, cancel: cleanUp, commit: async () => { + // Ignore clean up requests after this point so the temp folder isn't deleted before + // we finish commiting the new deps cache files to the deps folder + committed = true + // Write metadata file, then commit the processing folder to the global deps cache // Rewire the file paths from the temporal processing dir to the final deps cache dir - const dataPath = path.join(processingCacheDir, '_metadata.json') fs.writeFileSync( dataPath, diff --git a/packages/vite/src/node/optimizer/optimizer.ts b/packages/vite/src/node/optimizer/optimizer.ts index 56c960da34fdc0..f4f60f291eeeef 100644 --- a/packages/vite/src/node/optimizer/optimizer.ts +++ b/packages/vite/src/node/optimizer/optimizer.ts @@ -175,14 +175,12 @@ async function createDepsOptimizer( } | undefined - let optimizingNewDeps: Promise | undefined async function close() { closed = true await Promise.allSettled([ discover?.cancel(), depsOptimizer.scanProcessing, optimizationResult?.cancel(), - optimizingNewDeps, ]) } @@ -261,27 +259,6 @@ async function createDepsOptimizer( depOptimizationProcessing = newDepOptimizationProcessing() } - async function optimizeNewDeps() { - // a successful completion of the optimizeDeps rerun will end up - // creating new bundled version of all current and discovered deps - // in the cache dir and a new metadata info object assigned - // to _metadata. A fullReload is only issued if the previous bundled - // dependencies have changed. - - // if the rerun fails, _metadata remains untouched, current discovered - // deps are cleaned, and a fullReload is issued - - // All deps, previous known and newly discovered are rebundled, - // respect insertion order to keep the metadata file stable - - const knownDeps = prepareKnownDeps() - - startNextDiscoveredBatch() - - optimizationResult = runOptimizeDeps(config, knownDeps) - return await optimizationResult.result - } - function prepareKnownDeps() { const knownDeps: Record = {} // Clone optimized info objects, fileHash, browserHash may be changed for them @@ -297,6 +274,18 @@ async function createDepsOptimizer( } async function runOptimizer(preRunResult?: DepOptimizationResult) { + // a successful completion of the optimizeDeps rerun will end up + // creating new bundled version of all current and discovered deps + // in the cache dir and a new metadata info object assigned + // to _metadata. A fullReload is only issued if the previous bundled + // dependencies have changed. + + // if the rerun fails, _metadata remains untouched, current discovered + // deps are cleaned, and a fullReload is issued + + // All deps, previous known and newly discovered are rebundled, + // respect insertion order to keep the metadata file stable + const isRerun = firstRunCalled firstRunCalled = true @@ -314,9 +303,17 @@ async function createDepsOptimizer( currentlyProcessing = true try { - const processingResult = - preRunResult ?? (await (optimizingNewDeps = optimizeNewDeps())) - optimizingNewDeps = undefined + let processingResult: DepOptimizationResult + if (preRunResult) { + processingResult = preRunResult + } else { + const knownDeps = prepareKnownDeps() + startNextDiscoveredBatch() + + optimizationResult = runOptimizeDeps(config, knownDeps) + processingResult = await optimizationResult.result + optimizationResult = undefined + } if (closed) { currentlyProcessing = false From c90b46e9f52a32b4d1d0577815a5a3cffda97827 Mon Sep 17 00:00:00 2001 From: patak Date: Mon, 3 Apr 2023 17:25:59 +0200 Subject: [PATCH 22/96] perf: start preprocessing static imports before updating module graph (#12723) --- .../vite/src/node/plugins/importAnalysis.ts | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index acd85a1402aa2a..289930320182fe 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -275,7 +275,6 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { let s: MagicString | undefined const str = () => s || (s = new MagicString(source)) const importedUrls = new Set() - const staticImportedUrls = new Set() const acceptedUrls = new Set<{ url: string start: number @@ -615,9 +614,23 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { ) } - if (!isDynamicImport && isLocalImport) { - // for pre-transforming - staticImportedUrls.add(hmrUrl) + if ( + !isDynamicImport && + isLocalImport && + config.server.preTransformRequests + ) { + // pre-transform known direct imports + // These requests will also be registered in transformRequest to be awaited + // by the deps optimizer + const url = removeImportQuery(hmrUrl) + server.transformRequest(url, { ssr }).catch((e) => { + if (e?.code === ERR_OUTDATED_OPTIMIZED_DEP) { + // This are expected errors + return + } + // Unexpected error, log the issue but avoid an unhandled exception + config.logger.error(e.message) + }) } } else if (!importer.startsWith(clientDir)) { if (!isInNodeModules(importer)) { @@ -760,23 +773,6 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { )}`, ) - // pre-transform known direct imports - // These requests will also be registered in transformRequest to be awaited - // by the deps optimizer - if (config.server.preTransformRequests && staticImportedUrls.size) { - for (let url of staticImportedUrls) { - url = removeImportQuery(url) - server.transformRequest(url, { ssr }).catch((e) => { - if (e?.code === ERR_OUTDATED_OPTIMIZED_DEP) { - // This are expected errors - return - } - // Unexpected error, log the issue but avoid an unhandled exception - config.logger.error(e.message) - }) - } - } - if (s) { return transformStableResult(s, importer, config) } else { From fedb0803308f8d62ff88f300187f0379a4d49f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Tue, 4 Apr 2023 04:06:47 +0900 Subject: [PATCH 23/96] perf(css): cache lazy import (#12721) --- packages/vite/src/node/plugins/css.ts | 78 ++++++++++++++++++--------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 1ea8cba9c510d9..238357d400fed6 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -891,7 +891,7 @@ async function compileCSS( if (needInlineImport) { postcssPlugins.unshift( - (await import('postcss-import')).default({ + (await importPostcssImport()).default({ async resolve(id, basedir) { const publicFile = checkPublicFile(id, config) if (publicFile) { @@ -926,7 +926,7 @@ async function compileCSS( if (isModule) { postcssPlugins.unshift( - (await import('postcss-modules')).default({ + (await importPostcssModules()).default({ ...modulesOptions, localsConvention: modulesOptions?.localsConvention, getJSON( @@ -963,31 +963,30 @@ async function compileCSS( let postcssResult: PostCSS.Result try { const source = removeDirectQuery(id) + const postcss = await importPostcss() // postcss is an unbundled dep and should be lazy imported - postcssResult = await (await import('postcss')) - .default(postcssPlugins) - .process(code, { - ...postcssOptions, - parser: - lang === 'sss' - ? loadPreprocessor(PostCssDialectLang.sss, config.root) - : postcssOptions.parser, - to: source, - from: source, - ...(devSourcemap - ? { - map: { - inline: false, - annotation: false, - // postcss may return virtual files - // we cannot obtain content of them, so this needs to be enabled - sourcesContent: true, - // when "prev: preprocessorMap", the result map may include duplicate filename in `postcssResult.map.sources` - // prev: preprocessorMap, - }, - } - : {}), - }) + postcssResult = await postcss.default(postcssPlugins).process(code, { + ...postcssOptions, + parser: + lang === 'sss' + ? loadPreprocessor(PostCssDialectLang.sss, config.root) + : postcssOptions.parser, + to: source, + from: source, + ...(devSourcemap + ? { + map: { + inline: false, + annotation: false, + // postcss may return virtual files + // we cannot obtain content of them, so this needs to be enabled + sourcesContent: true, + // when "prev: preprocessorMap", the result map may include duplicate filename in `postcssResult.map.sources` + // prev: preprocessorMap, + }, + } + : {}), + }) // record CSS dependencies from @imports for (const message of postcssResult.messages) { @@ -1055,6 +1054,33 @@ async function compileCSS( } } +const lazyImportCache = new Map() +function createCachedImport( + name: string, + imp: () => Promise, +): () => T | Promise { + return () => { + const cached = lazyImportCache.get(name) + if (cached) return cached + + const promise = imp().then((module) => { + lazyImportCache.set(name, module) + return module + }) + lazyImportCache.set(name, promise) + return promise + } +} +const importPostcssImport = createCachedImport( + 'postcss-import', + () => import('postcss-import'), +) +const importPostcssModules = createCachedImport( + 'postcss-modules', + () => import('postcss-modules'), +) +const importPostcss = createCachedImport('postcss', () => import('postcss')) + export interface PreprocessCSSResult { code: string map?: SourceMapInput From 5d07d7c921f8cc6c9ca24926209066519b8b1f6b Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Tue, 4 Apr 2023 17:22:13 +0800 Subject: [PATCH 24/96] perf: skip es-module-lexer if have no dynamic imports (#12732) --- packages/vite/src/node/plugins/dynamicImportVars.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 7933618d49da08..45a27c6f466431 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -7,6 +7,7 @@ import { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars' import type { KnownAsTypeMap } from 'types/importGlob' import type { Plugin } from '../plugin' import type { ResolvedConfig } from '../config' +import { CLIENT_ENTRY } from '../constants' import { createFilter, normalizePath, @@ -20,6 +21,11 @@ import { toAbsoluteGlob } from './importMetaGlob' export const dynamicImportHelperId = '\0vite/dynamic-import-helper' const relativePathRE = /^\.{1,2}\// +// fast path to check if source contains a dynamic import. we check for a +// trailing slash too as a dynamic import statement can have comments between +// the `import` and the `(`. +const hasDynamicImportRE = /\bimport\s*[(/]/ + interface DynamicImportRequest { as?: keyof KnownAsTypeMap } @@ -162,7 +168,11 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { }, async transform(source, importer) { - if (!filter(importer)) { + if ( + !filter(importer) || + importer === CLIENT_ENTRY || + !hasDynamicImportRE.test(source) + ) { return } From e6eed856f79ec123afbd65c9d46900f77a4654ab Mon Sep 17 00:00:00 2001 From: sun0day Date: Tue, 4 Apr 2023 20:56:13 +0800 Subject: [PATCH 25/96] docs: troubleshooting on browser extension blocker (#12737) --- docs/guide/troubleshooting.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/guide/troubleshooting.md b/docs/guide/troubleshooting.md index f97b0447e32ff4..2bcf9042ca2791 100644 --- a/docs/guide/troubleshooting.md +++ b/docs/guide/troubleshooting.md @@ -144,3 +144,7 @@ For example, you might see these errors. > TypeError: Cannot create property 'foo' on boolean 'false' If these code are used inside dependencies, you could use [`patch-package`](https://github.com/ds300/patch-package) (or [`yarn patch`](https://yarnpkg.com/cli/patch) or [`pnpm patch`](https://pnpm.io/cli/patch)) for an escape hatch. + +### Browser extensions + +Some browser extensions (like ad-blockers) may prevent the Vite client from sending requests to the Vite dev server. You may see a white screen without logged errors in this case. Try disabling extensions if you have this issue. From 889eebe5002f898efa8985015637283377a7b262 Mon Sep 17 00:00:00 2001 From: sun0day Date: Tue, 4 Apr 2023 21:05:21 +0800 Subject: [PATCH 26/96] fix(optimizer): load the correct lock file (#12700) --- packages/vite/src/node/optimizer/index.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index a290e7a81eca5b..71673a65a6febd 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -1236,11 +1236,13 @@ function isSingleDefaultExport(exports: readonly string[]) { } const lockfileFormats = [ - { name: 'package-lock.json', checkPatches: true }, - { name: 'yarn.lock', checkPatches: true }, // Included in lockfile for v2+ - { name: 'pnpm-lock.yaml', checkPatches: false }, // Included in lockfile - { name: 'bun.lockb', checkPatches: true }, -] + { name: 'package-lock.json', checkPatches: true, manager: 'npm' }, + { name: 'yarn.lock', checkPatches: true, manager: 'yarn' }, // Included in lockfile for v2+ + { name: 'pnpm-lock.yaml', checkPatches: false, manager: 'pnpm' }, // Included in lockfile + { name: 'bun.lockb', checkPatches: true, manager: 'bun' }, +].sort((_, { manager }) => { + return process.env.npm_config_user_agent?.startsWith(manager) ? 1 : -1 +}) const lockfileNames = lockfileFormats.map((l) => l.name) export function getDepHash(config: ResolvedConfig, ssr: boolean): string { From 0646754bea54efd584978d1a911038167ee45071 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Tue, 4 Apr 2023 21:25:53 +0800 Subject: [PATCH 27/96] refactor(css): simplify cached import code (#12730) --- packages/vite/src/node/plugins/css.ts | 35 +++++++++------------------ 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 238357d400fed6..aa47b6b3bc93f8 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -1054,32 +1054,21 @@ async function compileCSS( } } -const lazyImportCache = new Map() -function createCachedImport( - name: string, - imp: () => Promise, -): () => T | Promise { +function createCachedImport(imp: () => Promise): () => T | Promise { + let cached: T | Promise return () => { - const cached = lazyImportCache.get(name) - if (cached) return cached - - const promise = imp().then((module) => { - lazyImportCache.set(name, module) - return module - }) - lazyImportCache.set(name, promise) - return promise + if (!cached) { + cached = imp().then((module) => { + cached = module + return module + }) + } + return cached } } -const importPostcssImport = createCachedImport( - 'postcss-import', - () => import('postcss-import'), -) -const importPostcssModules = createCachedImport( - 'postcss-modules', - () => import('postcss-modules'), -) -const importPostcss = createCachedImport('postcss', () => import('postcss')) +const importPostcssImport = createCachedImport(() => import('postcss-import')) +const importPostcssModules = createCachedImport(() => import('postcss-modules')) +const importPostcss = createCachedImport(() => import('postcss')) export interface PreprocessCSSResult { code: string From 4538bfe5bd5a574b13bd25a344d0d9e04453ec9f Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Wed, 5 Apr 2023 04:49:00 +0800 Subject: [PATCH 28/96] refactor: remove unused exports data props (#12740) --- packages/vite/src/node/optimizer/index.ts | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 71673a65a6febd..81a0929b68eaed 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -43,16 +43,11 @@ const isDebugEnabled = _debug('vite:deps').enabled const jsExtensionRE = /\.js$/i const jsMapExtensionRE = /\.js\.map$/i -const reExportRE = /export\s+\*\s+from/ export type ExportsData = { hasImports: boolean // exported names (for `export { a as b }`, `b` is exported name) exports: readonly string[] - facade: boolean - // es-module-lexer has a facade detection but isn't always accurate for our - // use case when the module has default export - hasReExports?: boolean // hint if the dep requires loading as jsx jsxLoader?: boolean } @@ -731,7 +726,7 @@ async function prepareEsbuildOptimizerRun( const src = depsInfo[id].src! const exportsData = await (depsInfo[id].exportsData ?? extractExportsData(src, config, ssr)) - if (exportsData.jsxLoader) { + if (exportsData.jsxLoader && !esbuildOptions.loader?.['.js']) { // Ensure that optimization won't fail by defaulting '.js' to the JSX parser. // This is useful for packages such as Gatsby. esbuildOptions.loader = { @@ -1152,11 +1147,10 @@ export async function extractExportsData( write: false, format: 'esm', }) - const [imports, exports, facade] = parse(result.outputFiles[0].text) + const [imports, exports] = parse(result.outputFiles[0].text) return { hasImports: imports.length > 0, exports: exports.map((e) => e.n), - facade, } } @@ -1174,25 +1168,14 @@ export async function extractExportsData( const transformed = await transformWithEsbuild(entryContent, filePath, { loader, }) - // Ensure that optimization won't fail by defaulting '.js' to the JSX parser. - // This is useful for packages such as Gatsby. - esbuildOptions.loader = { - '.js': 'jsx', - ...esbuildOptions.loader, - } parseResult = parse(transformed.code) usedJsxLoader = true } - const [imports, exports, facade] = parseResult + const [imports, exports] = parseResult const exportsData: ExportsData = { hasImports: imports.length > 0, exports: exports.map((e) => e.n), - facade, - hasReExports: imports.some(({ ss, se }) => { - const exp = entryContent.slice(ss, se) - return reExportRE.test(exp) - }), jsxLoader: usedJsxLoader, } return exportsData From be9505041bb07844af629344a1115240fb0a8e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Wed, 5 Apr 2023 06:07:09 +0900 Subject: [PATCH 29/96] fix(ssr): load sourcemaps alongside modules (#11780) Co-authored-by: Justice Almanzar --- packages/vite/src/node/ssr/ssrModuleLoader.ts | 28 +++++++++-- .../ssr-html/__tests__/ssr-html.spec.ts | 27 +++++++++++ playground/ssr-html/package.json | 4 +- playground/ssr-html/src/error.js | 3 ++ playground/ssr-html/test-stacktrace.js | 47 +++++++++++++++++++ 5 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 playground/ssr-html/src/error.js create mode 100644 playground/ssr-html/test-stacktrace.js diff --git a/packages/vite/src/node/ssr/ssrModuleLoader.ts b/packages/vite/src/node/ssr/ssrModuleLoader.ts index cd234876a748e6..2f9e71f55569bd 100644 --- a/packages/vite/src/node/ssr/ssrModuleLoader.ts +++ b/packages/vite/src/node/ssr/ssrModuleLoader.ts @@ -11,6 +11,7 @@ import { import { transformRequest } from '../server/transformRequest' import type { InternalResolveOptionsWithOverrideConditions } from '../plugins/resolve' import { tryNodeResolve } from '../plugins/resolve' +import { genSourceMapUrl } from '../server/sourcemap' import { ssrDynamicImportKey, ssrExportAllKey, @@ -26,6 +27,16 @@ interface SSRContext { type SSRModule = Record +// eslint-disable-next-line @typescript-eslint/no-empty-function +const AsyncFunction = async function () {}.constructor as typeof Function +let fnDeclarationLineCount = 0 +{ + const body = '/*code*/' + const source = new AsyncFunction('a', 'b', body).toString() + fnDeclarationLineCount = + source.slice(0, source.indexOf(body)).split('\n').length - 1 +} + const pendingModules = new Map>() const pendingImports = new Map() const importErrors = new WeakMap() @@ -190,9 +201,18 @@ async function instantiateModule( } } + let sourceMapSuffix = '' + if (result.map) { + const moduleSourceMap = Object.assign({}, result.map, { + // currently we need to offset the line + // https://github.com/nodejs/node/issues/43047#issuecomment-1180632750 + mappings: ';'.repeat(fnDeclarationLineCount) + result.map.mappings, + }) + sourceMapSuffix = + '\n//# sourceMappingURL=' + genSourceMapUrl(moduleSourceMap) + } + try { - // eslint-disable-next-line @typescript-eslint/no-empty-function - const AsyncFunction = async function () {}.constructor as typeof Function const initModule = new AsyncFunction( `global`, ssrModuleExportsKey, @@ -200,7 +220,9 @@ async function instantiateModule( ssrImportKey, ssrDynamicImportKey, ssrExportAllKey, - '"use strict";' + result.code + `\n//# sourceURL=${mod.url}`, + '"use strict";' + + result.code + + `\n//# sourceURL=${mod.url}${sourceMapSuffix}`, ) await initModule( context.global, diff --git a/playground/ssr-html/__tests__/ssr-html.spec.ts b/playground/ssr-html/__tests__/ssr-html.spec.ts index fa871fce04efb8..2b9da5cadd01c0 100644 --- a/playground/ssr-html/__tests__/ssr-html.spec.ts +++ b/playground/ssr-html/__tests__/ssr-html.spec.ts @@ -1,3 +1,6 @@ +import { execFile } from 'node:child_process' +import { promisify } from 'node:util' +import path from 'node:path' import fetch from 'node-fetch' import { describe, expect, test } from 'vitest' import { port } from './serve' @@ -55,3 +58,27 @@ describe.runIf(isServe)('hmr', () => { }, '[wow]') }) }) + +describe.runIf(isServe)('stacktrace', () => { + const execFileAsync = promisify(execFile) + + for (const sourcemapsEnabled of [false, true]) { + test(`stacktrace is correct when sourcemaps is${ + sourcemapsEnabled ? '' : ' not' + } enabled in Node.js`, async () => { + const testStacktraceFile = path.resolve( + __dirname, + '../test-stacktrace.js', + ) + + const p = await execFileAsync('node', [ + testStacktraceFile, + '' + sourcemapsEnabled, + ]) + const line = p.stdout + .split('\n') + .find((line) => line.includes('Module.error')) + expect(line.trim()).toMatch(/[\\/]src[\\/]error\.js:2:9/) + }) + } +}) diff --git a/playground/ssr-html/package.json b/playground/ssr-html/package.json index 090faa1b578684..f1fb19aaa25488 100644 --- a/playground/ssr-html/package.json +++ b/playground/ssr-html/package.json @@ -6,7 +6,9 @@ "scripts": { "dev": "node server", "serve": "NODE_ENV=production node server", - "debug": "node --inspect-brk server" + "debug": "node --inspect-brk server", + "test-stacktrace:off": "node test-stacktrace false", + "test-stacktrace:on": "node test-stacktrace true" }, "dependencies": {}, "devDependencies": { diff --git a/playground/ssr-html/src/error.js b/playground/ssr-html/src/error.js new file mode 100644 index 00000000000000..fe8eeb20af8f8a --- /dev/null +++ b/playground/ssr-html/src/error.js @@ -0,0 +1,3 @@ +export function error() { + throw new Error('e') +} diff --git a/playground/ssr-html/test-stacktrace.js b/playground/ssr-html/test-stacktrace.js new file mode 100644 index 00000000000000..c3ce5e56736799 --- /dev/null +++ b/playground/ssr-html/test-stacktrace.js @@ -0,0 +1,47 @@ +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import { createServer } from 'vite' + +const isSourceMapEnabled = process.argv[2] === 'true' +process.setSourceMapsEnabled(isSourceMapEnabled) +console.log('# sourcemaps enabled:', isSourceMapEnabled) + +const version = (() => { + const m = process.version.match(/^v(\d+)\.(\d+)\.\d+$/) + if (!m) throw new Error(`Failed to parse version: ${process.version}`) + + return { major: +m[1], minor: +m[2] } +})() + +// https://github.com/nodejs/node/pull/43428 +const isFunctionSourceMapSupported = + (version.major === 16 && version.minor >= 17) || + (version.major === 18 && version.minor >= 6) || + version.major >= 19 + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const isTest = process.env.VITEST + +const vite = await createServer({ + root: __dirname, + logLevel: isTest ? 'error' : 'info', + server: { + middlewareMode: true, + }, + appType: 'custom', +}) + +const mod = await vite.ssrLoadModule('/src/error.js') +try { + mod.error() +} catch (e) { + // this should not be called + // when sourcemap support for `new Function` is supported and sourcemap is enabled + // because the stacktrace is already rewritten by Node.js + if (!(isSourceMapEnabled && isFunctionSourceMapSupported)) { + vite.ssrFixStacktrace(e) + } + console.log(e) +} + +await vite.close() From 89e49773e688fc1fb7f2962f25b5c6749f425599 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Wed, 5 Apr 2023 10:22:51 +0800 Subject: [PATCH 30/96] refactor: make debugger nullable (#12687) --- packages/vite/src/node/config.ts | 22 +++++----- packages/vite/src/node/optimizer/index.ts | 15 +++---- packages/vite/src/node/optimizer/optimizer.ts | 30 +++++++------- packages/vite/src/node/optimizer/scan.ts | 5 +-- packages/vite/src/node/plugins/esbuild.ts | 7 ++-- .../vite/src/node/plugins/importAnalysis.ts | 27 +++++------- .../vite/src/node/plugins/optimizedDeps.ts | 5 +-- packages/vite/src/node/plugins/resolve.ts | 41 ++++++++----------- packages/vite/src/node/server/hmr.ts | 12 +++--- .../vite/src/node/server/middlewares/proxy.ts | 8 ++-- .../vite/src/node/server/middlewares/time.ts | 2 +- .../src/node/server/middlewares/transform.ts | 3 +- .../vite/src/node/server/pluginContainer.ts | 40 ++++++++---------- packages/vite/src/node/server/sourcemap.ts | 5 +-- .../vite/src/node/server/transformRequest.ts | 25 ++++++----- packages/vite/src/node/ssr/ssrExternal.ts | 4 +- packages/vite/src/node/utils.ts | 23 ++++++----- 17 files changed, 123 insertions(+), 151 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 19f856a040ef2b..6440dc5a058457 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -775,16 +775,14 @@ export async function resolveConfig( ) } - if (process.env.DEBUG) { - debug(`using resolved config: %O`, { - ...resolved, - plugins: resolved.plugins.map((p) => p.name), - worker: { - ...resolved.worker, - plugins: resolved.worker.plugins.map((p) => p.name), - }, - }) - } + debug?.(`using resolved config: %O`, { + ...resolved, + plugins: resolved.plugins.map((p) => p.name), + worker: { + ...resolved.worker, + plugins: resolved.worker.plugins.map((p) => p.name), + }, + }) if (config.build?.terserOptions && config.build.minify !== 'terser') { logger.warn( @@ -915,7 +913,7 @@ export async function loadConfigFromFile( } if (!resolvedPath) { - debug('no config file found.') + debug?.('no config file found.') return null } @@ -940,7 +938,7 @@ export async function loadConfigFromFile( bundled.code, isESM, ) - debug(`bundled config file loaded in ${getTime()}`) + debug?.(`bundled config file loaded in ${getTime()}`) const config = await (typeof userConfig === 'function' ? userConfig(configEnv) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 81a0929b68eaed..c4a3f199f291d9 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -3,7 +3,6 @@ import fsp from 'node:fs/promises' import path from 'node:path' import { promisify } from 'node:util' import { performance } from 'node:perf_hooks' -import _debug from 'debug' import colors from 'picocolors' import type { BuildContext, BuildOptions as EsbuildBuildOptions } from 'esbuild' import esbuild, { build } from 'esbuild' @@ -37,9 +36,7 @@ export { getDepsOptimizer, } from './optimizer' -export const debuggerViteDeps = createDebugger('vite:deps') -const debug = debuggerViteDeps -const isDebugEnabled = _debug('vite:deps').enabled +const debug = createDebugger('vite:deps') const jsExtensionRE = /\.js$/i const jsMapExtensionRE = /\.js\.map$/i @@ -243,7 +240,7 @@ export async function optimizeDeps( const deps = await discoverProjectDependencies(config).result const depsString = depsLogString(Object.keys(deps)) - log(colors.green(`Optimizing dependencies:\n ${depsString}`)) + log?.(colors.green(`Optimizing dependencies:\n ${depsString}`)) await addManuallyIncludedOptimizeDeps(deps, config, ssr) @@ -369,7 +366,7 @@ export async function loadCachedDepOptimizationMetadata( } catch (e) {} // hash is consistent, no need to re-bundle if (cachedMetadata && cachedMetadata.hash === getDepHash(config, ssr)) { - log('Hash is consistent. Skipping. Use --force to override.') + log?.('Hash is consistent. Skipping. Use --force to override.') // Nothing to commit or cancel as we are using the cache, we only // need to resolve the processing promise so requests can move on return cachedMetadata @@ -440,7 +437,7 @@ export function toDiscoveredDependencies( } export function depsLogString(qualifiedIds: string[]): string { - if (isDebugEnabled) { + if (debug) { return colors.yellow(qualifiedIds.join(`, `)) } else { const total = qualifiedIds.length @@ -656,7 +653,7 @@ export function runOptimizeDeps( } } - debug( + debug?.( `Dependencies bundled in ${(performance.now() - start).toFixed(2)}ms`, ) @@ -1162,7 +1159,7 @@ export async function extractExportsData( parseResult = parse(entryContent) } catch { const loader = esbuildOptions.loader?.[path.extname(filePath)] || 'jsx' - debug( + debug?.( `Unable to parse: ${filePath}.\n Trying again with a ${loader} transform.`, ) const transformed = await transformWithEsbuild(entryContent, filePath, { diff --git a/packages/vite/src/node/optimizer/optimizer.ts b/packages/vite/src/node/optimizer/optimizer.ts index f4f60f291eeeef..8c097941da5103 100644 --- a/packages/vite/src/node/optimizer/optimizer.ts +++ b/packages/vite/src/node/optimizer/optimizer.ts @@ -1,6 +1,5 @@ import colors from 'picocolors' -import _debug from 'debug' -import { getHash } from '../utils' +import { createDebugger, getHash } from '../utils' import { getDepOptimizationConfig } from '../config' import type { ResolvedConfig, ViteDevServer } from '..' import { @@ -8,7 +7,6 @@ import { addOptimizedDepInfo, createIsOptimizedDepFile, createIsOptimizedDepUrl, - debuggerViteDeps as debug, depsFromOptimizedDepInfo, depsLogString, discoverProjectDependencies, @@ -28,7 +26,7 @@ import type { OptimizedDepInfo, } from '.' -const isDebugEnabled = _debug('vite:deps').enabled +const debug = createDebugger('vite:deps') /** * The amount to wait for requests to register newly found dependencies before triggering @@ -214,7 +212,7 @@ async function createDepsOptimizer( // Runs in the background in case blocking high priority tasks ;(async () => { try { - debug(colors.green(`scanning for dependencies...`)) + debug?.(colors.green(`scanning for dependencies...`)) discover = discoverProjectDependencies(config) const deps = await discover.result @@ -395,7 +393,7 @@ async function createDepsOptimizer( if (!needsReload) { await commitProcessing() - if (!isDebugEnabled) { + if (!debug) { if (newDepsToLogHandle) clearTimeout(newDepsToLogHandle) newDepsToLogHandle = setTimeout(() => { newDepsToLogHandle = undefined @@ -420,7 +418,7 @@ async function createDepsOptimizer( // once a rerun is committed processingResult.cancel() - debug( + debug?.( colors.green( `✨ delaying reload as new dependencies have been found...`, ), @@ -428,7 +426,7 @@ async function createDepsOptimizer( } else { await commitProcessing() - if (!isDebugEnabled) { + if (!debug) { if (newDepsToLogHandle) clearTimeout(newDepsToLogHandle) newDepsToLogHandle = undefined logNewlyDiscoveredDeps() @@ -492,7 +490,7 @@ async function createDepsOptimizer( // optimizeDeps processing is finished const deps = Object.keys(metadata.discovered) const depsString = depsLogString(deps) - debug(colors.green(`new dependencies found: ${depsString}`)) + debug?.(colors.green(`new dependencies found: ${depsString}`)) runOptimizer() } @@ -586,7 +584,7 @@ async function createDepsOptimizer( } async function onCrawlEnd() { - debug(colors.green(`✨ static imports crawl ended`)) + debug?.(colors.green(`✨ static imports crawl ended`)) if (firstRunCalled) { return } @@ -606,7 +604,7 @@ async function createDepsOptimizer( const scanDeps = Object.keys(result.metadata.optimized) if (scanDeps.length === 0 && crawlDeps.length === 0) { - debug( + debug?.( colors.green( `✨ no dependencies found by the scanner or crawling static imports`, ), @@ -635,16 +633,16 @@ async function createDepsOptimizer( } } if (scannerMissedDeps) { - debug( + debug?.( colors.yellow( `✨ new dependencies were found while crawling that weren't detected by the scanner`, ), ) } - debug(colors.green(`✨ re-running optimizer`)) + debug?.(colors.green(`✨ re-running optimizer`)) debouncedProcessing(0) } else { - debug( + debug?.( colors.green( `✨ using post-scan optimizer result, the scanner found every used dependency`, ), @@ -654,7 +652,7 @@ async function createDepsOptimizer( } } else { if (crawlDeps.length === 0) { - debug( + debug?.( colors.green( `✨ no dependencies found while crawling the static imports`, ), @@ -808,7 +806,7 @@ function findInteropMismatches( // This only happens when a discovered dependency has mixed ESM and CJS syntax // and it hasn't been manually added to optimizeDeps.needsInterop needsInteropMismatch.push(dep) - debug(colors.cyan(`✨ needsInterop mismatch detected for ${dep}`)) + debug?.(colors.cyan(`✨ needsInterop mismatch detected for ${dep}`)) } } } diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index 7aa5902d23e04b..5571d031245f6d 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -34,7 +34,6 @@ import { transformGlobImport } from '../plugins/importMetaGlob' type ResolveIdOptions = Parameters[2] -const isDebug = process.env.DEBUG const debug = createDebugger('vite:deps') const htmlTypesRE = /\.(html|vue|svelte|astro|imba)$/ @@ -85,7 +84,7 @@ export function scanImports(config: ResolvedConfig): { } if (scanContext.cancelled) return - debug( + debug?.( `Crawling dependencies using entries: ${entries .map((entry) => `\n ${colors.dim(entry)}`) .join('')}`, @@ -141,7 +140,7 @@ export function scanImports(config: ResolvedConfig): { throw e }) .finally(() => { - if (isDebug) { + if (debug) { const duration = (performance.now() - start).toFixed(2) const depsStr = Object.keys(orderedDependencies(deps)) diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts index fac8c44b140f67..4426150cccd59e 100644 --- a/packages/vite/src/node/plugins/esbuild.ts +++ b/packages/vite/src/node/plugins/esbuild.ts @@ -24,7 +24,6 @@ import type { ResolvedConfig, ViteDevServer } from '..' import type { Plugin } from '../plugin' import { searchForWorkspaceRoot } from '..' -const isDebug = process.env.DEBUG const debug = createDebugger('vite:esbuild') const INJECT_HELPERS_IIFE_RE = @@ -193,7 +192,7 @@ export async function transformWithEsbuild( map, } } catch (e: any) { - debug(`esbuild error with options used: `, resolvedOptions) + debug?.(`esbuild error with options used: `, resolvedOptions) // patch error information if (e.errors) { e.frame = '' @@ -455,7 +454,7 @@ function initTSConfck(root: string, force = false) { } async function initTSConfckParseOptions(workspaceRoot: string) { - const start = isDebug ? performance.now() : 0 + const start = debug ? performance.now() : 0 const options: TSConfckParseOptions = { cache: new Map(), @@ -468,7 +467,7 @@ async function initTSConfckParseOptions(workspaceRoot: string) { resolveWithEmptyIfConfigNotFound: true, } - isDebug && debug(timeFrom(start), 'tsconfck init', colors.dim(workspaceRoot)) + debug?.(timeFrom(start), 'tsconfck init', colors.dim(workspaceRoot)) return options } diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 289930320182fe..677394f587a46f 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -62,7 +62,6 @@ import { import { isCSSRequest, isDirectCSSRequest, isModuleCSSRequest } from './css' import { browserExternalId } from './resolve' -const isDebug = !!process.env.DEBUG const debug = createDebugger('vite:import-analysis') const clientDir = normalizePath(CLIENT_DIR) @@ -207,7 +206,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { const prettyImporter = prettifyUrl(importer, root) if (canSkipImportAnalysis(importer)) { - isDebug && debug(colors.dim(`[skipped] ${prettyImporter}`)) + debug?.(colors.dim(`[skipped] ${prettyImporter}`)) return null } @@ -259,12 +258,9 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { if (!imports.length && !(this as any)._addedImports) { importerModule.isSelfAccepting = false - isDebug && - debug( - `${timeFrom(start)} ${colors.dim( - `[no imports] ${prettyImporter}`, - )}`, - ) + debug?.( + `${timeFrom(start)} ${colors.dim(`[no imports] ${prettyImporter}`)}`, + ) return source } @@ -572,7 +568,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { ) } } else if (needsInterop) { - debug(`${url} needs interop`) + debug?.(`${url} needs interop`) interopNamedImports(str(), imports[index], url, index) rewriteDone = true } @@ -682,7 +678,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { } if (hasHMR && !ssr) { - debugHmr( + debugHmr?.( `${ isSelfAccepting ? `[self-accepts]` @@ -766,12 +762,11 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { } } - isDebug && - debug( - `${timeFrom(start)} ${colors.dim( - `[${importedUrls.size} imports rewritten] ${prettyImporter}`, - )}`, - ) + debug?.( + `${timeFrom(start)} ${colors.dim( + `[${importedUrls.size} imports rewritten] ${prettyImporter}`, + )}`, + ) if (s) { return transformStableResult(s, importer, config) diff --git a/packages/vite/src/node/plugins/optimizedDeps.ts b/packages/vite/src/node/plugins/optimizedDeps.ts index 82a1c529adacf2..93c53f82400cb2 100644 --- a/packages/vite/src/node/plugins/optimizedDeps.ts +++ b/packages/vite/src/node/plugins/optimizedDeps.ts @@ -10,7 +10,6 @@ export const ERR_OPTIMIZE_DEPS_PROCESSING_ERROR = 'ERR_OPTIMIZE_DEPS_PROCESSING_ERROR' export const ERR_OUTDATED_OPTIMIZED_DEP = 'ERR_OUTDATED_OPTIMIZED_DEP' -const isDebug = process.env.DEBUG const debug = createDebugger('vite:optimize-deps') export function optimizedDepsPlugin(config: ResolvedConfig): Plugin { @@ -62,7 +61,7 @@ export function optimizedDepsPlugin(config: ResolvedConfig): Plugin { } } } - isDebug && debug(`load ${colors.cyan(file)}`) + debug?.(`load ${colors.cyan(file)}`) // Load the file from the cache instead of waiting for other plugin // load hooks to avoid race conditions, once processing is resolved, // we are sure that the file has been properly save to disk @@ -117,7 +116,7 @@ export function optimizedDepsBuildPlugin(config: ResolvedConfig): Plugin { const info = optimizedDepInfoFromFile(depsOptimizer.metadata, file) if (info) { await info.processing - isDebug && debug(`load ${colors.cyan(file)}`) + debug?.(`load ${colors.cyan(file)}`) } else { throw new Error( `Something unexpected happened while optimizing "${id}".`, diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 92965078e9e816..a1c5ab353110b4 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -61,7 +61,6 @@ const subpathImportsPrefix = '#' const startsWithWordCharRE = /^\w/ -const isDebug = process.env.DEBUG const debug = createDebugger('vite:resolve-details', { onlyWhenFocused: true, }) @@ -210,7 +209,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { if (asSrc && id.startsWith(FS_PREFIX)) { const fsPath = fsPathFromId(id) res = tryFsResolve(fsPath, options) - isDebug && debug(`[@fs] ${colors.cyan(id)} -> ${colors.dim(res)}`) + debug?.(`[@fs] ${colors.cyan(id)} -> ${colors.dim(res)}`) // always return here even if res doesn't exist since /@fs/ is explicit // if the file doesn't exist it should be a 404 return ensureVersionQuery(res || fsPath, id, options, depsOptimizer) @@ -221,7 +220,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { if (asSrc && id[0] === '/' && (rootInRoot || !id.startsWith(root))) { const fsPath = path.resolve(root, id.slice(1)) if ((res = tryFsResolve(fsPath, options))) { - isDebug && debug(`[url] ${colors.cyan(id)} -> ${colors.dim(res)}`) + debug?.(`[url] ${colors.cyan(id)} -> ${colors.dim(res)}`) return ensureVersionQuery(res, id, options, depsOptimizer) } } @@ -267,8 +266,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { options.packageCache, ) res = ensureVersionQuery(res, id, options, depsOptimizer) - isDebug && - debug(`[relative] ${colors.cyan(id)} -> ${colors.dim(res)}`) + debug?.(`[relative] ${colors.cyan(id)} -> ${colors.dim(res)}`) return resPkg ? { @@ -284,8 +282,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { const basedir = importer ? path.dirname(importer) : process.cwd() const fsPath = path.resolve(basedir, id) if ((res = tryFsResolve(fsPath, options))) { - isDebug && - debug(`[drive-relative] ${colors.cyan(id)} -> ${colors.dim(res)}`) + debug?.(`[drive-relative] ${colors.cyan(id)} -> ${colors.dim(res)}`) return ensureVersionQuery(res, id, options, depsOptimizer) } } @@ -295,7 +292,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { isNonDriveRelativeAbsolutePath(id) && (res = tryFsResolve(id, options)) ) { - isDebug && debug(`[fs] ${colors.cyan(id)} -> ${colors.dim(res)}`) + debug?.(`[fs] ${colors.cyan(id)} -> ${colors.dim(res)}`) return ensureVersionQuery(res, id, options, depsOptimizer) } @@ -376,7 +373,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { } } else { if (!asSrc) { - debug( + debug?.( `externalized node built-in "${id}" to empty module. ` + `(imported by: ${colors.white(colors.dim(importer))})`, ) @@ -388,7 +385,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { } } - isDebug && debug(`[fallthrough] ${colors.dim(id)}`) + debug?.(`[fallthrough] ${colors.dim(id)}`) }, load(id) { @@ -756,8 +753,7 @@ export function tryNodeResolve( let resolvedId = id if (deepMatch && !pkg?.data.exports && path.extname(id) !== resolvedExt) { resolvedId = resolved.id.slice(resolved.id.indexOf(id)) - isDebug && - debug(`[processResult] ${colors.cyan(id)} -> ${colors.dim(resolvedId)}`) + debug?.(`[processResult] ${colors.cyan(id)} -> ${colors.dim(resolvedId)}`) } return { ...resolved, id: resolvedId, external: true } } @@ -1026,12 +1022,11 @@ export function resolvePackageEntry( skipPackageJson, ) if (resolvedEntryPoint) { - isDebug && - debug( - `[package entry] ${colors.cyan(id)} -> ${colors.dim( - resolvedEntryPoint, - )}`, - ) + debug?.( + `[package entry] ${colors.cyan(id)} -> ${colors.dim( + resolvedEntryPoint, + )}`, + ) setResolvedCache('.', resolvedEntryPoint, targetWeb) return resolvedEntryPoint } @@ -1168,10 +1163,9 @@ function resolveDeepImport( targetWeb, ) if (resolved) { - isDebug && - debug( - `[node/deep-import] ${colors.cyan(id)} -> ${colors.dim(resolved)}`, - ) + debug?.( + `[node/deep-import] ${colors.cyan(id)} -> ${colors.dim(resolved)}`, + ) setResolvedCache(id, resolved, targetWeb) return resolved } @@ -1198,8 +1192,7 @@ function tryResolveBrowserMapping( ? tryNodeResolve(browserMappedPath, importer, options, true)?.id : tryFsResolve(path.join(pkg.dir, browserMappedPath), options)) ) { - isDebug && - debug(`[browser mapped] ${colors.cyan(id)} -> ${colors.dim(res)}`) + debug?.(`[browser mapped] ${colors.cyan(id)} -> ${colors.dim(res)}`) const resPkg = findNearestPackageData( path.dirname(res), options.packageCache, diff --git a/packages/vite/src/node/server/hmr.ts b/packages/vite/src/node/server/hmr.ts index 9e693566366c5d..226ea5a365cda8 100644 --- a/packages/vite/src/node/server/hmr.ts +++ b/packages/vite/src/node/server/hmr.ts @@ -59,7 +59,7 @@ export async function handleHMRUpdate( (fileName === '.env' || fileName.startsWith('.env.')) if (isConfig || isConfigDependency || isEnv) { // auto restart server - debugHmr(`[config change] ${colors.dim(shortFile)}`) + debugHmr?.(`[config change] ${colors.dim(shortFile)}`) config.logger.info( colors.green( `${path.relative(process.cwd(), file)} changed, restarting server...`, @@ -78,7 +78,7 @@ export async function handleHMRUpdate( return } - debugHmr(`[file change] ${colors.dim(shortFile)}`) + debugHmr?.(`[file change] ${colors.dim(shortFile)}`) // (dev only) the client itself cannot be hot updated. if (file.startsWith(normalizedClientDir)) { @@ -123,7 +123,7 @@ export async function handleHMRUpdate( }) } else { // loaded but not in the module graph, probably not js - debugHmr(`[no modules matched] ${colors.dim(shortFile)}`) + debugHmr?.(`[no modules matched] ${colors.dim(shortFile)}`) } return } @@ -184,7 +184,7 @@ export function updateModules( } if (updates.length === 0) { - debugHmr(colors.yellow(`no update happened `) + colors.dim(file)) + debugHmr?.(colors.yellow(`no update happened `) + colors.dim(file)) return } @@ -241,7 +241,7 @@ function propagateUpdate( // if the imports of `node` have not been analyzed, then `node` has not // been loaded in the browser and we should stop propagation. if (node.id && node.isSelfAccepting === undefined) { - debugHmr( + debugHmr?.( `[propagate update] stop propagation because not analyzed: ${colors.dim( node.id, )}`, @@ -334,7 +334,7 @@ export function handlePrunedModules( const t = Date.now() mods.forEach((mod) => { mod.lastHMRTimestamp = t - debugHmr(`[dispose] ${colors.dim(mod.file)}`) + debugHmr?.(`[dispose] ${colors.dim(mod.file)}`) }) ws.send({ type: 'prune', diff --git a/packages/vite/src/node/server/middlewares/proxy.ts b/packages/vite/src/node/server/middlewares/proxy.ts index 2212c7e2d7f248..f07b93e0746223 100644 --- a/packages/vite/src/node/server/middlewares/proxy.ts +++ b/packages/vite/src/node/server/middlewares/proxy.ts @@ -98,7 +98,7 @@ export function proxyMiddleware( if (opts.rewrite) { req.url = opts.rewrite(url) } - debug(`${req.url} -> ws ${opts.target}`) + debug?.(`${req.url} -> ws ${opts.target}`) proxy.ws(req, socket, head) return } @@ -119,15 +119,15 @@ export function proxyMiddleware( const bypassResult = opts.bypass(req, res, opts) if (typeof bypassResult === 'string') { req.url = bypassResult - debug(`bypass: ${req.url} -> ${bypassResult}`) + debug?.(`bypass: ${req.url} -> ${bypassResult}`) return next() } else if (bypassResult === false) { - debug(`bypass: ${req.url} -> 404`) + debug?.(`bypass: ${req.url} -> 404`) return res.end(404) } } - debug(`${req.url} -> ${opts.target || opts.forward}`) + debug?.(`${req.url} -> ${opts.target || opts.forward}`) if (opts.rewrite) { req.url = opts.rewrite(req.url!) } diff --git a/packages/vite/src/node/server/middlewares/time.ts b/packages/vite/src/node/server/middlewares/time.ts index 1217361d84fb35..8d4b3e10c928a6 100644 --- a/packages/vite/src/node/server/middlewares/time.ts +++ b/packages/vite/src/node/server/middlewares/time.ts @@ -10,7 +10,7 @@ export function timeMiddleware(root: string): Connect.NextHandleFunction { const start = performance.now() const end = res.end res.end = (...args: readonly [any, any?, any?]) => { - logTime(`${timeFrom(start)} ${prettifyUrl(req.url!, root)}`) + logTime?.(`${timeFrom(start)} ${prettifyUrl(req.url!, root)}`) return end.call(res, ...args) } next() diff --git a/packages/vite/src/node/server/middlewares/transform.ts b/packages/vite/src/node/server/middlewares/transform.ts index b149c8e89fe9eb..0e83f997c9c892 100644 --- a/packages/vite/src/node/server/middlewares/transform.ts +++ b/packages/vite/src/node/server/middlewares/transform.ts @@ -38,7 +38,6 @@ import { import { getDepsOptimizer } from '../../optimizer' const debugCache = createDebugger('vite:cache') -const isDebug = !!process.env.DEBUG const knownIgnoreList = new Set(['/', '/favicon.ico']) @@ -185,7 +184,7 @@ export function transformMiddleware( (await moduleGraph.getModuleByUrl(url, false))?.transformResult ?.etag === ifNoneMatch ) { - isDebug && debugCache(`[304] ${prettifyUrl(url, root)}`) + debugCache?.(`[304] ${prettifyUrl(url, root)}`) res.statusCode = 304 return res.end() } diff --git a/packages/vite/src/node/server/pluginContainer.ts b/packages/vite/src/node/server/pluginContainer.ts index ce819ddb3537d2..76d9c422af45eb 100644 --- a/packages/vite/src/node/server/pluginContainer.ts +++ b/packages/vite/src/node/server/pluginContainer.ts @@ -141,7 +141,6 @@ export async function createPluginContainer( moduleGraph?: ModuleGraph, watcher?: FSWatcher, ): Promise { - const isDebug = process.env.DEBUG const { plugins, logger, @@ -159,10 +158,6 @@ export async function createPluginContainer( const debugPluginTransform = createDebugger('vite:plugin-transform', { onlyWhenFocused: 'vite:plugin', }) - const debugSourcemapCombineFlag = 'vite:sourcemap-combine' - const isDebugSourcemapCombineFocused = process.env.DEBUG?.includes( - debugSourcemapCombineFlag, - ) const debugSourcemapCombineFilter = process.env.DEBUG_VITE_SOURCEMAP_COMBINE_FILTER const debugSourcemapCombine = createDebugger('vite:sourcemap-combine', { @@ -512,7 +507,7 @@ export async function createPluginContainer( this.filename = filename this.originalCode = code if (inMap) { - if (isDebugSourcemapCombineFocused) { + if (debugSourcemapCombine) { // @ts-expect-error inject name for debug purpose inMap.name = '$inMap' } @@ -522,6 +517,7 @@ export async function createPluginContainer( _getCombinedSourcemap(createIfNull = false) { if ( + debugSourcemapCombine && debugSourcemapCombineFilter && this.filename.includes(debugSourcemapCombineFilter) ) { @@ -611,7 +607,7 @@ export async function createPluginContainer( ctx.ssr = !!ssr ctx._scan = scan ctx._resolveSkips = skip - const resolveStart = isDebug ? performance.now() : 0 + const resolveStart = debugPluginResolve ? performance.now() : 0 let id: string | null = null const partial: Partial = {} @@ -621,7 +617,7 @@ export async function createPluginContainer( ctx._activePlugin = plugin - const pluginResolveStart = isDebug ? performance.now() : 0 + const pluginResolveStart = debugPluginResolve ? performance.now() : 0 const handler = 'handler' in plugin.resolveId ? plugin.resolveId.handler @@ -642,18 +638,17 @@ export async function createPluginContainer( Object.assign(partial, result) } - isDebug && - debugPluginResolve( - timeFrom(pluginResolveStart), - plugin.name, - prettifyUrl(id, root), - ) + debugPluginResolve?.( + timeFrom(pluginResolveStart), + plugin.name, + prettifyUrl(id, root), + ) // resolveId() is hookFirst - first non-null result is returned. break } - if (isDebug && rawId !== id && !rawId.startsWith(FS_PREFIX)) { + if (debugResolve && rawId !== id && !rawId.startsWith(FS_PREFIX)) { const key = rawId + id // avoid spamming if (!seenResolves[key]) { @@ -704,7 +699,7 @@ export async function createPluginContainer( ctx._activePlugin = plugin ctx._activeId = id ctx._activeCode = code - const start = isDebug ? performance.now() : 0 + const start = debugPluginTransform ? performance.now() : 0 let result: TransformResult | string | undefined const handler = 'handler' in plugin.transform @@ -716,17 +711,16 @@ export async function createPluginContainer( ctx.error(e) } if (!result) continue - isDebug && - debugPluginTransform( - timeFrom(start), - plugin.name, - prettifyUrl(id, root), - ) + debugPluginTransform?.( + timeFrom(start), + plugin.name, + prettifyUrl(id, root), + ) if (isObject(result)) { if (result.code !== undefined) { code = result.code if (result.map) { - if (isDebugSourcemapCombineFocused) { + if (debugSourcemapCombine) { // @ts-expect-error inject plugin name for debug purpose result.map.name = plugin.name } diff --git a/packages/vite/src/node/server/sourcemap.ts b/packages/vite/src/node/server/sourcemap.ts index c988a02fca8b18..a1494fa01de223 100644 --- a/packages/vite/src/node/server/sourcemap.ts +++ b/packages/vite/src/node/server/sourcemap.ts @@ -4,7 +4,6 @@ import type { ExistingRawSourceMap, SourceMap } from 'rollup' import type { Logger } from '../logger' import { createDebugger } from '../utils' -const isDebug = !!process.env.DEBUG const debug = createDebugger('vite:sourcemap', { onlyWhenFocused: true, }) @@ -55,7 +54,7 @@ export async function injectSourcesContent( // …to log the missing sources. if (missingSources.length) { logger.warnOnce(`Sourcemap for "${file}" points to missing source files`) - isDebug && debug(`Missing sources:\n ` + missingSources.join(`\n `)) + debug?.(`Missing sources:\n ` + missingSources.join(`\n `)) } } @@ -71,7 +70,7 @@ export function getCodeWithSourcemap( code: string, map: SourceMap, ): string { - if (isDebug) { + if (debug) { code += `\n/*${JSON.stringify(map, null, 2).replace(/\*\//g, '*\\/')}*/\n` } diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index 3762c69cfef3b3..b08a01e5d01b9e 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -27,7 +27,6 @@ export const ERR_LOAD_PUBLIC_URL = 'ERR_LOAD_PUBLIC_URL' const debugLoad = createDebugger('vite:load') const debugTransform = createDebugger('vite:transform') const debugCache = createDebugger('vite:cache') -const isDebug = !!process.env.DEBUG export interface TransformResult { code: string @@ -123,7 +122,7 @@ async function doTransform( url = removeTimestampQuery(url) const { config, pluginContainer } = server - const prettyUrl = isDebug ? prettifyUrl(url, config.root) : '' + const prettyUrl = debugCache ? prettifyUrl(url, config.root) : '' const ssr = !!options.ssr const module = await server.moduleGraph.getModuleByUrl(url, ssr) @@ -138,7 +137,7 @@ async function doTransform( // in this case, we can reuse its previous cached result and only update // its import timestamps. - isDebug && debugCache(`[memory] ${prettyUrl}`) + debugCache?.(`[memory] ${prettyUrl}`) return cached } @@ -164,7 +163,8 @@ async function loadAndTransform( ) { const { config, pluginContainer, moduleGraph, watcher } = server const { root, logger } = config - const prettyUrl = isDebug ? prettifyUrl(url, config.root) : '' + const prettyUrl = + debugLoad || debugTransform ? prettifyUrl(url, config.root) : '' const ssr = !!options.ssr const file = cleanUrl(id) @@ -173,7 +173,7 @@ async function loadAndTransform( let map: SourceDescription['map'] = null // load - const loadStart = isDebug ? performance.now() : 0 + const loadStart = debugLoad ? performance.now() : 0 const loadResult = await pluginContainer.load(id, { ssr }) if (loadResult == null) { // if this is an html request and there is no load result, skip ahead to @@ -189,7 +189,7 @@ async function loadAndTransform( if (options.ssr || isFileServingAllowed(file, server)) { try { code = await fs.readFile(file, 'utf-8') - isDebug && debugLoad(`${timeFrom(loadStart)} [fs] ${prettyUrl}`) + debugLoad?.(`${timeFrom(loadStart)} [fs] ${prettyUrl}`) } catch (e) { if (e.code !== 'ENOENT') { throw e @@ -214,7 +214,7 @@ async function loadAndTransform( } } } else { - isDebug && debugLoad(`${timeFrom(loadStart)} [plugin] ${prettyUrl}`) + debugLoad?.(`${timeFrom(loadStart)} [plugin] ${prettyUrl}`) if (isObject(loadResult)) { code = loadResult.code map = loadResult.map @@ -247,7 +247,7 @@ async function loadAndTransform( ensureWatchedFile(watcher, mod.file, root) // transform - const transformStart = isDebug ? performance.now() : 0 + const transformStart = debugTransform ? performance.now() : 0 const transformResult = await pluginContainer.transform(code, id, { inMap: map, ssr, @@ -258,12 +258,11 @@ async function loadAndTransform( (isObject(transformResult) && transformResult.code == null) ) { // no transform applied, keep code as-is - isDebug && - debugTransform( - timeFrom(transformStart) + colors.dim(` [skipped] ${prettyUrl}`), - ) + debugTransform?.( + timeFrom(transformStart) + colors.dim(` [skipped] ${prettyUrl}`), + ) } else { - isDebug && debugTransform(`${timeFrom(transformStart)} ${prettyUrl}`) + debugTransform?.(`${timeFrom(transformStart)} ${prettyUrl}`) code = transformResult.code! map = transformResult.map } diff --git a/packages/vite/src/node/ssr/ssrExternal.ts b/packages/vite/src/node/ssr/ssrExternal.ts index af3349235f9d4d..7fd01d5a878642 100644 --- a/packages/vite/src/node/ssr/ssrExternal.ts +++ b/packages/vite/src/node/ssr/ssrExternal.ts @@ -146,7 +146,7 @@ export function createIsConfiguredAsSsrExternal( !!configuredAsExternal, )?.external } catch (e) { - debug( + debug?.( `Failed to node resolve "${id}". Skipping externalizing it by default.`, ) // may be an invalid import that's resolved by a plugin @@ -273,7 +273,7 @@ function cjsSsrCollectExternals( } // resolve failed, assume include - debug(`Failed to resolve entries for package "${id}"\n`, e) + debug?.(`Failed to resolve entries for package "${id}"\n`, e) continue } // no esm entry but has require entry diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 3f52cda0e53565..ba4c6a28a11837 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -175,19 +175,22 @@ export type ViteDebugScope = `vite:${string}` export function createDebugger( namespace: ViteDebugScope, options: DebuggerOptions = {}, -): debug.Debugger['log'] { +): debug.Debugger['log'] | undefined { const log = debug(namespace) const { onlyWhenFocused } = options - const focus = - typeof onlyWhenFocused === 'string' ? onlyWhenFocused : namespace - return (msg: string, ...args: any[]) => { - if (filter && !msg.includes(filter)) { - return - } - if (onlyWhenFocused && !DEBUG?.includes(focus)) { - return + + let enabled = log.enabled + if (enabled && onlyWhenFocused) { + const ns = typeof onlyWhenFocused === 'string' ? onlyWhenFocused : namespace + enabled = !!DEBUG?.includes(ns) + } + + if (enabled) { + return (msg: string, ...args: any[]) => { + if (!filter || msg.includes(filter)) { + log(msg, ...args) + } } - log(msg, ...args) } } From 8bef662054eef694e716eb1c56b122eca5303ddd Mon Sep 17 00:00:00 2001 From: sun0day Date: Wed, 5 Apr 2023 10:40:43 +0800 Subject: [PATCH 31/96] chore(optimizer): show full optimized deps list (#12686) --- packages/vite/src/node/optimizer/index.ts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index c4a3f199f291d9..b3263af1e37cf2 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -437,18 +437,7 @@ export function toDiscoveredDependencies( } export function depsLogString(qualifiedIds: string[]): string { - if (debug) { - return colors.yellow(qualifiedIds.join(`, `)) - } else { - const total = qualifiedIds.length - const maxListed = 5 - const listed = Math.min(total, maxListed) - const extra = Math.max(0, total - maxListed) - return colors.yellow( - qualifiedIds.slice(0, listed).join(`, `) + - (extra > 0 ? `, ...and ${extra} more` : ``), - ) - } + return colors.yellow(qualifiedIds.join(`, `)) } /** From 77bf4efa3940801b77beb847f891e7831bb04810 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Wed, 5 Apr 2023 14:04:02 +0800 Subject: [PATCH 32/96] perf: use package cache for one off resolve (#12744) --- packages/vite/src/node/config.ts | 1 + packages/vite/src/node/optimizer/index.ts | 1 + packages/vite/src/node/plugins/assetImportMetaUrl.ts | 2 ++ 3 files changed, 4 insertions(+) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 6440dc5a058457..f8349751505fa8 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -1001,6 +1001,7 @@ async function bundleConfigFile( dedupe: [], extensions: DEFAULT_EXTENSIONS, preserveSymlinks: false, + packageCache: new Map(), } // externalize bare imports diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index b3263af1e37cf2..3649c89c58494c 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -867,6 +867,7 @@ function createOptimizeDepsIncludeResolver( scan: true, ssrOptimizeCheck: ssr, ssrConfig: config.ssr, + packageCache: new Map(), }) return async (id: string) => { const lastArrowIndex = id.lastIndexOf('>') diff --git a/packages/vite/src/node/plugins/assetImportMetaUrl.ts b/packages/vite/src/node/plugins/assetImportMetaUrl.ts index 7a22de3e31814b..6872de5249e014 100644 --- a/packages/vite/src/node/plugins/assetImportMetaUrl.ts +++ b/packages/vite/src/node/plugins/assetImportMetaUrl.ts @@ -10,6 +10,7 @@ import { slash, transformStableResult, } from '../utils' +import { CLIENT_ENTRY } from '../constants' import { fileToUrl } from './asset' import { preloadHelperId } from './importAnalysisBuild' @@ -33,6 +34,7 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin { if ( !options?.ssr && id !== preloadHelperId && + id !== CLIENT_ENTRY && code.includes('new URL') && code.includes(`import.meta.url`) ) { From 22f6ae6975afab41f08617810e35d73e5e1827a6 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Wed, 5 Apr 2023 15:16:44 +0800 Subject: [PATCH 33/96] chore: fix resolve debug log timing (#12746) --- packages/vite/src/node/server/pluginContainer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/server/pluginContainer.ts b/packages/vite/src/node/server/pluginContainer.ts index 76d9c422af45eb..38c057bbbf8c29 100644 --- a/packages/vite/src/node/server/pluginContainer.ts +++ b/packages/vite/src/node/server/pluginContainer.ts @@ -607,7 +607,7 @@ export async function createPluginContainer( ctx.ssr = !!ssr ctx._scan = scan ctx._resolveSkips = skip - const resolveStart = debugPluginResolve ? performance.now() : 0 + const resolveStart = debugResolve ? performance.now() : 0 let id: string | null = null const partial: Partial = {} From 3b912fbcc8a1b7b08b4f8aa2ba0b952a4d4c772b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnaud=20Barr=C3=A9?= Date: Wed, 5 Apr 2023 09:53:51 +0200 Subject: [PATCH 34/96] perf(hmr): keep track of already traversed modules when propagating update (#12658) --- packages/vite/src/node/server/hmr.ts | 45 +++++++++++++--------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/packages/vite/src/node/server/hmr.ts b/packages/vite/src/node/server/hmr.ts index 226ea5a365cda8..42badca778b453 100644 --- a/packages/vite/src/node/server/hmr.ts +++ b/packages/vite/src/node/server/hmr.ts @@ -140,6 +140,7 @@ export function updateModules( ): void { const updates: Update[] = [] const invalidatedModules = new Set() + const traversedModules = new Set() let needFullReload = false for (const mod of modules) { @@ -148,18 +149,15 @@ export function updateModules( continue } - const boundaries = new Set<{ - boundary: ModuleNode - acceptedVia: ModuleNode - }>() - const hasDeadEnd = propagateUpdate(mod, boundaries) + const boundaries: { boundary: ModuleNode; acceptedVia: ModuleNode }[] = [] + const hasDeadEnd = propagateUpdate(mod, traversedModules, boundaries) if (hasDeadEnd) { needFullReload = true continue } updates.push( - ...[...boundaries].map(({ boundary, acceptedVia }) => ({ + ...boundaries.map(({ boundary, acceptedVia }) => ({ type: `${boundary.type}-update` as const, timestamp, path: normalizeHmrUrl(boundary.url), @@ -231,12 +229,15 @@ function areAllImportsAccepted( function propagateUpdate( node: ModuleNode, - boundaries: Set<{ - boundary: ModuleNode - acceptedVia: ModuleNode - }>, + traversedModules: Set, + boundaries: { boundary: ModuleNode; acceptedVia: ModuleNode }[], currentChain: ModuleNode[] = [node], ): boolean /* hasDeadEnd */ { + if (traversedModules.has(node)) { + return false + } + traversedModules.add(node) + // #7561 // if the imports of `node` have not been analyzed, then `node` has not // been loaded in the browser and we should stop propagation. @@ -250,16 +251,18 @@ function propagateUpdate( } if (node.isSelfAccepting) { - boundaries.add({ - boundary: node, - acceptedVia: node, - }) + boundaries.push({ boundary: node, acceptedVia: node }) // additionally check for CSS importers, since a PostCSS plugin like // Tailwind JIT may register any file as a dependency to a CSS file. for (const importer of node.importers) { if (isCSSRequest(importer.url) && !currentChain.includes(importer)) { - propagateUpdate(importer, boundaries, currentChain.concat(importer)) + propagateUpdate( + importer, + traversedModules, + boundaries, + currentChain.concat(importer), + ) } } @@ -272,10 +275,7 @@ function propagateUpdate( // Also, the imported module (this one) must be updated before the importers, // so that they do get the fresh imported module when/if they are reloaded. if (node.acceptedHmrExports) { - boundaries.add({ - boundary: node, - acceptedVia: node, - }) + boundaries.push({ boundary: node, acceptedVia: node }) } else { if (!node.importers.size) { return true @@ -295,10 +295,7 @@ function propagateUpdate( for (const importer of node.importers) { const subChain = currentChain.concat(importer) if (importer.acceptedHmrDeps.has(node)) { - boundaries.add({ - boundary: importer, - acceptedVia: node, - }) + boundaries.push({ boundary: importer, acceptedVia: node }) continue } @@ -317,7 +314,7 @@ function propagateUpdate( return true } - if (propagateUpdate(importer, boundaries, subChain)) { + if (propagateUpdate(importer, traversedModules, boundaries, subChain)) { return true } } From 3a41bd8dbd0d5fcaddde71a6f20dae7e6ce5ef16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20Ayg=C3=BCn?= Date: Wed, 5 Apr 2023 10:55:20 +0300 Subject: [PATCH 35/96] feat: reuse existing style elements in dev (#12678) --- packages/vite/src/client/client.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index 1818dda65eef98..cb668832aa6f53 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -363,6 +363,13 @@ function waitForWindowShow() { } const sheetsMap = new Map() + +// collect existing style elements that may have been inserted during SSR +// to avoid FOUC or duplicate styles +document.querySelectorAll('style[data-vite-dev-id]').forEach((el) => { + sheetsMap.set(el.getAttribute('data-vite-dev-id')!, el as HTMLStyleElement) +}) + // all css imports should be inserted at the same position // because after build it will be a single css file let lastInsertedStyle: HTMLStyleElement | undefined From 4ffaeee2033531788bc6d4d2541b8b5e44352591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnaud=20Barr=C3=A9?= Date: Wed, 5 Apr 2023 09:55:59 +0200 Subject: [PATCH 36/96] feat(create-vite): stricter TS configs in templates (#12604) --- .../create-vite/template-lit-ts/tsconfig.json | 19 ++++++++++------- .../template-preact-ts/src/main.tsx | 2 +- .../template-preact-ts/tsconfig.json | 21 ++++++++++++------- .../create-vite/template-preact/src/main.jsx | 2 +- .../template-react-ts/src/main.tsx | 2 +- .../template-react-ts/tsconfig.json | 18 +++++++++------- .../create-vite/template-react/src/main.jsx | 2 +- .../template-vanilla-ts/src/main.ts | 2 +- .../template-vanilla-ts/tsconfig.json | 16 ++++++++------ .../create-vite/template-vue-ts/tsconfig.json | 21 ++++++++++++------- 10 files changed, 65 insertions(+), 40 deletions(-) diff --git a/packages/create-vite/template-lit-ts/tsconfig.json b/packages/create-vite/template-lit-ts/tsconfig.json index f7c83877a73947..75abdef2659446 100644 --- a/packages/create-vite/template-lit-ts/tsconfig.json +++ b/packages/create-vite/template-lit-ts/tsconfig.json @@ -1,18 +1,23 @@ { "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, "module": "ESNext", "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, "noEmit": true, + + /* Linting */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "moduleResolution": "bundler", - "isolatedModules": true, - "allowSyntheticDefaultImports": true, - "useDefineForClassFields": false, - "skipLibCheck": true + "noFallthroughCasesInSwitch": true }, "include": ["src"] } diff --git a/packages/create-vite/template-preact-ts/src/main.tsx b/packages/create-vite/template-preact-ts/src/main.tsx index e0ce3e9980eecd..125b2d586a34bc 100644 --- a/packages/create-vite/template-preact-ts/src/main.tsx +++ b/packages/create-vite/template-preact-ts/src/main.tsx @@ -1,5 +1,5 @@ import { render } from 'preact' -import { App } from './app' +import { App } from './app.tsx' import './index.css' render(, document.getElementById('app') as HTMLElement) diff --git a/packages/create-vite/template-preact-ts/tsconfig.json b/packages/create-vite/template-preact-ts/tsconfig.json index cfc4dec8c13935..21abced1d38ea6 100644 --- a/packages/create-vite/template-preact-ts/tsconfig.json +++ b/packages/create-vite/template-preact-ts/tsconfig.json @@ -1,20 +1,25 @@ { "compilerOptions": { - "target": "ESNext", + "target": "ES2020", "useDefineForClassFields": true, - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "allowJs": false, - "skipLibCheck": true, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true, - "strict": true, "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ "moduleResolution": "bundler", + "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", - "jsxImportSource": "preact" + "jsxImportSource": "preact", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/packages/create-vite/template-preact/src/main.jsx b/packages/create-vite/template-preact/src/main.jsx index be3fbce92b202b..b088b63d9dad7c 100644 --- a/packages/create-vite/template-preact/src/main.jsx +++ b/packages/create-vite/template-preact/src/main.jsx @@ -1,5 +1,5 @@ import { render } from 'preact' -import { App } from './app' +import { App } from './app.jsx' import './index.css' render(, document.getElementById('app')) diff --git a/packages/create-vite/template-react-ts/src/main.tsx b/packages/create-vite/template-react-ts/src/main.tsx index 791f139e242c70..91c03f3fb20c1e 100644 --- a/packages/create-vite/template-react-ts/src/main.tsx +++ b/packages/create-vite/template-react-ts/src/main.tsx @@ -1,6 +1,6 @@ import React from 'react' import ReactDOM from 'react-dom/client' -import App from './App' +import App from './App.tsx' import './index.css' ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( diff --git a/packages/create-vite/template-react-ts/tsconfig.json b/packages/create-vite/template-react-ts/tsconfig.json index d0a38be3ee33ba..c81ef9f382291a 100644 --- a/packages/create-vite/template-react-ts/tsconfig.json +++ b/packages/create-vite/template-react-ts/tsconfig.json @@ -1,19 +1,23 @@ { "compilerOptions": { "target": "ESNext", - "useDefineForClassFields": true, "lib": ["DOM", "DOM.Iterable", "ESNext"], - "allowJs": false, - "skipLibCheck": true, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true, - "strict": true, "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ "moduleResolution": "bundler", + "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react-jsx" + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/packages/create-vite/template-react/src/main.jsx b/packages/create-vite/template-react/src/main.jsx index 5cc599199a2091..54b39dd1d900e8 100644 --- a/packages/create-vite/template-react/src/main.jsx +++ b/packages/create-vite/template-react/src/main.jsx @@ -1,6 +1,6 @@ import React from 'react' import ReactDOM from 'react-dom/client' -import App from './App' +import App from './App.jsx' import './index.css' ReactDOM.createRoot(document.getElementById('root')).render( diff --git a/packages/create-vite/template-vanilla-ts/src/main.ts b/packages/create-vite/template-vanilla-ts/src/main.ts index 2f852a7cf8532f..791547b0d382f5 100644 --- a/packages/create-vite/template-vanilla-ts/src/main.ts +++ b/packages/create-vite/template-vanilla-ts/src/main.ts @@ -1,7 +1,7 @@ import './style.css' import typescriptLogo from './typescript.svg' import viteLogo from '/vite.svg' -import { setupCounter } from './counter' +import { setupCounter } from './counter.ts' document.querySelector('#app')!.innerHTML = `
diff --git a/packages/create-vite/template-vanilla-ts/tsconfig.json b/packages/create-vite/template-vanilla-ts/tsconfig.json index 08fa7f8a928ed9..75abdef2659446 100644 --- a/packages/create-vite/template-vanilla-ts/tsconfig.json +++ b/packages/create-vite/template-vanilla-ts/tsconfig.json @@ -1,19 +1,23 @@ { "compilerOptions": { - "target": "ESNext", + "target": "ES2020", "useDefineForClassFields": true, "module": "ESNext", - "lib": ["ESNext", "DOM"], + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ "moduleResolution": "bundler", - "strict": true, + "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, - "esModuleInterop": true, "noEmit": true, + + /* Linting */ + "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noImplicitReturns": true, - "skipLibCheck": true + "noFallthroughCasesInSwitch": true }, "include": ["src"] } diff --git a/packages/create-vite/template-vue-ts/tsconfig.json b/packages/create-vite/template-vue-ts/tsconfig.json index ffb2e9b4969404..f82888f3d0965c 100644 --- a/packages/create-vite/template-vue-ts/tsconfig.json +++ b/packages/create-vite/template-vue-ts/tsconfig.json @@ -1,17 +1,24 @@ { "compilerOptions": { - "target": "ESNext", + "target": "ES2020", "useDefineForClassFields": true, "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ "moduleResolution": "bundler", - "strict": true, - "jsx": "preserve", + "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, - "esModuleInterop": true, - "lib": ["ESNext", "DOM"], - "skipLibCheck": true, - "noEmit": true + "noEmit": true, + "jsx": "preserve", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true }, "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], "references": [{ "path": "./tsconfig.node.json" }] From 8e30025b76040a8b61cc2aa23aaa5f7054c5a9de Mon Sep 17 00:00:00 2001 From: sun0day Date: Wed, 5 Apr 2023 16:28:22 +0800 Subject: [PATCH 37/96] fix(css): css file emit synchronously (#12558) Co-authored-by: bluwy --- package.json | 2 +- packages/vite/package.json | 2 +- packages/vite/src/node/plugins/css.ts | 25 +++++- pnpm-lock.yaml | 110 +++++++++++++------------- 4 files changed, 81 insertions(+), 58 deletions(-) diff --git a/package.json b/package.json index 0964c0a12864c9..4efc4a6d453df0 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "prompts": "^2.4.2", "resolve": "^1.22.1", "rimraf": "^4.4.0", - "rollup": "^3.20.0", + "rollup": "^3.20.2", "semver": "^7.3.8", "simple-git-hooks": "^2.8.1", "tslib": "^2.5.0", diff --git a/packages/vite/package.json b/packages/vite/package.json index 0e4c5d5ab799c8..9829ee9ce9e4e7 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -69,7 +69,7 @@ "esbuild": "^0.17.5", "postcss": "^8.4.21", "resolve": "^1.22.1", - "rollup": "^3.20.0" + "rollup": "^3.20.2" }, "optionalDependencies": { "fsevents": "~2.3.2" diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index aa47b6b3bc93f8..d189ae06231d42 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -316,6 +316,8 @@ export function cssPlugin(config: ResolvedConfig): Plugin { export function cssPostPlugin(config: ResolvedConfig): Plugin { // styles initialization in buildStart causes a styling loss in watch const styles: Map = new Map() + // list of css emit tasks to guarantee the files are emitted in a deterministic order + let emitTasks: Promise[] = [] let pureCssChunks: Set // when there are multiple rollup outputs and extracting CSS, only emit once, @@ -353,6 +355,7 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { pureCssChunks = new Set() outputToExtractedCSSMap = new Map() hasEmitted = false + emitTasks = [] }, async transform(css, id, options) { @@ -563,7 +566,22 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { const cssFileName = ensureFileExt(cssAssetName, '.css') chunkCSS = resolveAssetUrlsInCss(chunkCSS, cssAssetName) - chunkCSS = await finalizeCss(chunkCSS, true, config) + + const previousTask = emitTasks[emitTasks.length - 1] + // finalizeCss is async which makes `emitFile` non-deterministic, so + // we use a `.then` to wait for previous tasks before finishing this + const thisTask = finalizeCss(chunkCSS, true, config).then((css) => { + chunkCSS = css + // make sure the previous task is also finished, this works recursively + return previousTask + }) + + // push this task so the next task can wait for this one + emitTasks.push(thisTask) + const emitTasksLength = emitTasks.length + + // wait for this and previous tasks to finish + await thisTask // emit corresponding css file const referenceId = this.emitFile({ @@ -577,6 +595,11 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { .get(config)! .set(referenceId, { originalName, isEntry }) chunk.viteMetadata!.importedCss.add(this.getFileName(referenceId)) + + if (emitTasksLength === emitTasks.length) { + // this is the last task, clear `emitTasks` to free up memory + emitTasks = [] + } } else if (!config.build.ssr) { // legacy build and inline css diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d8c41e9d10d4db..8900cb622457a2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,12 +9,12 @@ patchedDependencies: chokidar@3.5.3: hash: dzxbf3kgof5pdmbsyih2x43sq4 path: patches/chokidar@3.5.3.patch - sirv@2.0.2: - hash: hmoqtj4vy3i7wnpchga2a2mu3y - path: patches/sirv@2.0.2.patch dotenv-expand@9.0.0: hash: dccccn23nvejzy75sgiosdt2au path: patches/dotenv-expand@9.0.0.patch + sirv@2.0.2: + hash: hmoqtj4vy3i7wnpchga2a2mu3y + path: patches/sirv@2.0.2.patch importers: @@ -63,7 +63,7 @@ importers: prompts: ^2.4.2 resolve: ^1.22.1 rimraf: ^4.4.0 - rollup: ^3.20.0 + rollup: ^3.20.2 semver: ^7.3.8 simple-git-hooks: ^2.8.1 tslib: ^2.5.0 @@ -77,7 +77,7 @@ importers: devDependencies: '@babel/types': 7.21.3 '@microsoft/api-extractor': 7.34.4_@types+node@18.15.5 - '@rollup/plugin-typescript': 11.0.0_7sniqkrn5rmxrmax2dmiqcv3qu + '@rollup/plugin-typescript': 11.0.0_b72j35qsjh4lu3mgicjyqmc4ve '@types/babel__core': 7.20.0 '@types/babel__standalone': 7.1.4 '@types/convert-source-map': 2.0.0 @@ -118,7 +118,7 @@ importers: prompts: 2.4.2 resolve: 1.22.1 rimraf: 4.4.0 - rollup: 3.20.0 + rollup: 3.20.2 semver: 7.3.8 simple-git-hooks: 2.8.1 tslib: 2.5.0 @@ -219,7 +219,7 @@ importers: postcss-modules: ^6.0.0 resolve: ^1.22.1 resolve.exports: ^2.0.1 - rollup: ^3.20.0 + rollup: ^3.20.2 rollup-plugin-license: ^3.0.1 sirv: ^2.0.2 source-map-js: ^1.0.2 @@ -235,7 +235,7 @@ importers: esbuild: 0.17.5 postcss: 8.4.21 resolve: 1.22.1 - rollup: 3.20.0 + rollup: 3.20.2 optionalDependencies: fsevents: 2.3.2 devDependencies: @@ -243,13 +243,13 @@ importers: '@babel/parser': 7.21.3 '@babel/types': 7.21.3 '@jridgewell/trace-mapping': 0.3.17 - '@rollup/plugin-alias': 4.0.3_rollup@3.20.0 - '@rollup/plugin-commonjs': 24.0.1_rollup@3.20.0 - '@rollup/plugin-dynamic-import-vars': 2.0.3_rollup@3.20.0 - '@rollup/plugin-json': 6.0.0_rollup@3.20.0 - '@rollup/plugin-node-resolve': 15.0.1_rollup@3.20.0 - '@rollup/plugin-typescript': 11.0.0_rollup@3.20.0+tslib@2.5.0 - '@rollup/pluginutils': 5.0.2_rollup@3.20.0 + '@rollup/plugin-alias': 4.0.3_rollup@3.20.2 + '@rollup/plugin-commonjs': 24.0.1_rollup@3.20.2 + '@rollup/plugin-dynamic-import-vars': 2.0.3_rollup@3.20.2 + '@rollup/plugin-json': 6.0.0_rollup@3.20.2 + '@rollup/plugin-node-resolve': 15.0.1_rollup@3.20.2 + '@rollup/plugin-typescript': 11.0.0_rollup@3.20.2+tslib@2.5.0 + '@rollup/pluginutils': 5.0.2_rollup@3.20.2 '@types/pnpapi': 0.0.2 acorn: 8.8.2 acorn-walk: 8.2.0_acorn@8.8.2 @@ -285,7 +285,7 @@ importers: postcss-load-config: 4.0.1_postcss@8.4.21 postcss-modules: 6.0.0_postcss@8.4.21 resolve.exports: 2.0.1 - rollup-plugin-license: 3.0.1_rollup@3.20.0 + rollup-plugin-license: 3.0.1_rollup@3.20.2 sirv: 2.0.2_hmoqtj4vy3i7wnpchga2a2mu3y source-map-js: 1.0.2 source-map-support: 0.5.21 @@ -3177,7 +3177,7 @@ packages: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} dev: true - /@rollup/plugin-alias/4.0.3_rollup@3.20.0: + /@rollup/plugin-alias/4.0.3_rollup@3.20.2: resolution: {integrity: sha512-ZuDWE1q4PQDhvm/zc5Prun8sBpLJy41DMptYrS6MhAy9s9kL/doN1613BWfEchGVfKxzliJ3BjbOPizXX38DbQ==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3186,11 +3186,11 @@ packages: rollup: optional: true dependencies: - rollup: 3.20.0 + rollup: 3.20.2 slash: 4.0.0 dev: true - /@rollup/plugin-commonjs/24.0.1_rollup@3.20.0: + /@rollup/plugin-commonjs/24.0.1_rollup@3.20.2: resolution: {integrity: sha512-15LsiWRZk4eOGqvrJyu3z3DaBu5BhXIMeWnijSRvd8irrrg9SHpQ1pH+BUK4H6Z9wL9yOxZJMTLU+Au86XHxow==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3199,16 +3199,16 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.20.0 + '@rollup/pluginutils': 5.0.2_rollup@3.20.2 commondir: 1.0.1 estree-walker: 2.0.2 glob: 8.0.3 is-reference: 1.2.1 magic-string: 0.27.0 - rollup: 3.20.0 + rollup: 3.20.2 dev: true - /@rollup/plugin-dynamic-import-vars/2.0.3_rollup@3.20.0: + /@rollup/plugin-dynamic-import-vars/2.0.3_rollup@3.20.2: resolution: {integrity: sha512-0zQV0TDDewilU+7ZLmwc0u44SkeRxSxMdINBuX5isrQGJ6EdTjVL1TcnOZ9In99byaSGAQnHmSFw+6hm0E/jrw==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3217,14 +3217,14 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.20.0 + '@rollup/pluginutils': 5.0.2_rollup@3.20.2 estree-walker: 2.0.2 fast-glob: 3.2.12 magic-string: 0.27.0 - rollup: 3.20.0 + rollup: 3.20.2 dev: true - /@rollup/plugin-json/6.0.0_rollup@3.20.0: + /@rollup/plugin-json/6.0.0_rollup@3.20.2: resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3233,11 +3233,11 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.20.0 - rollup: 3.20.0 + '@rollup/pluginutils': 5.0.2_rollup@3.20.2 + rollup: 3.20.2 dev: true - /@rollup/plugin-node-resolve/15.0.1_rollup@3.20.0: + /@rollup/plugin-node-resolve/15.0.1_rollup@3.20.2: resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3246,16 +3246,16 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.20.0 + '@rollup/pluginutils': 5.0.2_rollup@3.20.2 '@types/resolve': 1.20.2 deepmerge: 4.2.2 is-builtin-module: 3.2.0 is-module: 1.0.0 resolve: 1.22.1 - rollup: 3.20.0 + rollup: 3.20.2 dev: true - /@rollup/plugin-replace/5.0.2_rollup@3.20.0: + /@rollup/plugin-replace/5.0.2_rollup@3.20.2: resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3264,12 +3264,12 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.20.0 + '@rollup/pluginutils': 5.0.2_rollup@3.20.2 magic-string: 0.27.0 - rollup: 3.20.0 + rollup: 3.20.2 dev: true - /@rollup/plugin-typescript/11.0.0_7sniqkrn5rmxrmax2dmiqcv3qu: + /@rollup/plugin-typescript/11.0.0_b72j35qsjh4lu3mgicjyqmc4ve: resolution: {integrity: sha512-goPyCWBiimk1iJgSTgsehFD5OOFHiAknrRJjqFCudcW8JtWiBlK284Xnn4flqMqg6YAjVG/EE+3aVzrL5qNSzQ==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3282,14 +3282,14 @@ packages: tslib: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.20.0 + '@rollup/pluginutils': 5.0.2_rollup@3.20.2 resolve: 1.22.1 - rollup: 3.20.0 + rollup: 3.20.2 tslib: 2.5.0 typescript: 5.0.2 dev: true - /@rollup/plugin-typescript/11.0.0_rollup@3.20.0+tslib@2.5.0: + /@rollup/plugin-typescript/11.0.0_rollup@3.20.2+tslib@2.5.0: resolution: {integrity: sha512-goPyCWBiimk1iJgSTgsehFD5OOFHiAknrRJjqFCudcW8JtWiBlK284Xnn4flqMqg6YAjVG/EE+3aVzrL5qNSzQ==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3302,13 +3302,13 @@ packages: tslib: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.20.0 + '@rollup/pluginutils': 5.0.2_rollup@3.20.2 resolve: 1.22.1 - rollup: 3.20.0 + rollup: 3.20.2 tslib: 2.5.0 dev: true - /@rollup/pluginutils/5.0.2_rollup@3.20.0: + /@rollup/pluginutils/5.0.2_rollup@3.20.2: resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3320,7 +3320,7 @@ packages: '@types/estree': 1.0.0 estree-walker: 2.0.2 picomatch: 2.3.1 - rollup: 3.20.0 + rollup: 3.20.2 dev: true /@rushstack/node-core-library/3.55.2_@types+node@18.15.5: @@ -8544,7 +8544,7 @@ packages: glob: 9.3.1 dev: true - /rollup-plugin-dts/5.3.0_pn5zetjg24cqcolt42iry5qj6a: + /rollup-plugin-dts/5.3.0_e7tciabaay7z2i5ycjdzz3zl6i: resolution: {integrity: sha512-8FXp0ZkyZj1iU5klkIJYLjIq/YZSwBoERu33QBDxm/1yw5UU4txrEtcmMkrq+ZiKu3Q4qvPCNqc3ovX6rjqzbQ==} engines: {node: '>=v14'} peerDependencies: @@ -8552,13 +8552,13 @@ packages: typescript: ^4.1 || ^5.0 dependencies: magic-string: 0.30.0 - rollup: 3.20.0 + rollup: 3.20.2 typescript: 4.9.5 optionalDependencies: '@babel/code-frame': 7.18.6 dev: true - /rollup-plugin-license/3.0.1_rollup@3.20.0: + /rollup-plugin-license/3.0.1_rollup@3.20.2: resolution: {integrity: sha512-/lec6Y94Y3wMfTDeYTO/jSXII0GQ/XkDZCiqkMKxyU5D5nGPaxr/2JNYvAgYsoCYuOLGOanKDPjCCQiTT96p7A==} engines: {node: '>=14.0.0'} peerDependencies: @@ -8571,13 +8571,13 @@ packages: mkdirp: 1.0.4 moment: 2.29.3 package-name-regex: 2.0.6 - rollup: 3.20.0 + rollup: 3.20.2 spdx-expression-validate: 2.0.0 spdx-satisfies: 5.0.1 dev: true - /rollup/3.20.0: - resolution: {integrity: sha512-YsIfrk80NqUDrxrjWPXUa7PWvAfegZEXHuPsEZg58fGCdjL1I9C1i/NaG+L+27kxxwkrG/QEDEQc8s/ynXWWGQ==} + /rollup/3.20.2: + resolution: {integrity: sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: @@ -9487,12 +9487,12 @@ packages: resolution: {integrity: sha512-EK5LeABThyn5KbX0eo5c7xKRQhnHVxKN8/e5Y+YQEf4ZobJB6OZ766756wbVqzIY/G/MvAfLbc6EwFPdSNnlpA==} hasBin: true dependencies: - '@rollup/plugin-alias': 4.0.3_rollup@3.20.0 - '@rollup/plugin-commonjs': 24.0.1_rollup@3.20.0 - '@rollup/plugin-json': 6.0.0_rollup@3.20.0 - '@rollup/plugin-node-resolve': 15.0.1_rollup@3.20.0 - '@rollup/plugin-replace': 5.0.2_rollup@3.20.0 - '@rollup/pluginutils': 5.0.2_rollup@3.20.0 + '@rollup/plugin-alias': 4.0.3_rollup@3.20.2 + '@rollup/plugin-commonjs': 24.0.1_rollup@3.20.2 + '@rollup/plugin-json': 6.0.0_rollup@3.20.2 + '@rollup/plugin-node-resolve': 15.0.1_rollup@3.20.2 + '@rollup/plugin-replace': 5.0.2_rollup@3.20.2 + '@rollup/pluginutils': 5.0.2_rollup@3.20.2 chalk: 5.2.0 consola: 2.15.3 defu: 6.1.2 @@ -9507,8 +9507,8 @@ packages: pathe: 1.1.0 pkg-types: 1.0.2 pretty-bytes: 6.1.0 - rollup: 3.20.0 - rollup-plugin-dts: 5.3.0_pn5zetjg24cqcolt42iry5qj6a + rollup: 3.20.2 + rollup-plugin-dts: 5.3.0_e7tciabaay7z2i5ycjdzz3zl6i scule: 1.0.0 typescript: 4.9.5 untyped: 1.2.2 From 1ea38e21c37cf8021940bd4554cc981ccfdcdf25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Wed, 5 Apr 2023 17:38:16 +0900 Subject: [PATCH 38/96] refactor: use `resolvePackageData` in `requireResolveFromRootWithFallback` (#12712) --- packages/vite/src/node/utils.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index ba4c6a28a11837..2bad4730961b62 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -3,7 +3,7 @@ import os from 'node:os' import path from 'node:path' import { exec } from 'node:child_process' import { createHash } from 'node:crypto' -import { URL, URLSearchParams } from 'node:url' +import { URL, URLSearchParams, fileURLToPath } from 'node:url' import { builtinModules, createRequire } from 'node:module' import { promises as dns } from 'node:dns' import { performance } from 'node:perf_hooks' @@ -34,6 +34,7 @@ import { import type { DepOptimizationConfig } from './optimizer' import type { ResolvedConfig } from './config' import type { ResolvedServerUrls, ViteDevServer } from './server' +import { resolvePackageData } from './packages' import type { CommonServerOptions } from '.' /** @@ -966,21 +967,25 @@ export function getHash(text: Buffer | string): string { return createHash('sha256').update(text).digest('hex').substring(0, 8) } +const _dirname = path.dirname(fileURLToPath(import.meta.url)) + export const requireResolveFromRootWithFallback = ( root: string, id: string, ): string => { - const paths = _require.resolve.paths?.(id) || [] - // Search in the root directory first, and fallback to the default require paths. - paths.unshift(root) - - // Use `resolve` package to check existence first, so if the package is not found, + // check existence first, so if the package is not found, // it won't be cached by nodejs, since there isn't a way to invalidate them: // https://github.com/nodejs/node/issues/44663 - resolve.sync(id, { basedir: root, paths }) + const found = resolvePackageData(id, root) || resolvePackageData(id, _dirname) + if (!found) { + const error = new Error(`${JSON.stringify(id)} not found.`) + ;(error as any).code = 'MODULE_NOT_FOUND' + throw error + } - // Use `require.resolve` again as the `resolve` package doesn't support the `exports` field - return _require.resolve(id, { paths }) + // actually resolve + // Search in the root directory first, and fallback to the default require paths. + return _require.resolve(id, { paths: [root, _dirname] }) } export function emptyCssComments(raw: string): string { From abe9274973386591c966804e87388ff829f8f613 Mon Sep 17 00:00:00 2001 From: sun0day Date: Wed, 5 Apr 2023 17:38:54 +0800 Subject: [PATCH 39/96] fix(server): delay ws server listen when restart (#12734) --- packages/vite/src/node/server/index.ts | 14 +++++- packages/vite/src/node/server/ws.ts | 64 +++++++++++++------------- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts index 74c45a57e8fb31..e43e81cdde17a0 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -338,6 +338,13 @@ export interface ResolvedServerUrls { export async function createServer( inlineConfig: InlineConfig = {}, +): Promise { + return _createServer(inlineConfig, { ws: true }) +} + +export async function _createServer( + inlineConfig: InlineConfig = {}, + options: { ws: boolean }, ): Promise { const config = await resolveConfig(inlineConfig, 'serve') @@ -699,6 +706,9 @@ export async function createServer( return listen(port, ...args) }) as any } else { + if (options.ws) { + ws.listen() + } await initServer() } @@ -832,7 +842,8 @@ async function restartServer(server: ViteDevServer) { let newServer = null try { - newServer = await createServer(inlineConfig) + // delay ws server listen + newServer = await _createServer(inlineConfig, { ws: false }) } catch (err: any) { server.config.logger.error(err.message, { timestamp: true, @@ -864,6 +875,7 @@ async function restartServer(server: ViteDevServer) { server.printUrls() } } else { + server.ws.listen() logger.info('server restarted.', { timestamp: true }) } diff --git a/packages/vite/src/node/server/ws.ts b/packages/vite/src/node/server/ws.ts index 0ccfbd8582233a..61d989080e7573 100644 --- a/packages/vite/src/node/server/ws.ts +++ b/packages/vite/src/node/server/ws.ts @@ -1,10 +1,10 @@ import type { Server } from 'node:http' -import { STATUS_CODES } from 'node:http' +import { STATUS_CODES, createServer as createHttpServer } from 'node:http' import type { ServerOptions as HttpsServerOptions } from 'node:https' import { createServer as createHttpsServer } from 'node:https' import type { Socket } from 'node:net' import colors from 'picocolors' -import type { ServerOptions, WebSocket as WebSocketRaw } from 'ws' +import type { WebSocket as WebSocketRaw } from 'ws' import { WebSocketServer as WebSocketServerRaw } from 'ws' import type { WebSocket as WebSocketTypes } from 'dep-types/ws' import type { CustomPayload, ErrorPayload, HMRPayload } from 'types/hmrPayload' @@ -20,6 +20,10 @@ export type WebSocketCustomListener = ( ) => void export interface WebSocketServer { + /** + * Listen on port and host + */ + listen(): void /** * Get all connected clients. */ @@ -83,7 +87,7 @@ export function createWebSocketServer( httpsOptions?: HttpsServerOptions, ): WebSocketServer { let wss: WebSocketServerRaw - let httpsServer: Server | undefined = undefined + let wsHttpServer: Server | undefined = undefined const hmr = isObject(config.server.hmr) && config.server.hmr const hmrServer = hmr && hmr.server @@ -93,6 +97,8 @@ export function createWebSocketServer( const wsServer = hmrServer || (portsAreCompatible && server) const customListeners = new Map>>() const clientsMap = new WeakMap() + const port = hmrPort || 24678 + const host = (hmr && hmr.host) || undefined if (wsServer) { wss = new WebSocketServerRaw({ noServer: true }) @@ -104,39 +110,28 @@ export function createWebSocketServer( } }) } else { - const websocketServerOptions: ServerOptions = {} - const port = hmrPort || 24678 - const host = (hmr && hmr.host) || undefined - if (httpsOptions) { - // if we're serving the middlewares over https, the ws library doesn't support automatically creating an https server, so we need to do it ourselves - // create an inline https server and mount the websocket server to it - httpsServer = createHttpsServer(httpsOptions, (req, res) => { - const statusCode = 426 - const body = STATUS_CODES[statusCode] - if (!body) - throw new Error( - `No body text found for the ${statusCode} status code`, - ) + // http server request handler keeps the same with + // https://github.com/websockets/ws/blob/45e17acea791d865df6b255a55182e9c42e5877a/lib/websocket-server.js#L88-L96 + const route = ((_, res) => { + const statusCode = 426 + const body = STATUS_CODES[statusCode] + if (!body) + throw new Error(`No body text found for the ${statusCode} status code`) - res.writeHead(statusCode, { - 'Content-Length': body.length, - 'Content-Type': 'text/plain', - }) - res.end(body) + res.writeHead(statusCode, { + 'Content-Length': body.length, + 'Content-Type': 'text/plain', }) - - httpsServer.listen(port, host) - websocketServerOptions.server = httpsServer + res.end(body) + }) as Parameters[1] + if (httpsOptions) { + wsHttpServer = createHttpsServer(httpsOptions, route) } else { - // we don't need to serve over https, just let ws handle its own server - websocketServerOptions.port = port - if (host) { - websocketServerOptions.host = host - } + wsHttpServer = createHttpServer(route) } - // vite dev server in middleware mode - wss = new WebSocketServerRaw(websocketServerOptions) + // need to call ws listen manually + wss = new WebSocketServerRaw({ server: wsHttpServer }) } wss.on('connection', (socket) => { @@ -210,6 +205,9 @@ export function createWebSocketServer( let bufferedError: ErrorPayload | null = null return { + listen: () => { + wsHttpServer?.listen(port, host) + }, on: ((event: string, fn: () => void) => { if (wsServerEvents.includes(event)) wss.on(event, fn) else { @@ -266,8 +264,8 @@ export function createWebSocketServer( if (err) { reject(err) } else { - if (httpsServer) { - httpsServer.close((err) => { + if (wsHttpServer) { + wsHttpServer.close((err) => { if (err) { reject(err) } else { From 9c37cc1148737458d0580353e37f1e746f766eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnaud=20Barr=C3=A9?= Date: Wed, 5 Apr 2023 11:43:16 +0200 Subject: [PATCH 40/96] chore: use @vitejs/release-scripts (#12682) --- package.json | 8 +- packages/create-vite/package.json | 3 +- .../__tests__/no-css-minify/vite.config.js | 3 +- pnpm-lock.yaml | 100 ++++++++-- scripts/publishCI.ts | 48 +---- scripts/release.ts | 152 +++----------- scripts/releaseUtils.ts | 186 +----------------- scripts/tsconfig.json | 2 +- 8 files changed, 125 insertions(+), 377 deletions(-) diff --git a/package.json b/package.json index 4efc4a6d453df0..ed2ad360dd5d30 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "@vitejs/vite-monorepo", "private": true, + "type": "module", "engines": { "node": "^14.18.0 || >=16.0.0" }, @@ -50,17 +51,15 @@ "@types/json-stable-stringify": "^1.0.34", "@types/less": "^3.0.3", "@types/micromatch": "^4.0.2", - "@types/minimist": "^1.2.2", "@types/node": "^18.15.5", "@types/picomatch": "^2.3.0", - "@types/prompts": "2.4.2", "@types/resolve": "^1.20.2", "@types/sass": "~1.43.1", - "@types/semver": "^7.3.13", "@types/stylus": "^0.48.38", "@types/ws": "^8.5.4", "@typescript-eslint/eslint-plugin": "^5.56.0", "@typescript-eslint/parser": "^5.56.0", + "@vitejs/release-scripts": "^1.1.0", "conventional-changelog-cli": "^2.2.2", "eslint": "^8.36.0", "eslint-define-config": "^1.17.0", @@ -71,16 +70,13 @@ "fast-glob": "^3.2.12", "fs-extra": "^11.1.1", "lint-staged": "^13.2.0", - "minimist": "^1.2.8", "npm-run-all": "^4.1.5", "picocolors": "^1.0.0", "playwright-chromium": "^1.31.2", "prettier": "2.8.5", - "prompts": "^2.4.2", "resolve": "^1.22.1", "rimraf": "^4.4.0", "rollup": "^3.20.2", - "semver": "^7.3.8", "simple-git-hooks": "^2.8.1", "tslib": "^2.5.0", "tsx": "^3.12.6", diff --git a/packages/create-vite/package.json b/packages/create-vite/package.json index 57f24d87f6ac7f..e5232c9bdf48f9 100644 --- a/packages/create-vite/package.json +++ b/packages/create-vite/package.json @@ -13,7 +13,6 @@ "template-*", "dist" ], - "main": "index.js", "scripts": { "dev": "unbuild --stub", "build": "unbuild", @@ -33,6 +32,8 @@ }, "homepage": "https://github.com/vitejs/vite/tree/main/packages/create-vite#readme", "devDependencies": { + "@types/minimist": "^1.2.2", + "@types/prompts": "^2.4.4", "cross-spawn": "^7.0.3", "kolorist": "^1.7.0", "minimist": "^1.2.8", diff --git a/playground/css/__tests__/no-css-minify/vite.config.js b/playground/css/__tests__/no-css-minify/vite.config.js index 260e7f253520be..0f9d18ad3ed221 100644 --- a/playground/css/__tests__/no-css-minify/vite.config.js +++ b/playground/css/__tests__/no-css-minify/vite.config.js @@ -1 +1,2 @@ -module.exports = require('../../vite.config-no-css-minify') +import config from '../../vite.config-no-css-minify' +export default config diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8900cb622457a2..9459b1c3d56402 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,17 +34,15 @@ importers: '@types/json-stable-stringify': ^1.0.34 '@types/less': ^3.0.3 '@types/micromatch': ^4.0.2 - '@types/minimist': ^1.2.2 '@types/node': ^18.15.5 '@types/picomatch': ^2.3.0 - '@types/prompts': 2.4.2 '@types/resolve': ^1.20.2 '@types/sass': ~1.43.1 - '@types/semver': ^7.3.13 '@types/stylus': ^0.48.38 '@types/ws': ^8.5.4 '@typescript-eslint/eslint-plugin': ^5.56.0 '@typescript-eslint/parser': ^5.56.0 + '@vitejs/release-scripts': ^1.1.0 conventional-changelog-cli: ^2.2.2 eslint: ^8.36.0 eslint-define-config: ^1.17.0 @@ -55,16 +53,13 @@ importers: fast-glob: ^3.2.12 fs-extra: ^11.1.1 lint-staged: ^13.2.0 - minimist: ^1.2.8 npm-run-all: ^4.1.5 picocolors: ^1.0.0 playwright-chromium: ^1.31.2 prettier: 2.8.5 - prompts: ^2.4.2 resolve: ^1.22.1 rimraf: ^4.4.0 rollup: ^3.20.2 - semver: ^7.3.8 simple-git-hooks: ^2.8.1 tslib: ^2.5.0 tsx: ^3.12.6 @@ -89,17 +84,15 @@ importers: '@types/json-stable-stringify': 1.0.34 '@types/less': 3.0.3 '@types/micromatch': 4.0.2 - '@types/minimist': 1.2.2 '@types/node': 18.15.5 '@types/picomatch': 2.3.0 - '@types/prompts': 2.4.2 '@types/resolve': 1.20.2 '@types/sass': 1.43.1 - '@types/semver': 7.3.13 '@types/stylus': 0.48.38 '@types/ws': 8.5.4 '@typescript-eslint/eslint-plugin': 5.56.0_2hcjazgfnbtq42tcc73br2vup4 '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + '@vitejs/release-scripts': 1.1.0 conventional-changelog-cli: 2.2.2 eslint: 8.36.0 eslint-define-config: 1.17.0 @@ -110,16 +103,13 @@ importers: fast-glob: 3.2.12 fs-extra: 11.1.1 lint-staged: 13.2.0 - minimist: 1.2.8 npm-run-all: 4.1.5 picocolors: 1.0.0 playwright-chromium: 1.31.2 prettier: 2.8.5 - prompts: 2.4.2 resolve: 1.22.1 rimraf: 4.4.0 rollup: 3.20.2 - semver: 7.3.8 simple-git-hooks: 2.8.1 tslib: 2.5.0 tsx: 3.12.6 @@ -132,11 +122,15 @@ importers: packages/create-vite: specifiers: + '@types/minimist': ^1.2.2 + '@types/prompts': ^2.4.4 cross-spawn: ^7.0.3 kolorist: ^1.7.0 minimist: ^1.2.8 prompts: ^2.4.2 devDependencies: + '@types/minimist': 1.2.2 + '@types/prompts': 2.4.4 cross-spawn: 7.0.3 kolorist: 1.7.0 minimist: 1.2.8 @@ -3521,8 +3515,8 @@ packages: resolution: {integrity: sha512-2lqsQt1iXkiTqwuzw2SS50iduoPZNpV/ou4/vJD443C0weF63Gqd3ErGS811CBNMzLO64zVJ+tiyh+4yimdYkg==} dev: true - /@types/prompts/2.4.2: - resolution: {integrity: sha512-TwNx7qsjvRIUv/BCx583tqF5IINEVjCNqg9ofKHRlSoUHE62WBHrem4B1HGXcIrG511v29d1kJ9a/t2Esz7MIg==} + /@types/prompts/2.4.4: + resolution: {integrity: sha512-p5N9uoTH76lLvSAaYSZtBCdEXzpOOufsRjnhjVSrZGXikVGHX9+cc9ERtHRV4hvBKHyZb1bg4K+56Bd2TqUn4A==} dependencies: '@types/node': 18.15.5 kleur: 3.0.3 @@ -3713,6 +3707,17 @@ packages: vue: 3.2.47 dev: true + /@vitejs/release-scripts/1.1.0: + resolution: {integrity: sha512-pxP72AGDRGu6vufj8vrdmFll++N0K7aNDSWWYzPb28NgE5RjOdo99uLgJEpl3Ee/wEOnHKT2zJ9HN2GN44SUPQ==} + dependencies: + execa: 6.1.0 + minimist: 1.2.8 + picocolors: 1.0.0 + prompts: 2.4.2 + publint: 0.1.11 + semver: 7.3.8 + dev: true + /@vitest/expect/0.29.7: resolution: {integrity: sha512-UtG0tW0DP6b3N8aw7PHmweKDsvPv4wjGvrVZW7OSxaFg76ShtVdMiMcUkZJgCE8QWUmhwaM0aQhbbVLo4F4pkA==} dependencies: @@ -5746,6 +5751,21 @@ packages: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} dev: true + /execa/6.1.0: + resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 3.0.1 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 3.0.7 + strip-final-newline: 3.0.0 + dev: true + /execa/7.1.1: resolution: {integrity: sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==} engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} @@ -6366,6 +6386,11 @@ packages: - supports-color dev: false + /human-signals/3.0.1: + resolution: {integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==} + engines: {node: '>=12.20.0'} + dev: true + /human-signals/4.3.0: resolution: {integrity: sha512-zyzVyMjpGBX2+6cDVZeFPCdtOtdsxOeseRhB9tkQ6xXmGUNrcnBzdEKPy3VPNYz+4gy1oukVOXcrJCunSyc6QQ==} engines: {node: '>=14.18.0'} @@ -6394,6 +6419,13 @@ packages: postcss: 8.4.21 dev: true + /ignore-walk/5.0.1: + resolution: {integrity: sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + minimatch: 5.1.0 + dev: true + /ignore/5.2.0: resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} engines: {node: '>= 4'} @@ -7510,6 +7542,29 @@ packages: resolution: {integrity: sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==} dev: false + /npm-bundled/2.0.1: + resolution: {integrity: sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + npm-normalize-package-bin: 2.0.0 + dev: true + + /npm-normalize-package-bin/2.0.0: + resolution: {integrity: sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dev: true + + /npm-packlist/5.1.3: + resolution: {integrity: sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + dependencies: + glob: 8.0.3 + ignore-walk: 5.0.1 + npm-bundled: 2.0.1 + npm-normalize-package-bin: 2.0.0 + dev: true + /npm-run-all/4.1.5: resolution: {integrity: sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==} engines: {node: '>= 4'} @@ -8135,6 +8190,16 @@ packages: dev: true optional: true + /publint/0.1.11: + resolution: {integrity: sha512-sD0rtIEadks83MkpomJswBO/YHExJLkta1TyqUhb0/aVV+o3ZlVnwsDPjCAow8tpfxmLGutCSLWq32yfhPB98w==} + engines: {node: '>=16'} + hasBin: true + dependencies: + npm-packlist: 5.1.3 + picocolors: 1.0.0 + sade: 1.8.1 + dev: true + /pug-attrs/3.0.0: resolution: {integrity: sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==} dependencies: @@ -8594,6 +8659,13 @@ packages: tslib: 2.5.0 dev: true + /sade/1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + dependencies: + mri: 1.2.0 + dev: true + /safe-buffer/5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} dev: true diff --git a/scripts/publishCI.ts b/scripts/publishCI.ts index 02dbef74908032..a6d83385739ae6 100644 --- a/scripts/publishCI.ts +++ b/scripts/publishCI.ts @@ -1,47 +1,3 @@ -import semver from 'semver' -import { - args, - getActiveVersion, - getPackageInfo, - publishPackage, - step, -} from './releaseUtils' +import { publish } from '@vitejs/release-scripts' -async function main() { - const tag = args._[0] - - if (!tag) { - throw new Error('No tag specified') - } - - let pkgName = 'vite' - let version - - if (tag.includes('@')) [pkgName, version] = tag.split('@') - else version = tag - - if (version.startsWith('v')) version = version.slice(1) - - const { currentVersion, pkgDir } = getPackageInfo(pkgName) - if (currentVersion !== version) - throw new Error( - `Package version from tag "${version}" mismatches with current version "${currentVersion}"`, - ) - - const activeVersion = await getActiveVersion(pkgName) - - step('Publishing package...') - const releaseTag = version.includes('beta') - ? 'beta' - : version.includes('alpha') - ? 'alpha' - : semver.lt(currentVersion, activeVersion) - ? 'previous' - : undefined - await publishPackage(pkgDir, releaseTag) -} - -main().catch((err) => { - console.error(err) - process.exit(1) -}) +publish({ defaultPackage: 'vite' }) diff --git a/scripts/release.ts b/scripts/release.ts index b17f328518bcf1..5226cfc51e2083 100644 --- a/scripts/release.ts +++ b/scripts/release.ts @@ -1,128 +1,28 @@ -import prompts from 'prompts' -import semver from 'semver' +import { release } from '@vitejs/release-scripts' import colors from 'picocolors' -import { - args, - getPackageInfo, - getVersionChoices, - isDryRun, - logRecentCommits, - packages, - run, - runIfNotDry, - step, - updateTemplateVersions, - updateVersion, -} from './releaseUtils' - -async function main(): Promise { - let targetVersion: string | undefined - - const { pkg }: { pkg: string } = await prompts({ - type: 'select', - name: 'pkg', - message: 'Select package', - choices: packages.map((i) => ({ value: i, title: i })), - }) - - if (!pkg) return - - await logRecentCommits(pkg) - - const { currentVersion, pkgName, pkgPath, pkgDir } = getPackageInfo(pkg) - - if (!targetVersion) { - const { release }: { release: string } = await prompts({ - type: 'select', - name: 'release', - message: 'Select release type', - choices: getVersionChoices(currentVersion), - }) - - if (release === 'custom') { - const res: { version: string } = await prompts({ - type: 'text', - name: 'version', - message: 'Input custom version', - initial: currentVersion, - }) - targetVersion = res.version - } else { - targetVersion = release - } - } - - if (!semver.valid(targetVersion)) { - throw new Error(`invalid target version: ${targetVersion}`) - } - - const tag = - pkgName === 'vite' ? `v${targetVersion}` : `${pkgName}@${targetVersion}` - - if (targetVersion.includes('beta') && !args.tag) { - args.tag = 'beta' - } - if (targetVersion.includes('alpha') && !args.tag) { - args.tag = 'alpha' - } - - const { yes }: { yes: boolean } = await prompts({ - type: 'confirm', - name: 'yes', - message: `Releasing ${colors.yellow(tag)} Confirm?`, - }) - - if (!yes) { - return - } - - step('\nUpdating package version...') - updateVersion(pkgPath, targetVersion) - if (pkgName === 'create-vite') updateTemplateVersions() - - step('\nGenerating changelog...') - const changelogArgs = [ - 'conventional-changelog', - '-p', - 'angular', - '-i', - 'CHANGELOG.md', - '-s', - '--commit-path', - '.', - ] - if (pkgName !== 'vite') changelogArgs.push('--lerna-package', pkgName) - await run('npx', changelogArgs, { cwd: pkgDir }) - - const { stdout } = await run('git', ['diff'], { stdio: 'pipe' }) - if (stdout) { - step('\nCommitting changes...') - await runIfNotDry('git', ['add', '-A']) - await runIfNotDry('git', ['commit', '-m', `release: ${tag}`]) - await runIfNotDry('git', ['tag', tag]) - } else { - console.log('No changes to commit.') - return - } - - step('\nPushing to GitHub...') - await runIfNotDry('git', ['push', 'origin', `refs/tags/${tag}`]) - await runIfNotDry('git', ['push']) - - if (isDryRun) { - console.log(`\nDry run finished - run git diff to see package changes.`) - } else { - console.log( - colors.green( - '\nPushed, publishing should starts shortly on CI.\nhttps://github.com/vitejs/vite/actions/workflows/publish.yml', - ), - ) - } - - console.log() -} - -main().catch((err) => { - console.error(err) - process.exit(1) +import { logRecentCommits, run, updateTemplateVersions } from './releaseUtils' + +release({ + repo: 'vite', + packages: ['vite', 'create-vite', 'plugin-legacy'], + toTag: (pkg, version) => + pkg === 'vite' ? `v${version}` : `${pkg}@${version}`, + logChangelog: (pkg) => logRecentCommits(pkg), + generateChangelog: async (pkgName) => { + if (pkgName === 'create-vite') await updateTemplateVersions() + + console.log(colors.cyan('\nGenerating changelog...')) + const changelogArgs = [ + 'conventional-changelog', + '-p', + 'angular', + '-i', + 'CHANGELOG.md', + '-s', + '--commit-path', + '.', + ] + if (pkgName !== 'vite') changelogArgs.push('--lerna-package', pkgName) + await run('npx', changelogArgs, { cwd: `packages/${pkgName}` }) + }, }) diff --git a/scripts/releaseUtils.ts b/scripts/releaseUtils.ts index e971cdb24406cf..c2315ab883667f 100644 --- a/scripts/releaseUtils.ts +++ b/scripts/releaseUtils.ts @@ -1,71 +1,9 @@ -/** - * modified from https://github.com/vuejs/core/blob/master/scripts/release.js - */ -import { existsSync, readdirSync, writeFileSync } from 'node:fs' +import { readdirSync, writeFileSync } from 'node:fs' import path from 'node:path' import colors from 'picocolors' import type { Options as ExecaOptions, ExecaReturnValue } from 'execa' import { execa } from 'execa' -import type { ReleaseType } from 'semver' -import semver from 'semver' import fs from 'fs-extra' -import minimist from 'minimist' - -export const args = minimist(process.argv.slice(2)) - -export const isDryRun = !!args.dry - -if (isDryRun) { - console.log(colors.inverse(colors.yellow(' DRY RUN '))) - console.log() -} - -export const packages = ['vite', 'create-vite', 'plugin-legacy'] - -export const versionIncrements: ReleaseType[] = [ - 'patch', - 'minor', - 'major', - // 'prepatch', - // 'preminor', - // 'premajor', - // 'prerelease' -] - -interface Pkg { - name: string - version: string - private?: boolean -} -export function getPackageInfo(pkgName: string): { - pkg: Pkg - pkgName: string - pkgDir: string - pkgPath: string - currentVersion: string -} { - const pkgDir = path.resolve(__dirname, '../packages/' + pkgName) - - if (!existsSync(pkgDir)) { - throw new Error(`Package ${pkgName} not found`) - } - - const pkgPath = path.resolve(pkgDir, 'package.json') - const pkg: Pkg = require(pkgPath) - const currentVersion = pkg.version - - if (pkg.private) { - throw new Error(`Package ${pkgName} is private`) - } - - return { - pkg, - pkgName, - pkgDir, - pkgPath, - currentVersion, - } -} export async function run( bin: string, @@ -75,110 +13,6 @@ export async function run( return execa(bin, args, { stdio: 'inherit', ...opts }) } -export async function dryRun( - bin: string, - args: string[], - opts?: ExecaOptions, -): Promise { - return console.log( - colors.blue(`[dryrun] ${bin} ${args.join(' ')}`), - opts || '', - ) -} - -export const runIfNotDry = isDryRun ? dryRun : run - -export function step(msg: string): void { - return console.log(colors.cyan(msg)) -} - -interface VersionChoice { - title: string - value: string -} -export function getVersionChoices(currentVersion: string): VersionChoice[] { - const currentBeta = currentVersion.includes('beta') - const currentAlpha = currentVersion.includes('alpha') - const isStable = !currentBeta && !currentAlpha - - function inc(i: ReleaseType, tag = currentAlpha ? 'alpha' : 'beta') { - return semver.inc(currentVersion, i, tag)! - } - - let versionChoices: VersionChoice[] = [ - { - title: 'next', - value: inc(isStable ? 'patch' : 'prerelease'), - }, - ] - - if (isStable) { - versionChoices.push( - { - title: 'beta-minor', - value: inc('preminor'), - }, - { - title: 'beta-major', - value: inc('premajor'), - }, - { - title: 'alpha-minor', - value: inc('preminor', 'alpha'), - }, - { - title: 'alpha-major', - value: inc('premajor', 'alpha'), - }, - { - title: 'minor', - value: inc('minor'), - }, - { - title: 'major', - value: inc('major'), - }, - ) - } else if (currentAlpha) { - versionChoices.push({ - title: 'beta', - value: inc('patch') + '-beta.0', - }) - } else { - versionChoices.push({ - title: 'stable', - value: inc('patch'), - }) - } - versionChoices.push({ value: 'custom', title: 'custom' }) - - versionChoices = versionChoices.map((i) => { - i.title = `${i.title} (${i.value})` - return i - }) - - return versionChoices -} - -export function updateVersion(pkgPath: string, version: string): void { - const pkg = fs.readJSONSync(pkgPath) - pkg.version = version - writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n') -} - -export async function publishPackage( - pkdDir: string, - tag?: string, -): Promise { - const publicArgs = ['publish', '--access', 'public'] - if (tag) { - publicArgs.push(`--tag`, tag) - } - await runIfNotDry('npm', publicArgs, { - cwd: pkdDir, - }) -} - export async function getLatestTag(pkgName: string): Promise { const tags = (await run('git', ['tag'], { stdio: 'pipe' })).stdout .split(/\n/) @@ -190,15 +24,6 @@ export async function getLatestTag(pkgName: string): Promise { .reverse()[0] } -export async function getActiveVersion(pkgName: string): Promise { - const npmName = - pkgName === 'vite' || pkgName === 'create-vite' - ? pkgName - : `@vitejs/${pkgName}` - return (await run('npm', ['info', npmName, 'version'], { stdio: 'pipe' })) - .stdout -} - export async function logRecentCommits(pkgName: string): Promise { const tag = await getLatestTag(pkgName) if (!tag) return @@ -228,19 +53,16 @@ export async function logRecentCommits(pkgName: string): Promise { } export async function updateTemplateVersions(): Promise { - const viteVersion = ( - await fs.readJSON(path.resolve(__dirname, '../packages/vite/package.json')) - ).version + const viteVersion = fs.readJSONSync('packages/vite/package.json').version if (/beta|alpha|rc/.test(viteVersion)) return - const dir = path.resolve(__dirname, '../packages/create-vite') - + const dir = 'packages/create-vite' const templates = readdirSync(dir).filter((dir) => dir.startsWith('template-'), ) for (const template of templates) { const pkgPath = path.join(dir, template, `package.json`) - const pkg = require(pkgPath) + const pkg = fs.readJSONSync(pkgPath) pkg.devDependencies.vite = `^` + viteVersion writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n') } diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json index 06fd68cfc95572..359dd1aeafb2b3 100644 --- a/scripts/tsconfig.json +++ b/scripts/tsconfig.json @@ -2,7 +2,7 @@ "$schema": "https://json.schemastore.org/tsconfig", "include": ["."], "compilerOptions": { - "module": "CommonJS", + "module": "ES2020", "target": "ES2020", "moduleResolution": "Node", "strict": true, From a4341bca44f3c41d56fa2b8fef542d2114f4ac0f Mon Sep 17 00:00:00 2001 From: patak Date: Wed, 5 Apr 2023 11:57:31 +0200 Subject: [PATCH 41/96] release: v4.3.0-beta.2 --- packages/vite/CHANGELOG.md | 46 ++++++++++++++++++++++++++++++++++++++ packages/vite/package.json | 2 +- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/packages/vite/CHANGELOG.md b/packages/vite/CHANGELOG.md index a449e90d5e8647..19a7b19cbfef8b 100644 --- a/packages/vite/CHANGELOG.md +++ b/packages/vite/CHANGELOG.md @@ -1,3 +1,49 @@ +## 4.3.0-beta.2 (2023-04-05) + +* fix: avoid clean up while committing deps folder (#12722) ([3f4d109](https://github.com/vitejs/vite/commit/3f4d109)), closes [#12722](https://github.com/vitejs/vite/issues/12722) +* fix: ignore pnp resolve error (#12719) ([2d30ae5](https://github.com/vitejs/vite/commit/2d30ae5)), closes [#12719](https://github.com/vitejs/vite/issues/12719) +* fix: leave fully dynamic import.meta.url asset (fixes #10306) (#10549) ([56802b1](https://github.com/vitejs/vite/commit/56802b1)), closes [#10306](https://github.com/vitejs/vite/issues/10306) [#10549](https://github.com/vitejs/vite/issues/10549) +* fix: output combined sourcemap in importAnalysisBuild plugin (#12642) ([d051639](https://github.com/vitejs/vite/commit/d051639)), closes [#12642](https://github.com/vitejs/vite/issues/12642) +* fix: take in relative assets path fixes from rollup (#12695) ([81e44dd](https://github.com/vitejs/vite/commit/81e44dd)), closes [#12695](https://github.com/vitejs/vite/issues/12695) +* fix: throws error when plugin tries to resolve ID to external URL (#11731) ([49674b5](https://github.com/vitejs/vite/commit/49674b5)), closes [#11731](https://github.com/vitejs/vite/issues/11731) +* fix(css): css file emit synchronously (#12558) ([8e30025](https://github.com/vitejs/vite/commit/8e30025)), closes [#12558](https://github.com/vitejs/vite/issues/12558) +* fix(import-analysis): escape quotes correctly (#12688) ([1638ebd](https://github.com/vitejs/vite/commit/1638ebd)), closes [#12688](https://github.com/vitejs/vite/issues/12688) +* fix(optimizer): load the correct lock file (#12700) ([889eebe](https://github.com/vitejs/vite/commit/889eebe)), closes [#12700](https://github.com/vitejs/vite/issues/12700) +* fix(server): delay ws server listen when restart (#12734) ([abe9274](https://github.com/vitejs/vite/commit/abe9274)), closes [#12734](https://github.com/vitejs/vite/issues/12734) +* fix(ssr): load sourcemaps alongside modules (#11780) ([be95050](https://github.com/vitejs/vite/commit/be95050)), closes [#11780](https://github.com/vitejs/vite/issues/11780) +* fix(ssr): show ssr module loader error stack (#12651) ([050c0f9](https://github.com/vitejs/vite/commit/050c0f9)), closes [#12651](https://github.com/vitejs/vite/issues/12651) +* fix(worker): disable manifest plugins in worker build (#12661) ([20b8ef4](https://github.com/vitejs/vite/commit/20b8ef4)), closes [#12661](https://github.com/vitejs/vite/issues/12661) +* fix(worker): worker import.meta.url should not depends on document in iife mode (#12629) ([65f5ed2](https://github.com/vitejs/vite/commit/65f5ed2)), closes [#12629](https://github.com/vitejs/vite/issues/12629) +* refactor: `import.meta.url` condition from renderChunk hook of worker plugin (#12696) ([fdef8fd](https://github.com/vitejs/vite/commit/fdef8fd)), closes [#12696](https://github.com/vitejs/vite/issues/12696) +* refactor: clean up preTransformRequest (#12672) ([561227c](https://github.com/vitejs/vite/commit/561227c)), closes [#12672](https://github.com/vitejs/vite/issues/12672) +* refactor: make debugger nullable (#12687) ([89e4977](https://github.com/vitejs/vite/commit/89e4977)), closes [#12687](https://github.com/vitejs/vite/issues/12687) +* refactor: remove `ensureVolumeInPath` (#12690) ([a3150ee](https://github.com/vitejs/vite/commit/a3150ee)), closes [#12690](https://github.com/vitejs/vite/issues/12690) +* refactor: remove unused exports data props (#12740) ([4538bfe](https://github.com/vitejs/vite/commit/4538bfe)), closes [#12740](https://github.com/vitejs/vite/issues/12740) +* refactor: use `resolvePackageData` in `requireResolveFromRootWithFallback` (#12712) ([1ea38e2](https://github.com/vitejs/vite/commit/1ea38e2)), closes [#12712](https://github.com/vitejs/vite/issues/12712) +* refactor(css): simplify cached import code (#12730) ([0646754](https://github.com/vitejs/vite/commit/0646754)), closes [#12730](https://github.com/vitejs/vite/issues/12730) +* feat: reuse existing style elements in dev (#12678) ([3a41bd8](https://github.com/vitejs/vite/commit/3a41bd8)), closes [#12678](https://github.com/vitejs/vite/issues/12678) +* feat: skip pinging the server when the tab is not shown (#12698) ([bedcd8f](https://github.com/vitejs/vite/commit/bedcd8f)), closes [#12698](https://github.com/vitejs/vite/issues/12698) +* feat(create-vite): use typescript 5.0 in templates (#12481) ([8582e2d](https://github.com/vitejs/vite/commit/8582e2d)), closes [#12481](https://github.com/vitejs/vite/issues/12481) +* perf: avoid new URL() in hot path (#12654) ([f4e2fdf](https://github.com/vitejs/vite/commit/f4e2fdf)), closes [#12654](https://github.com/vitejs/vite/issues/12654) +* perf: improve isFileReadable performance (#12397) ([acf3a14](https://github.com/vitejs/vite/commit/acf3a14)), closes [#12397](https://github.com/vitejs/vite/issues/12397) +* perf: module graph url shortcuts (#12635) ([c268cfa](https://github.com/vitejs/vite/commit/c268cfa)), closes [#12635](https://github.com/vitejs/vite/issues/12635) +* perf: reduce runOptimizerIfIdleAfterMs time (#12614) ([d026a65](https://github.com/vitejs/vite/commit/d026a65)), closes [#12614](https://github.com/vitejs/vite/issues/12614) +* perf: shorcircuit resolve in ensure entry from url (#12655) ([82137d6](https://github.com/vitejs/vite/commit/82137d6)), closes [#12655](https://github.com/vitejs/vite/issues/12655) +* perf: skip es-module-lexer if have no dynamic imports (#12732) ([5d07d7c](https://github.com/vitejs/vite/commit/5d07d7c)), closes [#12732](https://github.com/vitejs/vite/issues/12732) +* perf: start preprocessing static imports before updating module graph (#12723) ([c90b46e](https://github.com/vitejs/vite/commit/c90b46e)), closes [#12723](https://github.com/vitejs/vite/issues/12723) +* perf: use package cache for one off resolve (#12744) ([77bf4ef](https://github.com/vitejs/vite/commit/77bf4ef)), closes [#12744](https://github.com/vitejs/vite/issues/12744) +* perf(css): cache lazy import (#12721) ([fedb080](https://github.com/vitejs/vite/commit/fedb080)), closes [#12721](https://github.com/vitejs/vite/issues/12721) +* perf(hmr): keep track of already traversed modules when propagating update (#12658) ([3b912fb](https://github.com/vitejs/vite/commit/3b912fb)), closes [#12658](https://github.com/vitejs/vite/issues/12658) +* perf(moduleGraph): resolve dep urls in parallel (#12619) ([4823fec](https://github.com/vitejs/vite/commit/4823fec)), closes [#12619](https://github.com/vitejs/vite/issues/12619) +* perf(resolve): skip for virtual files (#12638) ([9e13f5f](https://github.com/vitejs/vite/commit/9e13f5f)), closes [#12638](https://github.com/vitejs/vite/issues/12638) +* chore: fix resolve debug log timing (#12746) ([22f6ae6](https://github.com/vitejs/vite/commit/22f6ae6)), closes [#12746](https://github.com/vitejs/vite/issues/12746) +* chore: revert custom license resolve (#12709) ([621bb2f](https://github.com/vitejs/vite/commit/621bb2f)), closes [#12709](https://github.com/vitejs/vite/issues/12709) +* chore: set target in tsconfig.check.json (#12675) ([15177a1](https://github.com/vitejs/vite/commit/15177a1)), closes [#12675](https://github.com/vitejs/vite/issues/12675) +* chore(optimizer): remove redundant setTimeout call in scan process (#12718) ([0ce0e93](https://github.com/vitejs/vite/commit/0ce0e93)), closes [#12718](https://github.com/vitejs/vite/issues/12718) +* chore(optimizer): show full optimized deps list (#12686) ([8bef662](https://github.com/vitejs/vite/commit/8bef662)), closes [#12686](https://github.com/vitejs/vite/issues/12686) + + + ## 4.3.0-beta.1 (2023-03-29) * feat: use preview server parameter in preview server hook (#11647) ([4c142ea](https://github.com/vitejs/vite/commit/4c142ea)), closes [#11647](https://github.com/vitejs/vite/issues/11647) diff --git a/packages/vite/package.json b/packages/vite/package.json index 9829ee9ce9e4e7..291051b920736f 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -1,6 +1,6 @@ { "name": "vite", - "version": "4.3.0-beta.1", + "version": "4.3.0-beta.2", "type": "module", "license": "MIT", "author": "Evan You", From f736930b8bceacbe1f1cb7d9dfc8a7f5c010cc47 Mon Sep 17 00:00:00 2001 From: patak Date: Thu, 6 Apr 2023 07:26:38 +0200 Subject: [PATCH 42/96] fix: allow onwarn to override vite default warning handling (#12757) Co-authored-by: Anthony Fu --- packages/vite/src/node/build.ts | 58 +++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index aedbe282f11074..3cfea1943da8c8 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -871,40 +871,50 @@ export function onRollupWarning( warn: WarningHandler, config: ResolvedConfig, ): void { - if (warning.code === 'UNRESOLVED_IMPORT') { - const id = warning.id - const exporter = warning.exporter - // throw unless it's commonjs external... - if (!id || !/\?commonjs-external$/.test(id)) { - throw new Error( - `[vite]: Rollup failed to resolve import "${exporter}" from "${id}".\n` + - `This is most likely unintended because it can break your application at runtime.\n` + - `If you do want to externalize this module explicitly add it to\n` + - `\`build.rollupOptions.external\``, + function viteWarn(warning: RollupWarning) { + if (warning.code === 'UNRESOLVED_IMPORT') { + const id = warning.id + const exporter = warning.exporter + // throw unless it's commonjs external... + if (!id || !/\?commonjs-external$/.test(id)) { + throw new Error( + `[vite]: Rollup failed to resolve import "${exporter}" from "${id}".\n` + + `This is most likely unintended because it can break your application at runtime.\n` + + `If you do want to externalize this module explicitly add it to\n` + + `\`build.rollupOptions.external\``, + ) + } + } + + if ( + warning.plugin === 'rollup-plugin-dynamic-import-variables' && + dynamicImportWarningIgnoreList.some((msg) => + warning.message.includes(msg), ) + ) { + return } - } - if ( - warning.plugin === 'rollup-plugin-dynamic-import-variables' && - dynamicImportWarningIgnoreList.some((msg) => warning.message.includes(msg)) - ) { - return - } + if (!warningIgnoreList.includes(warning.code!)) { + return + } - if (!warningIgnoreList.includes(warning.code!)) { - const userOnWarn = config.build.rollupOptions?.onwarn - if (userOnWarn) { - userOnWarn(warning, warn) - } else if (warning.code === 'PLUGIN_WARNING') { + if (warning.code === 'PLUGIN_WARNING') { config.logger.warn( `${colors.bold( colors.yellow(`[plugin:${warning.plugin}]`), )} ${colors.yellow(warning.message)}`, ) - } else { - warn(warning) } + + warn(warning) + } + + const userOnWarn = config.build.rollupOptions?.onwarn + if (userOnWarn) { + userOnWarn(warning, viteWarn) + } else { + viteWarn(warning) } } From 037a6c77da04aeec7442e11765619b0ea4d846f9 Mon Sep 17 00:00:00 2001 From: patak Date: Thu, 6 Apr 2023 08:43:15 +0200 Subject: [PATCH 43/96] perf: parallelize imports processing in import analysis plugin (#12754) --- .../vite/src/node/plugins/importAnalysis.ts | 499 +++++++++--------- 1 file changed, 264 insertions(+), 235 deletions(-) diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 677394f587a46f..0a93e270213d99 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -80,6 +80,12 @@ const hasViteIgnoreRE = /\/\*\s*@vite-ignore\s*\*\// const cleanUpRawUrlRE = /\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm const urlIsStringRE = /^(?:'.*'|".*"|`.*`)$/ +interface UrlPosition { + url: string + start: number + end: number +} + export function isExplicitImportRequired(url: string): boolean { return !isJSRequest(cleanUrl(url)) && !isCSSRequest(url) } @@ -271,13 +277,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { let s: MagicString | undefined const str = () => s || (s = new MagicString(source)) const importedUrls = new Set() - const acceptedUrls = new Set<{ - url: string - start: number - end: number - }>() let isPartiallySelfAccepting = false - const acceptedExports = new Set() const importedBindings = enablePartialAccept ? new Map>() : null @@ -409,268 +409,288 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { return [url, resolved.id] } - for (let index = 0; index < imports.length; index++) { - const { - s: start, - e: end, - ss: expStart, - se: expEnd, - d: dynamicIndex, - // #2083 User may use escape path, - // so use imports[index].n to get the unescaped string - n: specifier, - a: assertIndex, - } = imports[index] - - const rawUrl = source.slice(start, end) - - // check import.meta usage - if (rawUrl === 'import.meta') { - const prop = source.slice(end, end + 4) - if (prop === '.hot') { - hasHMR = true - const endHot = end + 4 + (source[end + 4] === '?' ? 1 : 0) - if (source.slice(endHot, endHot + 7) === '.accept') { - // further analyze accepted modules - if (source.slice(endHot, endHot + 14) === '.acceptExports') { - lexAcceptedHmrExports( - source, - source.indexOf('(', endHot + 14) + 1, - acceptedExports, - ) - isPartiallySelfAccepting = true - } else if ( - lexAcceptedHmrDeps( - source, - source.indexOf('(', endHot + 7) + 1, - acceptedUrls, - ) - ) { - isSelfAccepting = true + const orderedAcceptedUrls = new Array | undefined>( + imports.length, + ) + const orderedAcceptedExports = new Array | undefined>( + imports.length, + ) + + await Promise.all( + imports.map(async (importSpecifier, index) => { + const { + s: start, + e: end, + ss: expStart, + se: expEnd, + d: dynamicIndex, + // #2083 User may use escape path, + // so use imports[index].n to get the unescaped string + n: specifier, + a: assertIndex, + } = importSpecifier + + const rawUrl = source.slice(start, end) + + // check import.meta usage + if (rawUrl === 'import.meta') { + const prop = source.slice(end, end + 4) + if (prop === '.hot') { + hasHMR = true + const endHot = end + 4 + (source[end + 4] === '?' ? 1 : 0) + if (source.slice(endHot, endHot + 7) === '.accept') { + // further analyze accepted modules + if (source.slice(endHot, endHot + 14) === '.acceptExports') { + const importAcceptedExports = (orderedAcceptedExports[index] = + new Set()) + lexAcceptedHmrExports( + source, + source.indexOf('(', endHot + 14) + 1, + importAcceptedExports, + ) + isPartiallySelfAccepting = true + } else { + const importAcceptedUrls = (orderedAcceptedUrls[index] = + new Set()) + if ( + lexAcceptedHmrDeps( + source, + source.indexOf('(', endHot + 7) + 1, + importAcceptedUrls, + ) + ) { + isSelfAccepting = true + } + } } + } else if (prop === '.env') { + hasEnv = true } - } else if (prop === '.env') { - hasEnv = true + return } - continue - } - const isDynamicImport = dynamicIndex > -1 + const isDynamicImport = dynamicIndex > -1 - // strip import assertions as we can process them ourselves - if (!isDynamicImport && assertIndex > -1) { - str().remove(end + 1, expEnd) - } - - // static import or valid string in dynamic import - // If resolvable, let's resolve it - if (specifier) { - // skip external / data uri - if (isExternalUrl(specifier) || isDataUrl(specifier)) { - continue + // strip import assertions as we can process them ourselves + if (!isDynamicImport && assertIndex > -1) { + str().remove(end + 1, expEnd) } - // skip ssr external - if (ssr) { - if (config.legacy?.buildSsrCjsExternalHeuristics) { - if (cjsShouldExternalizeForSSR(specifier, server._ssrExternals)) { - continue + + // static import or valid string in dynamic import + // If resolvable, let's resolve it + if (specifier) { + // skip external / data uri + if (isExternalUrl(specifier) || isDataUrl(specifier)) { + return + } + // skip ssr external + if (ssr) { + if (config.legacy?.buildSsrCjsExternalHeuristics) { + if ( + cjsShouldExternalizeForSSR(specifier, server._ssrExternals) + ) { + return + } + } else if (shouldExternalizeForSSR(specifier, config)) { + return + } + if (isBuiltin(specifier)) { + return } - } else if (shouldExternalizeForSSR(specifier, config)) { - continue } - if (isBuiltin(specifier)) { - continue + // skip client + if (specifier === clientPublicPath) { + return } - } - // skip client - if (specifier === clientPublicPath) { - continue - } - // warn imports to non-asset /public files - if ( - specifier[0] === '/' && - !config.assetsInclude(cleanUrl(specifier)) && - !specifier.endsWith('.json') && - checkPublicFile(specifier, config) - ) { - throw new Error( - `Cannot import non-asset file ${specifier} which is inside /public.` + - `JS/CSS files inside /public are copied as-is on build and ` + - `can only be referenced via diff --git a/playground/html/side-effects/package.json b/playground/html/side-effects/package.json new file mode 100644 index 00000000000000..72a1449164f79b --- /dev/null +++ b/playground/html/side-effects/package.json @@ -0,0 +1,6 @@ +{ + "name": "@vitejs/test-html-side-effects", + "private": true, + "version": "0.0.0", + "sideEffects": false +} diff --git a/playground/html/side-effects/sideEffects.js b/playground/html/side-effects/sideEffects.js new file mode 100644 index 00000000000000..6bfb77c68206c0 --- /dev/null +++ b/playground/html/side-effects/sideEffects.js @@ -0,0 +1 @@ +console.log('message from sideEffects script') diff --git a/playground/html/vite.config.js b/playground/html/vite.config.js index e6301ec5ebf4dd..c03421c16045b0 100644 --- a/playground/html/vite.config.js +++ b/playground/html/vite.config.js @@ -28,6 +28,7 @@ export default defineConfig({ valid: resolve(__dirname, 'valid.html'), importmapOrder: resolve(__dirname, 'importmapOrder.html'), env: resolve(__dirname, 'env.html'), + sideEffects: resolve(__dirname, 'side-effects/index.html'), }, }, }, From b91135c0096933c93bfc2ea4373724857c92b063 Mon Sep 17 00:00:00 2001 From: sun0day Date: Sat, 8 Apr 2023 02:02:39 +0800 Subject: [PATCH 59/96] test(css): deterministic css emit with the same file basename (#12773) --- .../same-file-name/same-file-name.spec.ts | 19 +++++++++++++++++++ .../__tests__/same-file-name/vite.config.js | 2 ++ playground/css/main.js | 3 +++ playground/css/same-name/sub1/sub.css | 3 +++ playground/css/same-name/sub1/sub.js | 3 +++ playground/css/same-name/sub2/sub.css | 3 +++ playground/css/same-name/sub2/sub.js | 3 +++ playground/css/vite.config-same-file-name.js | 17 +++++++++++++++++ 8 files changed, 53 insertions(+) create mode 100644 playground/css/__tests__/same-file-name/same-file-name.spec.ts create mode 100644 playground/css/__tests__/same-file-name/vite.config.js create mode 100644 playground/css/same-name/sub1/sub.css create mode 100644 playground/css/same-name/sub1/sub.js create mode 100644 playground/css/same-name/sub2/sub.css create mode 100644 playground/css/same-name/sub2/sub.js create mode 100644 playground/css/vite.config-same-file-name.js diff --git a/playground/css/__tests__/same-file-name/same-file-name.spec.ts b/playground/css/__tests__/same-file-name/same-file-name.spec.ts new file mode 100644 index 00000000000000..a0c9a115288135 --- /dev/null +++ b/playground/css/__tests__/same-file-name/same-file-name.spec.ts @@ -0,0 +1,19 @@ +import { beforeEach, describe, expect, test } from 'vitest' +import { findAssetFile, isBuild, startDefaultServe } from '~utils' + +beforeEach(async () => { + await startDefaultServe() +}) + +for (let i = 0; i < 5; i++) { + describe.runIf(isBuild)('css files has same basename', () => { + test('emit file name should consistent', () => { + expect(findAssetFile('sub.css', 'same-file-name', '.')).toMatch( + '.sub1-sub', + ) + expect(findAssetFile('sub2.css', 'same-file-name', '.')).toMatch( + '.sub2-sub', + ) + }) + }) +} diff --git a/playground/css/__tests__/same-file-name/vite.config.js b/playground/css/__tests__/same-file-name/vite.config.js new file mode 100644 index 00000000000000..c5c1f4f16874ad --- /dev/null +++ b/playground/css/__tests__/same-file-name/vite.config.js @@ -0,0 +1,2 @@ +import config from '../../vite.config-same-file-name' +export default config diff --git a/playground/css/main.js b/playground/css/main.js index 36fde9ff251589..4664ee1d2d8dde 100644 --- a/playground/css/main.js +++ b/playground/css/main.js @@ -117,3 +117,6 @@ document import './unsupported.css' import './async/index' + +import('./same-name/sub1/sub') +import('./same-name/sub2/sub') diff --git a/playground/css/same-name/sub1/sub.css b/playground/css/same-name/sub1/sub.css new file mode 100644 index 00000000000000..8eca4c3b9a7b6d --- /dev/null +++ b/playground/css/same-name/sub1/sub.css @@ -0,0 +1,3 @@ +.sub1-sub { + color: red; +} diff --git a/playground/css/same-name/sub1/sub.js b/playground/css/same-name/sub1/sub.js new file mode 100644 index 00000000000000..abe787e8e3c05d --- /dev/null +++ b/playground/css/same-name/sub1/sub.js @@ -0,0 +1,3 @@ +import './sub.css' + +export default 'sub1-name' diff --git a/playground/css/same-name/sub2/sub.css b/playground/css/same-name/sub2/sub.css new file mode 100644 index 00000000000000..910bf3898e5bfb --- /dev/null +++ b/playground/css/same-name/sub2/sub.css @@ -0,0 +1,3 @@ +.sub2-sub { + color: blue; +} diff --git a/playground/css/same-name/sub2/sub.js b/playground/css/same-name/sub2/sub.js new file mode 100644 index 00000000000000..3d338a64d0649f --- /dev/null +++ b/playground/css/same-name/sub2/sub.js @@ -0,0 +1,3 @@ +import './sub.css' + +export default 'sub2-name' diff --git a/playground/css/vite.config-same-file-name.js b/playground/css/vite.config-same-file-name.js new file mode 100644 index 00000000000000..f8e88d23b973be --- /dev/null +++ b/playground/css/vite.config-same-file-name.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import baseConfig from './vite.config.js' + +export default defineConfig({ + ...baseConfig, + build: { + ...baseConfig.build, + outDir: 'dist/same-file-name', + rollupOptions: { + output: { + entryFileNames: '[name].js', + chunkFileNames: '[name].[hash].js', + assetFileNames: '[name].[ext]', + }, + }, + }, +}) From 09350c69ada6a43b26241b99a0d4f8aa4283ade2 Mon Sep 17 00:00:00 2001 From: patak Date: Fri, 7 Apr 2023 20:12:23 +0200 Subject: [PATCH 60/96] chore: update lock --- pnpm-lock.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b9c47f2d0e4e91..f0d4ad1c4f32b3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -509,6 +509,9 @@ importers: playground/html: specifiers: {} + playground/html/side-effects: + specifiers: {} + playground/import-assertion: specifiers: '@vitejs/test-import-assertion-dep': file:./import-assertion-dep From fb904f97348119cc9d70bcc25c1ccd8eff4e0c90 Mon Sep 17 00:00:00 2001 From: patak Date: Sat, 8 Apr 2023 08:24:13 +0200 Subject: [PATCH 61/96] perf: avoid side effects resolving in dev and in the optimizer/scanner (#12789) Co-authored-by: Bjorn Lu --- packages/vite/src/node/config.ts | 1 + packages/vite/src/node/plugins/resolve.ts | 51 +++++++++++++++-------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index f4816167fa05e7..7e91c1775a680d 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -594,6 +594,7 @@ export async function resolveConfig( preferRelative: false, tryIndex: true, ...options, + idOnly: true, }), ], })) diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 856c8aa37e9033..52a01652d4cd5d 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -115,6 +115,13 @@ export interface InternalResolveOptions extends Required { // Resolve using esbuild deps optimization getDepsOptimizer?: (ssr: boolean) => DepsOptimizer | undefined shouldExternalize?: (id: string) => boolean | undefined + + /** + * Set by createResolver, we only care about the resolved id. moduleSideEffects + * and other fields are discarded so we can avoid computing them. + * @internal + */ + idOnly?: boolean } export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { @@ -265,7 +272,12 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { // If this isn't a script imported from a .html file, include side effects // hints so the non-used code is properly tree-shaken during build time. - if (!importer?.endsWith('.html')) { + if ( + !options.idOnly && + !options.scan && + options.isBuild && + !importer?.endsWith('.html') + ) { const resPkg = findNearestPackageData( path.dirname(res), options.packageCache, @@ -302,10 +314,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { // external if (isExternalUrl(id)) { - return { - id, - external: true, - } + return options.idOnly ? id : { id, external: true } } // data uri: pass through (this only happens during build and will be @@ -377,10 +386,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { this.error(message) } - return { - id, - external: true, - } + return options.idOnly ? id : { id, external: true } } else { if (!asSrc) { debug?.( @@ -773,7 +779,10 @@ export function tryNodeResolve( return { ...resolved, id: resolvedId, external: true } } - if ((isBuild && !depsOptimizer) || externalize) { + if ( + !options.idOnly && + ((!options.scan && isBuild && !depsOptimizer) || externalize) + ) { // Resolve package side effects for build so that rollup can better // perform tree-shaking return processResult({ @@ -853,7 +862,7 @@ export function tryNodeResolve( resolved = depsOptimizer!.getOptimizedDepId(optimizedInfo) } - if (isBuild) { + if (!options.idOnly && !options.scan && isBuild) { // Resolve package side effects for build so that rollup can better // perform tree-shaking return { @@ -1210,16 +1219,22 @@ function tryResolveBrowserMapping( : tryFsResolve(path.join(pkg.dir, browserMappedPath), options)) ) { debug?.(`[browser mapped] ${colors.cyan(id)} -> ${colors.dim(res)}`) - const resPkg = findNearestPackageData( - path.dirname(res), - options.packageCache, - ) - const result = resPkg - ? { + let result: PartialResolvedId = { id: res } + if (options.idOnly) { + return result + } + if (!options.scan && options.isBuild) { + const resPkg = findNearestPackageData( + path.dirname(res), + options.packageCache, + ) + if (resPkg) { + result = { id: res, moduleSideEffects: resPkg.hasSideEffects(res), } - : { id: res } + } + } return externalize ? { ...result, external: true } : result } } else if (browserMappedPath === false) { From a2b7a51eb09acf794b3696e448eb4839ef80a3c9 Mon Sep 17 00:00:00 2001 From: patak Date: Sat, 8 Apr 2023 10:13:50 +0200 Subject: [PATCH 62/96] docs: yarn link and outdated dependencies (#12790) --- docs/guide/troubleshooting.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/guide/troubleshooting.md b/docs/guide/troubleshooting.md index 2bcf9042ca2791..c9eeab879c5c5a 100644 --- a/docs/guide/troubleshooting.md +++ b/docs/guide/troubleshooting.md @@ -121,6 +121,12 @@ See [Reason: CORS request not HTTP - HTTP | MDN](https://developer.mozilla.org/e You will need to access the file with `http` protocol. The easiest way to achieve this is to run `npx vite preview`. +## Optimized Dependencies + +### Outdated pre-bundled deps when linking to a local package + +The hash key used to invalidate optimized dependencies depend on the package lock contents, the patches applied to dependencies, and the options in the Vite config file that affects the bundling of node modules. This means that Vite will detect when a dependency is overridden using a feature as [npm overrides](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides), and re-bundle your dependencies on the next server start. Vite won't invalidate the dependencies when you use a feature like [npm link](https://docs.npmjs.com/cli/v9/commands/npm-link). In case you link or unlink a dependency, you'll need to force re-optimization on the next server start by using `vite --force`. We recommend using overrides instead, which are supported now by every package manager (see also [pnpm overrides](https://pnpm.io/package_json#pnpmoverrides) and [yarn resolutions](https://yarnpkg.com/configuration/manifest/#resolutions)). + ## Others ### Module externalized for browser compatibility From 46bdf7dbfaa6df8a0405c68df586752713c4ded6 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Sun, 9 Apr 2023 13:30:12 +0800 Subject: [PATCH 63/96] fix(css): resolve at import from dependency basedir (#12796) --- packages/vite/rollup.config.ts | 2 +- packages/vite/src/node/plugins/css.ts | 12 ++++++++++ packages/vite/src/node/plugins/resolve.ts | 9 ++++--- playground/css/__tests__/css.spec.ts | 4 ++++ playground/css/css-proxy-dep-nested/index.css | 3 +++ .../css/css-proxy-dep-nested/package.json | 6 +++++ playground/css/css-proxy-dep/index.css | 1 + playground/css/css-proxy-dep/package.json | 9 +++++++ playground/css/dep.css | 1 + playground/css/index.html | 4 ++++ playground/css/package.json | 1 + pnpm-lock.yaml | 24 +++++++++++++++++++ 12 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 playground/css/css-proxy-dep-nested/index.css create mode 100644 playground/css/css-proxy-dep-nested/package.json create mode 100644 playground/css/css-proxy-dep/index.css create mode 100644 playground/css/css-proxy-dep/package.json diff --git a/packages/vite/rollup.config.ts b/packages/vite/rollup.config.ts index b50359581147e0..7a1064778ae9f8 100644 --- a/packages/vite/rollup.config.ts +++ b/packages/vite/rollup.config.ts @@ -125,7 +125,7 @@ function createNodePlugins( // bundling the `resolve` dep. 'postcss-import/index.js': { src: 'const resolveId = require("./lib/resolve-id")', - replacement: 'const resolveId = undefined', + replacement: 'const resolveId = (id) => id', }, }), diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index d189ae06231d42..dd49feb4c744d0 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -929,6 +929,18 @@ async function compileCSS( if (resolved) { return path.resolve(resolved) } + + // postcss-import falls back to `resolve` dep if this is unresolved, + // but we've shimmed to remove the `resolve` dep to cut on bundle size. + // warn here to provide a better error message. + if (!path.isAbsolute(id)) { + config.logger.error( + colors.red( + `Unable to resolve \`@import "${id}"\` from ${basedir}`, + ), + ) + } + return id }, nameLayer(index) { diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 52a01652d4cd5d..720f4e6b5f9e5c 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -695,12 +695,11 @@ export function tryNodeResolve( let basedir: string if (dedupe?.includes(pkgId)) { basedir = root - } else if ( - importer && - path.isAbsolute(importer) && - fs.existsSync(cleanUrl(importer)) - ) { + } else if (importer && path.isAbsolute(importer)) { basedir = path.dirname(importer) + if (!fs.existsSync(basedir)) { + basedir = root + } } else { basedir = root } diff --git a/playground/css/__tests__/css.spec.ts b/playground/css/__tests__/css.spec.ts index 45a33d4c3b1950..e0ef92c74c149b 100644 --- a/playground/css/__tests__/css.spec.ts +++ b/playground/css/__tests__/css.spec.ts @@ -297,6 +297,10 @@ test('@import dependency w/ sass export mapping', async () => { expect(await getColor('.css-dep-exports-sass')).toBe('orange') }) +test('@import dependency that @import another dependency', async () => { + expect(await getColor('.css-proxy-dep')).toBe('purple') +}) + test('@import dependency w/out package scss', async () => { expect(await getColor('.sass-dep')).toBe('lavender') }) diff --git a/playground/css/css-proxy-dep-nested/index.css b/playground/css/css-proxy-dep-nested/index.css new file mode 100644 index 00000000000000..ad0654a130d2e5 --- /dev/null +++ b/playground/css/css-proxy-dep-nested/index.css @@ -0,0 +1,3 @@ +.css-proxy-dep { + color: purple; +} diff --git a/playground/css/css-proxy-dep-nested/package.json b/playground/css/css-proxy-dep-nested/package.json new file mode 100644 index 00000000000000..06cb23332c7c56 --- /dev/null +++ b/playground/css/css-proxy-dep-nested/package.json @@ -0,0 +1,6 @@ +{ + "name": "@vitejs/test-css-proxy-dep-nested", + "private": true, + "version": "1.0.0", + "style": "index.css" +} diff --git a/playground/css/css-proxy-dep/index.css b/playground/css/css-proxy-dep/index.css new file mode 100644 index 00000000000000..9b31759a8a326d --- /dev/null +++ b/playground/css/css-proxy-dep/index.css @@ -0,0 +1 @@ +@import '@vitejs/test-css-proxy-dep-nested'; diff --git a/playground/css/css-proxy-dep/package.json b/playground/css/css-proxy-dep/package.json new file mode 100644 index 00000000000000..60256b6f4e2486 --- /dev/null +++ b/playground/css/css-proxy-dep/package.json @@ -0,0 +1,9 @@ +{ + "name": "@vitejs/test-css-proxy-dep", + "private": true, + "version": "1.0.0", + "style": "index.css", + "dependencies": { + "@vitejs/test-css-proxy-dep-nested": "file:../css-proxy-dep-nested" + } +} diff --git a/playground/css/dep.css b/playground/css/dep.css index 3578a9d5312363..2577e5b8cb3578 100644 --- a/playground/css/dep.css +++ b/playground/css/dep.css @@ -1,2 +1,3 @@ @import '@vitejs/test-css-dep'; @import '@vitejs/test-css-dep-exports'; +@import '@vitejs/test-css-proxy-dep'; diff --git a/playground/css/index.html b/playground/css/index.html index 791a549ae53349..748181b87f064e 100644 --- a/playground/css/index.html +++ b/playground/css/index.html @@ -140,6 +140,10 @@

CSS

@import dependency w/ sass export mapping: this should be orange

+

+ @import dependency that @import another dependency: this should be purple +

+

PostCSS dir-dependency: this should be grey

PostCSS dir-dependency (file 2): this should be grey too diff --git a/playground/css/package.json b/playground/css/package.json index 5153cb18f69f1b..826701058bd17e 100644 --- a/playground/css/package.json +++ b/playground/css/package.json @@ -18,6 +18,7 @@ "@vitejs/test-css-dep": "link:./css-dep", "@vitejs/test-css-dep-exports": "link:./css-dep-exports", "@vitejs/test-css-js-dep": "file:./css-js-dep", + "@vitejs/test-css-proxy-dep": "file:./css-proxy-dep", "fast-glob": "^3.2.12", "less": "^4.1.3", "postcss-nested": "^6.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f0d4ad1c4f32b3..66e061bcb9b84c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -369,6 +369,7 @@ importers: '@vitejs/test-css-dep': link:./css-dep '@vitejs/test-css-dep-exports': link:./css-dep-exports '@vitejs/test-css-js-dep': file:./css-js-dep + '@vitejs/test-css-proxy-dep': file:./css-proxy-dep fast-glob: ^3.2.12 less: ^4.1.3 postcss-nested: ^6.0.1 @@ -379,6 +380,7 @@ importers: '@vitejs/test-css-dep': link:css-dep '@vitejs/test-css-dep-exports': link:css-dep-exports '@vitejs/test-css-js-dep': file:playground/css/css-js-dep + '@vitejs/test-css-proxy-dep': file:playground/css/css-proxy-dep fast-glob: 3.2.12 less: 4.1.3 postcss-nested: 6.0.1 @@ -418,6 +420,15 @@ importers: playground/css/css-js-dep: specifiers: {} + playground/css/css-proxy-dep: + specifiers: + '@vitejs/test-css-proxy-dep-nested': file:../css-proxy-dep-nested + dependencies: + '@vitejs/test-css-proxy-dep-nested': file:playground/css/css-proxy-dep-nested + + playground/css/css-proxy-dep-nested: + specifiers: {} + playground/css/pkg-dep: specifiers: {} @@ -10095,6 +10106,19 @@ packages: version: 1.0.0 dev: true + file:playground/css/css-proxy-dep: + resolution: {directory: playground/css/css-proxy-dep, type: directory} + name: '@vitejs/test-css-proxy-dep' + version: 1.0.0 + dependencies: + '@vitejs/test-css-proxy-dep-nested': file:playground/css/css-proxy-dep-nested + dev: true + + file:playground/css/css-proxy-dep-nested: + resolution: {directory: playground/css/css-proxy-dep-nested, type: directory} + name: '@vitejs/test-css-proxy-dep-nested' + version: 1.0.0 + file:playground/define/commonjs-dep: resolution: {directory: playground/define/commonjs-dep, type: directory} name: '@vitejs/test-commonjs-dep' From ea5f6fcd06064bf80fc6b2e8b31bb507be242b73 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Sun, 9 Apr 2023 14:26:59 +0800 Subject: [PATCH 64/96] fix(worker): return null for shouldTransformCachedModule (#12797) --- packages/vite/src/node/plugins/reporter.ts | 4 ++++ packages/vite/src/node/plugins/worker.ts | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/plugins/reporter.ts b/packages/vite/src/node/plugins/reporter.ts index 0559e02dd5cb89..0c3a8cfe099c6e 100644 --- a/packages/vite/src/node/plugins/reporter.ts +++ b/packages/vite/src/node/plugins/reporter.ts @@ -91,6 +91,10 @@ export function buildReporterPlugin(config: ResolvedConfig): Plugin { startTime = Date.now() }, + buildStart() { + transformedCount = 0 + }, + buildEnd() { if (shouldLogInfo) { if (tty) { diff --git a/packages/vite/src/node/plugins/worker.ts b/packages/vite/src/node/plugins/worker.ts index c28b7da19dc237..930b7b796e9561 100644 --- a/packages/vite/src/node/plugins/worker.ts +++ b/packages/vite/src/node/plugins/worker.ts @@ -240,11 +240,12 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin { } }, + // @ts-expect-error return void to fallback to other plugins, even though + // the types doesn't allow it. https://github.com/rollup/rollup/pull/4932 shouldTransformCachedModule({ id }) { if (isBuild && isWorkerQueryId(id) && config.build.watch) { return true } - return false }, async transform(raw, id, options) { From 72a379f46ba4f3ced524b1bfe3014cf5f787f4d1 Mon Sep 17 00:00:00 2001 From: patak Date: Sun, 9 Apr 2023 08:28:13 +0200 Subject: [PATCH 65/96] release: v4.3.0-beta.4 --- packages/vite/CHANGELOG.md | 12 ++++++++++++ packages/vite/package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/vite/CHANGELOG.md b/packages/vite/CHANGELOG.md index 13d30715a7f773..6a9218afc4561a 100644 --- a/packages/vite/CHANGELOG.md +++ b/packages/vite/CHANGELOG.md @@ -1,3 +1,15 @@ +## 4.3.0-beta.4 (2023-04-09) + +* fix: ignore sideEffects for scripts imported from html (#12786) ([f09551f](https://github.com/vitejs/vite/commit/f09551f)), closes [#12786](https://github.com/vitejs/vite/issues/12786) +* fix: warn on build when bundling code that uses nodejs built in module (#12616) ([72050f9](https://github.com/vitejs/vite/commit/72050f9)), closes [#12616](https://github.com/vitejs/vite/issues/12616) +* fix(cli): pass mode to optimize command (#12776) ([da38ad8](https://github.com/vitejs/vite/commit/da38ad8)), closes [#12776](https://github.com/vitejs/vite/issues/12776) +* fix(css): resolve at import from dependency basedir (#12796) ([46bdf7d](https://github.com/vitejs/vite/commit/46bdf7d)), closes [#12796](https://github.com/vitejs/vite/issues/12796) +* fix(worker): asset in iife worker and relative base (#12697) ([ddefc06](https://github.com/vitejs/vite/commit/ddefc06)), closes [#12697](https://github.com/vitejs/vite/issues/12697) +* fix(worker): return null for shouldTransformCachedModule (#12797) ([ea5f6fc](https://github.com/vitejs/vite/commit/ea5f6fc)), closes [#12797](https://github.com/vitejs/vite/issues/12797) +* perf: avoid side effects resolving in dev and in the optimizer/scanner (#12789) ([fb904f9](https://github.com/vitejs/vite/commit/fb904f9)), closes [#12789](https://github.com/vitejs/vite/issues/12789) + + + ## 4.3.0-beta.3 (2023-04-07) * fix: allow onwarn to override vite default warning handling (#12757) ([f736930](https://github.com/vitejs/vite/commit/f736930)), closes [#12757](https://github.com/vitejs/vite/issues/12757) diff --git a/packages/vite/package.json b/packages/vite/package.json index 77e133e3e1d246..269bcac55ef87d 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -1,6 +1,6 @@ { "name": "vite", - "version": "4.3.0-beta.3", + "version": "4.3.0-beta.4", "type": "module", "license": "MIT", "author": "Evan You", From 66ec31caa0bfe97f847c925f0e70ef47f25b7326 Mon Sep 17 00:00:00 2001 From: yangxingyuan <39261479+sanyuan0704@users.noreply.github.com> Date: Sun, 9 Apr 2023 18:06:06 +0800 Subject: [PATCH 66/96] test: resolve using absolute dep path (#5495) Co-authored-by: patak --- .../nested-deps/__tests__/nested-deps.spec.ts | 3 ++- playground/nested-deps/index.html | 5 +++++ playground/nested-deps/package.json | 3 ++- playground/nested-deps/test-package-f/index.js | 1 + .../nested-deps/test-package-f/package.json | 7 +++++++ playground/nested-deps/vite.config.js | 9 +++++++++ pnpm-lock.yaml | 17 +++++++++++------ 7 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 playground/nested-deps/test-package-f/index.js create mode 100644 playground/nested-deps/test-package-f/package.json diff --git a/playground/nested-deps/__tests__/nested-deps.spec.ts b/playground/nested-deps/__tests__/nested-deps.spec.ts index 19c280b228b551..04618ece544ad9 100644 --- a/playground/nested-deps/__tests__/nested-deps.spec.ts +++ b/playground/nested-deps/__tests__/nested-deps.spec.ts @@ -10,7 +10,8 @@ test('handle nested package', async () => { expect(await page.textContent('.side-c')).toBe(c) expect(await page.textContent('.d')).toBe('D@1.0.0') expect(await page.textContent('.nested-d')).toBe('D-nested@1.0.0') - // TODO: Review if the test is correct // expect(await page.textContent('.nested-e')).toBe('1') + + expect(await page.textContent('.absolute-f')).toBe('F@2.0.0') }) diff --git a/playground/nested-deps/index.html b/playground/nested-deps/index.html index 2efb4f71044208..86dbc149fff32e 100644 --- a/playground/nested-deps/index.html +++ b/playground/nested-deps/index.html @@ -22,6 +22,8 @@

nested dependency nested-D (dep of D)

exclude dependency of pre-bundled dependency

nested module instance count:
+

absolute dependency path:

+