From fa869e13438a0298e9ac5df0aac979bc3d066a3b Mon Sep 17 00:00:00 2001 From: patak Date: Tue, 16 Jan 2024 16:17:51 +0100 Subject: [PATCH 1/7] perf: lazy load rollup during dev --- packages/vite/src/node/index.ts | 2 +- packages/vite/src/node/publicUtils.ts | 11 ++-- packages/vite/src/node/server/index.ts | 2 + .../vite/src/node/server/pluginContainer.ts | 6 +-- packages/vite/src/node/utils.ts | 53 ++++++++++++++++++- 5 files changed, 66 insertions(+), 8 deletions(-) diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts index 0c94465e1690be..5ef7bb84f6e274 100644 --- a/packages/vite/src/node/index.ts +++ b/packages/vite/src/node/index.ts @@ -1,7 +1,7 @@ import type * as Rollup from 'rollup' export type { Rollup } -export { parseAst, parseAstAsync } from 'rollup/parseAst' +export { initRollupParseAst, parseAst, parseAstAsync } from './utils' export { defineConfig, loadConfigFromFile, diff --git a/packages/vite/src/node/publicUtils.ts b/packages/vite/src/node/publicUtils.ts index 8a9ab56559815b..c7dd2f3d1a5566 100644 --- a/packages/vite/src/node/publicUtils.ts +++ b/packages/vite/src/node/publicUtils.ts @@ -4,14 +4,19 @@ * Please control the side-effects by checking the ./dist/node-cjs/publicUtils.cjs bundle */ export { VERSION as version } from './constants' -export { version as esbuildVersion } from 'esbuild' -export { VERSION as rollupVersion } from 'rollup' export { splitVendorChunkPlugin, splitVendorChunk, isCSSRequest, } from './plugins/splitVendorChunk' -export { normalizePath, mergeConfig, mergeAlias, createFilter } from './utils' +export { + normalizePath, + mergeConfig, + mergeAlias, + createFilter, + esbuildVersion, + rollupVersion, +} from './utils' export { send } from './server/send' export { createLogger } from './logger' export { searchForWorkspaceRoot } from './server/searchRoot' diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts index 2501e1fde26170..1a25929e6024c4 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -27,6 +27,7 @@ import type { InlineConfig, ResolvedConfig } from '../config' import { isDepsOptimizerEnabled, resolveConfig } from '../config' import { diffDnsOrderChange, + initRollupParseAst, isInNodeModules, isObject, isParentDirectory, @@ -816,6 +817,7 @@ export async function _createServer( if (initingServer) return initingServer initingServer = (async function () { + await initRollupParseAst() await container.buildStart({}) // start deps optimizer after all container plugins are ready if (isDepsOptimizerEnabled(config, false)) { diff --git a/packages/vite/src/node/server/pluginContainer.ts b/packages/vite/src/node/server/pluginContainer.ts index fa2dd4167fce5d..adca67b4cce7f2 100644 --- a/packages/vite/src/node/server/pluginContainer.ts +++ b/packages/vite/src/node/server/pluginContainer.ts @@ -32,8 +32,6 @@ SOFTWARE. import fs from 'node:fs' import { join } from 'node:path' import { performance } from 'node:perf_hooks' -import { VERSION as rollupVersion } from 'rollup' -import { parseAst as rollupParseAst } from 'rollup/parseAst' import type { AsyncPluginHooks, CustomPluginOptions, @@ -73,7 +71,9 @@ import { isObject, normalizePath, numberToPos, + parseAst, prettifyUrl, + rollupVersion, timeFrom, unwrapId, } from '../utils' @@ -302,7 +302,7 @@ export async function createPluginContainer( } parse(code: string, opts: any) { - return rollupParseAst(code, opts) + return parseAst(code, opts) } async resolve( diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 73c3806cc9fd44..5dd411deb91828 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -17,7 +17,7 @@ import debug from 'debug' import type { Alias, AliasOptions } from 'dep-types/alias' import type MagicString from 'magic-string' -import type { TransformResult } from 'rollup' +import type { AstNode, ParseAst, ParseAstAsync, TransformResult } from 'rollup' import { createFilter as _createFilter } from '@rollup/pluginutils' import { CLIENT_ENTRY, @@ -41,6 +41,46 @@ import { } from './packages' import type { CommonServerOptions } from '.' +let rollupParseAst: ParseAst +let rollupParseAstAsync: ParseAstAsync +let rollupInited: Promise | boolean = false +export async function initRollupParseAst(): Promise { + if (!rollupInited) { + const importRollupParseAst = import('rollup/parseAst') + rollupInited = importRollupParseAst + const { parseAst, parseAstAsync } = await importRollupParseAst + rollupParseAst = parseAst + rollupParseAstAsync = parseAstAsync + rollupInited = true + } + return rollupInited +} +export function parseAst( + code: string, + options?: { + allowReturnOutsideFunction?: boolean + }, +): AstNode { + if (!rollupInited) { + throw new Error( + `rollup/parseAst is not initialized yet, call initRollupParseAst() first`, + ) + } + return rollupParseAst(code, options) +} + +export async function parseAstAsync( + code: string, + options?: { + allowReturnOutsideFunction?: boolean + }, +): Promise { + if (rollupInited === false) { + await initRollupParseAst() + } + return rollupParseAstAsync(code, options) +} + /** * Inlined to keep `@rollup/pluginutils` in devDependencies */ @@ -162,6 +202,17 @@ export const deepImportRE = /^([^@][^/]*)\/|^(@[^/]+\/[^/]+)\// // TODO: use import() const _require = createRequire(import.meta.url) +export function resolveDependencyVersion( + dep: string, + pkgRelativePath = '../../package.json', +): string { + const pkgPath = path.resolve(_require.resolve(dep), pkgRelativePath) + return JSON.parse(fs.readFileSync(pkgPath, 'utf-8')).version +} + +export const esbuildVersion = resolveDependencyVersion('rollup') +export const rollupVersion = resolveDependencyVersion('esbuild') + // set in bin/vite.js const filter = process.env.VITE_DEBUG_FILTER From 9493220afad409c18700ead2c17c9eb777d0c8d1 Mon Sep 17 00:00:00 2001 From: patak Date: Thu, 18 Jan 2024 13:33:57 +0100 Subject: [PATCH 2/7] chore: revert rollup/parseAst changes --- packages/vite/src/node/index.ts | 2 +- packages/vite/src/node/server/index.ts | 2 - .../vite/src/node/server/pluginContainer.ts | 4 +- packages/vite/src/node/utils.ts | 42 +------------------ 4 files changed, 4 insertions(+), 46 deletions(-) diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts index 5ef7bb84f6e274..0c94465e1690be 100644 --- a/packages/vite/src/node/index.ts +++ b/packages/vite/src/node/index.ts @@ -1,7 +1,7 @@ import type * as Rollup from 'rollup' export type { Rollup } -export { initRollupParseAst, parseAst, parseAstAsync } from './utils' +export { parseAst, parseAstAsync } from 'rollup/parseAst' export { defineConfig, loadConfigFromFile, diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts index 1a25929e6024c4..2501e1fde26170 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -27,7 +27,6 @@ import type { InlineConfig, ResolvedConfig } from '../config' import { isDepsOptimizerEnabled, resolveConfig } from '../config' import { diffDnsOrderChange, - initRollupParseAst, isInNodeModules, isObject, isParentDirectory, @@ -817,7 +816,6 @@ export async function _createServer( if (initingServer) return initingServer initingServer = (async function () { - await initRollupParseAst() await container.buildStart({}) // start deps optimizer after all container plugins are ready if (isDepsOptimizerEnabled(config, false)) { diff --git a/packages/vite/src/node/server/pluginContainer.ts b/packages/vite/src/node/server/pluginContainer.ts index adca67b4cce7f2..551b210418363d 100644 --- a/packages/vite/src/node/server/pluginContainer.ts +++ b/packages/vite/src/node/server/pluginContainer.ts @@ -32,6 +32,7 @@ SOFTWARE. import fs from 'node:fs' import { join } from 'node:path' import { performance } from 'node:perf_hooks' +import { parseAst as rollupParseAst } from 'rollup/parseAst' import type { AsyncPluginHooks, CustomPluginOptions, @@ -71,7 +72,6 @@ import { isObject, normalizePath, numberToPos, - parseAst, prettifyUrl, rollupVersion, timeFrom, @@ -302,7 +302,7 @@ export async function createPluginContainer( } parse(code: string, opts: any) { - return parseAst(code, opts) + return rollupParseAst(code, opts) } async resolve( diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 5dd411deb91828..00209d423338d4 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -17,7 +17,7 @@ import debug from 'debug' import type { Alias, AliasOptions } from 'dep-types/alias' import type MagicString from 'magic-string' -import type { AstNode, ParseAst, ParseAstAsync, TransformResult } from 'rollup' +import type { TransformResult } from 'rollup' import { createFilter as _createFilter } from '@rollup/pluginutils' import { CLIENT_ENTRY, @@ -41,46 +41,6 @@ import { } from './packages' import type { CommonServerOptions } from '.' -let rollupParseAst: ParseAst -let rollupParseAstAsync: ParseAstAsync -let rollupInited: Promise | boolean = false -export async function initRollupParseAst(): Promise { - if (!rollupInited) { - const importRollupParseAst = import('rollup/parseAst') - rollupInited = importRollupParseAst - const { parseAst, parseAstAsync } = await importRollupParseAst - rollupParseAst = parseAst - rollupParseAstAsync = parseAstAsync - rollupInited = true - } - return rollupInited -} -export function parseAst( - code: string, - options?: { - allowReturnOutsideFunction?: boolean - }, -): AstNode { - if (!rollupInited) { - throw new Error( - `rollup/parseAst is not initialized yet, call initRollupParseAst() first`, - ) - } - return rollupParseAst(code, options) -} - -export async function parseAstAsync( - code: string, - options?: { - allowReturnOutsideFunction?: boolean - }, -): Promise { - if (rollupInited === false) { - await initRollupParseAst() - } - return rollupParseAstAsync(code, options) -} - /** * Inlined to keep `@rollup/pluginutils` in devDependencies */ From af14ea0d9254709aa5bf77630c640c07d1aaee2a Mon Sep 17 00:00:00 2001 From: patak Date: Thu, 18 Jan 2024 17:25:32 +0100 Subject: [PATCH 3/7] perf: import esbuild dynamically --- packages/vite/src/node/config.ts | 3 ++- packages/vite/src/node/optimizer/index.ts | 3 ++- packages/vite/src/node/optimizer/scan.ts | 4 +++- packages/vite/src/node/plugins/css.ts | 3 ++- packages/vite/src/node/plugins/define.ts | 2 +- packages/vite/src/node/plugins/esbuild.ts | 2 +- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index c96dae1b191ba8..ac42f7fee5fb73 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -8,7 +8,6 @@ import { createRequire } from 'node:module' import colors from 'picocolors' import type { Alias, AliasOptions } from 'dep-types/alias' import aliasPlugin from '@rollup/plugin-alias' -import { build } from 'esbuild' import type { RollupOptions } from 'rollup' import type { HookHandler, Plugin, PluginWithRequiredHook } from './plugin' import type { @@ -1009,6 +1008,8 @@ async function bundleConfigFile( const dirnameVarName = '__vite_injected_original_dirname' const filenameVarName = '__vite_injected_original_filename' const importMetaUrlVarName = '__vite_injected_original_import_meta_url' + + const { build } = await import('esbuild') const result = await build({ absWorkingDir: process.cwd(), entryPoints: [fileName], diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index c085b5d10b23a3..05c49c5fd10235 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -5,7 +5,6 @@ import { promisify } from 'node:util' import { performance } from 'node:perf_hooks' import colors from 'picocolors' import type { BuildContext, BuildOptions as EsbuildBuildOptions } from 'esbuild' -import esbuild, { build } from 'esbuild' import { init, parse } from 'es-module-lexer' import glob from 'fast-glob' import { getDepOptimizationConfig } from '../config' @@ -759,6 +758,7 @@ async function prepareEsbuildOptimizerRun( } plugins.push(esbuildDepPlugin(flatIdDeps, external, config, ssr)) + const esbuild = (await import('esbuild')).default const context = await esbuild.context({ absWorkingDir: process.cwd(), entryPoints: Object.keys(flatIdDeps), @@ -1058,6 +1058,7 @@ export async function extractExportsData( // For custom supported extensions, build the entry file to transform it into JS, // and then parse with es-module-lexer. Note that the `bundle` option is not `true`, // so only the entry file is being transformed. + const { build } = await import('esbuild') const result = await build({ ...esbuildOptions, entryPoints: [filePath], diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index b28c13167e5fb6..02a8722eacca4d 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -10,7 +10,6 @@ import type { OnLoadResult, Plugin, } from 'esbuild' -import esbuild, { formatMessages, transform } from 'esbuild' import colors from 'picocolors' import type { ResolvedConfig } from '..' import { @@ -135,6 +134,7 @@ export function scanImports(config: ResolvedConfig): { `) if (e.errors) { + const { formatMessages } = await import('esbuild') const msgs = await formatMessages(e.errors, { kind: 'error', color: true, @@ -216,6 +216,7 @@ async function prepareEsbuildScanner( const { plugins = [], ...esbuildOptions } = config.optimizeDeps?.esbuildOptions ?? {} + const esbuild = (await import('esbuild')).default return await esbuild.context({ absWorkingDir: process.cwd(), write: false, @@ -315,6 +316,7 @@ function esbuildScanPlugin( let transpiledContents // transpile because `transformGlobImport` only expects js if (loader !== 'js') { + const { transform } = await import('esbuild') transpiledContents = (await transform(contents, { loader })).code } else { transpiledContents = contents diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index effeec1203c066..5c34bdaeb11ee3 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -22,7 +22,6 @@ import type Less from 'less' import type { Alias } from 'dep-types/alias' import type { LightningCSSOptions } from 'dep-types/lightningcss' import type { TransformOptions } from 'esbuild' -import { formatMessages, transform } from 'esbuild' import type { RawSourceMap } from '@ampproject/remapping' import { getCodeWithSourcemap, injectSourcesContent } from '../server/sourcemap' import type { ModuleNode } from '../server/moduleGraph' @@ -1723,6 +1722,8 @@ async function minifyCSS( // LightningCSS output does not return a linebreak at the end return code.toString() + (inlined ? '' : '\n') } + + const { formatMessages, transform } = await import('esbuild') try { const { code, warnings } = await transform(css, { loader: 'css', diff --git a/packages/vite/src/node/plugins/define.ts b/packages/vite/src/node/plugins/define.ts index 3eaf2def0efde3..e7ca05635e2b85 100644 --- a/packages/vite/src/node/plugins/define.ts +++ b/packages/vite/src/node/plugins/define.ts @@ -1,4 +1,3 @@ -import { transform } from 'esbuild' import type { ResolvedConfig } from '../config' import type { Plugin } from '../plugin' import { escapeRegex, getHash } from '../utils' @@ -148,6 +147,7 @@ export async function replaceDefine( const esbuildOptions = config.esbuild || {} + const { transform } = await import('esbuild') const result = await transform(code, { loader: 'js', charset: esbuildOptions.charset ?? 'utf8', diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts index 6589756f37f5a6..297817e29b7832 100644 --- a/packages/vite/src/node/plugins/esbuild.ts +++ b/packages/vite/src/node/plugins/esbuild.ts @@ -6,7 +6,6 @@ import type { TransformOptions, TransformResult, } from 'esbuild' -import { transform } from 'esbuild' import type { RawSourceMap } from '@ampproject/remapping' import type { InternalModuleFormat, SourceMap } from 'rollup' import type { TSConfckParseResult } from 'tsconfck' @@ -173,6 +172,7 @@ export async function transformWithEsbuild( delete resolvedOptions.jsxInject try { + const { transform } = await import('esbuild') const result = await transform(code, resolvedOptions) let map: SourceMap if (inMap && resolvedOptions.sourcemap) { From 02f4bd5ce0367fd1197da4736752c225ee19252d Mon Sep 17 00:00:00 2001 From: patak Date: Fri, 19 Jan 2024 10:17:33 +0100 Subject: [PATCH 4/7] perf: importEsbuild() --- packages/vite/src/node/config.ts | 3 ++- packages/vite/src/node/optimizer/index.ts | 5 +++-- packages/vite/src/node/optimizer/scan.ts | 10 ++++++---- packages/vite/src/node/plugins/css.ts | 3 ++- packages/vite/src/node/plugins/define.ts | 4 ++-- packages/vite/src/node/plugins/esbuild.ts | 3 ++- packages/vite/src/node/utils.ts | 20 ++++++++++++++++++++ 7 files changed, 37 insertions(+), 11 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index ac42f7fee5fb73..bfe79b8e027029 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -29,6 +29,7 @@ import { asyncFlatten, createDebugger, createFilter, + importEsbuild, isBuiltin, isExternalUrl, isFilePathESM, @@ -1009,7 +1010,7 @@ async function bundleConfigFile( const filenameVarName = '__vite_injected_original_filename' const importMetaUrlVarName = '__vite_injected_original_import_meta_url' - const { build } = await import('esbuild') + const { build } = await importEsbuild() const result = await build({ absWorkingDir: process.cwd(), entryPoints: [fileName], diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 05c49c5fd10235..15490f01e7cf7a 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -13,6 +13,7 @@ import { createDebugger, flattenId, getHash, + importEsbuild, isOptimizable, isWindows, lookupFile, @@ -758,7 +759,7 @@ async function prepareEsbuildOptimizerRun( } plugins.push(esbuildDepPlugin(flatIdDeps, external, config, ssr)) - const esbuild = (await import('esbuild')).default + const esbuild = await importEsbuild() const context = await esbuild.context({ absWorkingDir: process.cwd(), entryPoints: Object.keys(flatIdDeps), @@ -1058,7 +1059,7 @@ export async function extractExportsData( // For custom supported extensions, build the entry file to transform it into JS, // and then parse with es-module-lexer. Note that the `bundle` option is not `true`, // so only the entry file is being transformed. - const { build } = await import('esbuild') + const { build } = await importEsbuild() const result = await build({ ...esbuildOptions, entryPoints: [filePath], diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index 02a8722eacca4d..2c2319ec151497 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -23,6 +23,7 @@ import { createDebugger, dataUrlRE, externalRE, + importEsbuild, isInNodeModules, isObject, isOptimizable, @@ -134,7 +135,7 @@ export function scanImports(config: ResolvedConfig): { `) if (e.errors) { - const { formatMessages } = await import('esbuild') + const { formatMessages } = await importEsbuild() const msgs = await formatMessages(e.errors, { kind: 'error', color: true, @@ -216,8 +217,9 @@ async function prepareEsbuildScanner( const { plugins = [], ...esbuildOptions } = config.optimizeDeps?.esbuildOptions ?? {} - const esbuild = (await import('esbuild')).default - return await esbuild.context({ + return await ( + await importEsbuild() + ).context({ absWorkingDir: process.cwd(), write: false, stdin: { @@ -316,7 +318,7 @@ function esbuildScanPlugin( let transpiledContents // transpile because `transformGlobImport` only expects js if (loader !== 'js') { - const { transform } = await import('esbuild') + const { transform } = await importEsbuild() transpiledContents = (await transform(contents, { loader })).code } else { transpiledContents = contents diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 5c34bdaeb11ee3..7b90a108b845d0 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -51,6 +51,7 @@ import { generateCodeFrame, getHash, getPackageManagerCommand, + importEsbuild, injectQuery, isDataUrl, isExternalUrl, @@ -1723,7 +1724,7 @@ async function minifyCSS( return code.toString() + (inlined ? '' : '\n') } - const { formatMessages, transform } = await import('esbuild') + const { formatMessages, transform } = await importEsbuild() try { const { code, warnings } = await transform(css, { loader: 'css', diff --git a/packages/vite/src/node/plugins/define.ts b/packages/vite/src/node/plugins/define.ts index e7ca05635e2b85..aa3e313051f2ca 100644 --- a/packages/vite/src/node/plugins/define.ts +++ b/packages/vite/src/node/plugins/define.ts @@ -1,6 +1,6 @@ import type { ResolvedConfig } from '../config' import type { Plugin } from '../plugin' -import { escapeRegex, getHash } from '../utils' +import { escapeRegex, getHash, importEsbuild } from '../utils' import { isCSSRequest } from './css' import { isHTMLRequest } from './html' @@ -147,7 +147,7 @@ export async function replaceDefine( const esbuildOptions = config.esbuild || {} - const { transform } = await import('esbuild') + const { transform } = await importEsbuild() const result = await transform(code, { loader: 'js', charset: esbuildOptions.charset ?? 'utf8', diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts index 297817e29b7832..ab848d4c2225cb 100644 --- a/packages/vite/src/node/plugins/esbuild.ts +++ b/packages/vite/src/node/plugins/esbuild.ts @@ -17,6 +17,7 @@ import { createFilter, ensureWatchedFile, generateCodeFrame, + importEsbuild, } from '../utils' import type { ViteDevServer } from '../server' import type { ResolvedConfig } from '../config' @@ -172,7 +173,7 @@ export async function transformWithEsbuild( delete resolvedOptions.jsxInject try { - const { transform } = await import('esbuild') + const { transform } = await importEsbuild() const result = await transform(code, resolvedOptions) let map: SourceMap if (inMap && resolvedOptions.sourcemap) { diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 00209d423338d4..47868e49582a88 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -41,6 +41,26 @@ import { } from './packages' import type { CommonServerOptions } from '.' +// Cache lazy loaded esbuild import to avoid the extra cost of the import resolution on hot paths +// Only keep the functions we use to avoid keeping the promise and the entire module in memory +type EsbuildModule = typeof import('esbuild') +type EsbuildFunctions = Pick< + EsbuildModule, + 'build' | 'transform' | 'context' | 'formatMessages' +> +let esbuildFunctions: EsbuildFunctions | Promise +export async function importEsbuild(): Promise { + if (esbuildFunctions) { + return esbuildFunctions + } + esbuildFunctions = import('esbuild').then((esbuild) => { + const { build, transform, context, formatMessages } = esbuild + esbuildFunctions = { build, transform, context, formatMessages } + return esbuildFunctions + }) + return esbuildFunctions +} + /** * Inlined to keep `@rollup/pluginutils` in devDependencies */ From 6a2c258e83898c6bf3b477b86ee67b19f55446c3 Mon Sep 17 00:00:00 2001 From: patak Date: Mon, 22 Jan 2024 16:19:03 +0100 Subject: [PATCH 5/7] chore: revert This reverts commit 02f4bd5ce0367fd1197da4736752c225ee19252d. --- packages/vite/src/node/config.ts | 3 +-- packages/vite/src/node/optimizer/index.ts | 5 ++--- packages/vite/src/node/optimizer/scan.ts | 10 ++++------ packages/vite/src/node/plugins/css.ts | 3 +-- packages/vite/src/node/plugins/define.ts | 4 ++-- packages/vite/src/node/plugins/esbuild.ts | 3 +-- packages/vite/src/node/utils.ts | 20 -------------------- 7 files changed, 11 insertions(+), 37 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index bfe79b8e027029..ac42f7fee5fb73 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -29,7 +29,6 @@ import { asyncFlatten, createDebugger, createFilter, - importEsbuild, isBuiltin, isExternalUrl, isFilePathESM, @@ -1010,7 +1009,7 @@ async function bundleConfigFile( const filenameVarName = '__vite_injected_original_filename' const importMetaUrlVarName = '__vite_injected_original_import_meta_url' - const { build } = await importEsbuild() + const { build } = await import('esbuild') const result = await build({ absWorkingDir: process.cwd(), entryPoints: [fileName], diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 15490f01e7cf7a..05c49c5fd10235 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -13,7 +13,6 @@ import { createDebugger, flattenId, getHash, - importEsbuild, isOptimizable, isWindows, lookupFile, @@ -759,7 +758,7 @@ async function prepareEsbuildOptimizerRun( } plugins.push(esbuildDepPlugin(flatIdDeps, external, config, ssr)) - const esbuild = await importEsbuild() + const esbuild = (await import('esbuild')).default const context = await esbuild.context({ absWorkingDir: process.cwd(), entryPoints: Object.keys(flatIdDeps), @@ -1059,7 +1058,7 @@ export async function extractExportsData( // For custom supported extensions, build the entry file to transform it into JS, // and then parse with es-module-lexer. Note that the `bundle` option is not `true`, // so only the entry file is being transformed. - const { build } = await importEsbuild() + const { build } = await import('esbuild') const result = await build({ ...esbuildOptions, entryPoints: [filePath], diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index 2c2319ec151497..02a8722eacca4d 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -23,7 +23,6 @@ import { createDebugger, dataUrlRE, externalRE, - importEsbuild, isInNodeModules, isObject, isOptimizable, @@ -135,7 +134,7 @@ export function scanImports(config: ResolvedConfig): { `) if (e.errors) { - const { formatMessages } = await importEsbuild() + const { formatMessages } = await import('esbuild') const msgs = await formatMessages(e.errors, { kind: 'error', color: true, @@ -217,9 +216,8 @@ async function prepareEsbuildScanner( const { plugins = [], ...esbuildOptions } = config.optimizeDeps?.esbuildOptions ?? {} - return await ( - await importEsbuild() - ).context({ + const esbuild = (await import('esbuild')).default + return await esbuild.context({ absWorkingDir: process.cwd(), write: false, stdin: { @@ -318,7 +316,7 @@ function esbuildScanPlugin( let transpiledContents // transpile because `transformGlobImport` only expects js if (loader !== 'js') { - const { transform } = await importEsbuild() + const { transform } = await import('esbuild') transpiledContents = (await transform(contents, { loader })).code } else { transpiledContents = contents diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 7b90a108b845d0..5c34bdaeb11ee3 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -51,7 +51,6 @@ import { generateCodeFrame, getHash, getPackageManagerCommand, - importEsbuild, injectQuery, isDataUrl, isExternalUrl, @@ -1724,7 +1723,7 @@ async function minifyCSS( return code.toString() + (inlined ? '' : '\n') } - const { formatMessages, transform } = await importEsbuild() + const { formatMessages, transform } = await import('esbuild') try { const { code, warnings } = await transform(css, { loader: 'css', diff --git a/packages/vite/src/node/plugins/define.ts b/packages/vite/src/node/plugins/define.ts index aa3e313051f2ca..e7ca05635e2b85 100644 --- a/packages/vite/src/node/plugins/define.ts +++ b/packages/vite/src/node/plugins/define.ts @@ -1,6 +1,6 @@ import type { ResolvedConfig } from '../config' import type { Plugin } from '../plugin' -import { escapeRegex, getHash, importEsbuild } from '../utils' +import { escapeRegex, getHash } from '../utils' import { isCSSRequest } from './css' import { isHTMLRequest } from './html' @@ -147,7 +147,7 @@ export async function replaceDefine( const esbuildOptions = config.esbuild || {} - const { transform } = await importEsbuild() + const { transform } = await import('esbuild') const result = await transform(code, { loader: 'js', charset: esbuildOptions.charset ?? 'utf8', diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts index ab848d4c2225cb..297817e29b7832 100644 --- a/packages/vite/src/node/plugins/esbuild.ts +++ b/packages/vite/src/node/plugins/esbuild.ts @@ -17,7 +17,6 @@ import { createFilter, ensureWatchedFile, generateCodeFrame, - importEsbuild, } from '../utils' import type { ViteDevServer } from '../server' import type { ResolvedConfig } from '../config' @@ -173,7 +172,7 @@ export async function transformWithEsbuild( delete resolvedOptions.jsxInject try { - const { transform } = await importEsbuild() + const { transform } = await import('esbuild') const result = await transform(code, resolvedOptions) let map: SourceMap if (inMap && resolvedOptions.sourcemap) { diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 47868e49582a88..00209d423338d4 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -41,26 +41,6 @@ import { } from './packages' import type { CommonServerOptions } from '.' -// Cache lazy loaded esbuild import to avoid the extra cost of the import resolution on hot paths -// Only keep the functions we use to avoid keeping the promise and the entire module in memory -type EsbuildModule = typeof import('esbuild') -type EsbuildFunctions = Pick< - EsbuildModule, - 'build' | 'transform' | 'context' | 'formatMessages' -> -let esbuildFunctions: EsbuildFunctions | Promise -export async function importEsbuild(): Promise { - if (esbuildFunctions) { - return esbuildFunctions - } - esbuildFunctions = import('esbuild').then((esbuild) => { - const { build, transform, context, formatMessages } = esbuild - esbuildFunctions = { build, transform, context, formatMessages } - return esbuildFunctions - }) - return esbuildFunctions -} - /** * Inlined to keep `@rollup/pluginutils` in devDependencies */ From 426016e4bb75d2d1b8a94be8fffd345008512aba Mon Sep 17 00:00:00 2001 From: patak Date: Mon, 22 Jan 2024 16:19:33 +0100 Subject: [PATCH 6/7] chore: revert This reverts commit af14ea0d9254709aa5bf77630c640c07d1aaee2a. --- packages/vite/src/node/config.ts | 3 +-- packages/vite/src/node/optimizer/index.ts | 3 +-- packages/vite/src/node/optimizer/scan.ts | 4 +--- packages/vite/src/node/plugins/css.ts | 3 +-- packages/vite/src/node/plugins/define.ts | 2 +- packages/vite/src/node/plugins/esbuild.ts | 2 +- 6 files changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index ac42f7fee5fb73..c96dae1b191ba8 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -8,6 +8,7 @@ import { createRequire } from 'node:module' import colors from 'picocolors' import type { Alias, AliasOptions } from 'dep-types/alias' import aliasPlugin from '@rollup/plugin-alias' +import { build } from 'esbuild' import type { RollupOptions } from 'rollup' import type { HookHandler, Plugin, PluginWithRequiredHook } from './plugin' import type { @@ -1008,8 +1009,6 @@ async function bundleConfigFile( const dirnameVarName = '__vite_injected_original_dirname' const filenameVarName = '__vite_injected_original_filename' const importMetaUrlVarName = '__vite_injected_original_import_meta_url' - - const { build } = await import('esbuild') const result = await build({ absWorkingDir: process.cwd(), entryPoints: [fileName], diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 05c49c5fd10235..c085b5d10b23a3 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -5,6 +5,7 @@ import { promisify } from 'node:util' import { performance } from 'node:perf_hooks' import colors from 'picocolors' import type { BuildContext, BuildOptions as EsbuildBuildOptions } from 'esbuild' +import esbuild, { build } from 'esbuild' import { init, parse } from 'es-module-lexer' import glob from 'fast-glob' import { getDepOptimizationConfig } from '../config' @@ -758,7 +759,6 @@ async function prepareEsbuildOptimizerRun( } plugins.push(esbuildDepPlugin(flatIdDeps, external, config, ssr)) - const esbuild = (await import('esbuild')).default const context = await esbuild.context({ absWorkingDir: process.cwd(), entryPoints: Object.keys(flatIdDeps), @@ -1058,7 +1058,6 @@ export async function extractExportsData( // For custom supported extensions, build the entry file to transform it into JS, // and then parse with es-module-lexer. Note that the `bundle` option is not `true`, // so only the entry file is being transformed. - const { build } = await import('esbuild') const result = await build({ ...esbuildOptions, entryPoints: [filePath], diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index 02a8722eacca4d..b28c13167e5fb6 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -10,6 +10,7 @@ import type { OnLoadResult, Plugin, } from 'esbuild' +import esbuild, { formatMessages, transform } from 'esbuild' import colors from 'picocolors' import type { ResolvedConfig } from '..' import { @@ -134,7 +135,6 @@ export function scanImports(config: ResolvedConfig): { `) if (e.errors) { - const { formatMessages } = await import('esbuild') const msgs = await formatMessages(e.errors, { kind: 'error', color: true, @@ -216,7 +216,6 @@ async function prepareEsbuildScanner( const { plugins = [], ...esbuildOptions } = config.optimizeDeps?.esbuildOptions ?? {} - const esbuild = (await import('esbuild')).default return await esbuild.context({ absWorkingDir: process.cwd(), write: false, @@ -316,7 +315,6 @@ function esbuildScanPlugin( let transpiledContents // transpile because `transformGlobImport` only expects js if (loader !== 'js') { - const { transform } = await import('esbuild') transpiledContents = (await transform(contents, { loader })).code } else { transpiledContents = contents diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 5c34bdaeb11ee3..effeec1203c066 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -22,6 +22,7 @@ import type Less from 'less' import type { Alias } from 'dep-types/alias' import type { LightningCSSOptions } from 'dep-types/lightningcss' import type { TransformOptions } from 'esbuild' +import { formatMessages, transform } from 'esbuild' import type { RawSourceMap } from '@ampproject/remapping' import { getCodeWithSourcemap, injectSourcesContent } from '../server/sourcemap' import type { ModuleNode } from '../server/moduleGraph' @@ -1722,8 +1723,6 @@ async function minifyCSS( // LightningCSS output does not return a linebreak at the end return code.toString() + (inlined ? '' : '\n') } - - const { formatMessages, transform } = await import('esbuild') try { const { code, warnings } = await transform(css, { loader: 'css', diff --git a/packages/vite/src/node/plugins/define.ts b/packages/vite/src/node/plugins/define.ts index e7ca05635e2b85..3eaf2def0efde3 100644 --- a/packages/vite/src/node/plugins/define.ts +++ b/packages/vite/src/node/plugins/define.ts @@ -1,3 +1,4 @@ +import { transform } from 'esbuild' import type { ResolvedConfig } from '../config' import type { Plugin } from '../plugin' import { escapeRegex, getHash } from '../utils' @@ -147,7 +148,6 @@ export async function replaceDefine( const esbuildOptions = config.esbuild || {} - const { transform } = await import('esbuild') const result = await transform(code, { loader: 'js', charset: esbuildOptions.charset ?? 'utf8', diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts index 297817e29b7832..6589756f37f5a6 100644 --- a/packages/vite/src/node/plugins/esbuild.ts +++ b/packages/vite/src/node/plugins/esbuild.ts @@ -6,6 +6,7 @@ import type { TransformOptions, TransformResult, } from 'esbuild' +import { transform } from 'esbuild' import type { RawSourceMap } from '@ampproject/remapping' import type { InternalModuleFormat, SourceMap } from 'rollup' import type { TSConfckParseResult } from 'tsconfck' @@ -172,7 +173,6 @@ export async function transformWithEsbuild( delete resolvedOptions.jsxInject try { - const { transform } = await import('esbuild') const result = await transform(code, resolvedOptions) let map: SourceMap if (inMap && resolvedOptions.sourcemap) { From c978fd9f225b7f599da91ba22003e453140bcd2e Mon Sep 17 00:00:00 2001 From: patak Date: Mon, 22 Jan 2024 16:22:09 +0100 Subject: [PATCH 7/7] chore: revert --- packages/vite/src/node/publicUtils.ts | 2 +- packages/vite/src/node/utils.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/vite/src/node/publicUtils.ts b/packages/vite/src/node/publicUtils.ts index c7dd2f3d1a5566..318c904047b2c0 100644 --- a/packages/vite/src/node/publicUtils.ts +++ b/packages/vite/src/node/publicUtils.ts @@ -4,6 +4,7 @@ * Please control the side-effects by checking the ./dist/node-cjs/publicUtils.cjs bundle */ export { VERSION as version } from './constants' +export { version as esbuildVersion } from 'esbuild' export { splitVendorChunkPlugin, splitVendorChunk, @@ -14,7 +15,6 @@ export { mergeConfig, mergeAlias, createFilter, - esbuildVersion, rollupVersion, } from './utils' export { send } from './server/send' diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 00209d423338d4..a949fd60851313 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -170,8 +170,7 @@ export function resolveDependencyVersion( return JSON.parse(fs.readFileSync(pkgPath, 'utf-8')).version } -export const esbuildVersion = resolveDependencyVersion('rollup') -export const rollupVersion = resolveDependencyVersion('esbuild') +export const rollupVersion = resolveDependencyVersion('rollup') // set in bin/vite.js const filter = process.env.VITE_DEBUG_FILTER