From 4402cc7780ea4f78a5cf3b805409ad168da0d44d Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Thu, 12 Dec 2024 15:48:53 +0900 Subject: [PATCH 1/3] feat: use transformWithOxc for extractExportsData --- packages/vite/src/node/optimizer/index.ts | 14 +++++++++----- packages/vite/src/node/plugins/oxc.ts | 6 +++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 47bbac7ce5fec6..15ac2f8d94a71c 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -28,10 +28,10 @@ import { tryStatSync, unique, } from '../utils' -import { transformWithEsbuild } from '../plugins/esbuild' import { METADATA_FILENAME } from '../constants' import { isWindows } from '../../shared/utils' import type { Environment } from '../environment' +import { transformWithOxc } from '../plugins/oxc' import { ScanEnvironment, scanImports } from './scan' import { createOptimizeDepsIncludeResolver, expandGlobIds } from './resolve' import { @@ -1100,14 +1100,18 @@ export async function extractExportsData( try { parseResult = parse(entryContent) } catch { - const loader = rollupOptions.moduleTypes?.[path.extname(filePath)] || 'jsx' + const lang = rollupOptions.moduleTypes?.[path.extname(filePath)] || 'jsx' debug?.( - `Unable to parse: ${filePath}.\n Trying again with a ${loader} transform.`, + `Unable to parse: ${filePath}.\n Trying again with a ${lang} transform.`, ) - const transformed = await transformWithEsbuild( + if (lang !== 'jsx' && lang !== 'tsx' && lang !== 'ts') { + throw new Error(`Unable to parse : ${filePath}.`) + } + const transformed = await transformWithOxc( + undefined, entryContent, filePath, - { loader }, + { lang }, undefined, environment.config, ) diff --git a/packages/vite/src/node/plugins/oxc.ts b/packages/vite/src/node/plugins/oxc.ts index b5e2b9e7e30393..5962bcc7fd94c0 100644 --- a/packages/vite/src/node/plugins/oxc.ts +++ b/packages/vite/src/node/plugins/oxc.ts @@ -42,7 +42,7 @@ export interface OxcOptions extends OxcTransformOptions { } export async function transformWithOxc( - ctx: PluginContext, + ctx: PluginContext | undefined, code: string, filename: string, options?: OxcTransformOptions, @@ -110,7 +110,7 @@ export async function transformWithOxc( break case 'preserve': if (lang === 'tsx') { - ctx.warn('The tsconfig jsx preserve is not supported by oxc') + ctx?.warn('The tsconfig jsx preserve is not supported by oxc') } break default: @@ -151,7 +151,7 @@ export async function transformWithOxc( resolvedOptions.typescript ??= {} resolvedOptions.typescript.onlyRemoveTypeImports = false } else { - ctx.warn( + ctx?.warn( `preserveValueImports=${preserveValueImports} + importsNotUsedAsValues=${importsNotUsedAsValues} is not supported by oxc.` + 'Please migrate to the new verbatimModuleSyntax option.', ) From c87cd8a5fd9b80372f8243f519307807adab3870 Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:58:10 +0900 Subject: [PATCH 2/3] feat: make esbuild optional peer dep --- packages/vite/package.json | 6 +++++- packages/vite/src/node/plugins/esbuild.ts | 8 +++++++- packages/vite/src/node/publicUtils.ts | 1 - pnpm-lock.yaml | 6 +++--- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/vite/package.json b/packages/vite/package.json index e0c3b7596398d6..7e3a3789361bd9 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -85,7 +85,6 @@ }, "//": "READ CONTRIBUTING.md to understand what to put under deps vs. devDeps!", "dependencies": { - "esbuild": "^0.24.0", "lightningcss": "^1.28.1", "postcss": "^8.4.49", "rolldown": "0.15.0-snapshot-3cea4f5-20241211003613", @@ -119,6 +118,7 @@ "dotenv": "^16.4.5", "dotenv-expand": "^12.0.1", "es-module-lexer": "^1.5.4", + "esbuild": "^0.24.0", "escape-html": "^1.0.3", "estree-walker": "^3.0.3", "etag": "^1.8.1", @@ -155,6 +155,7 @@ }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "esbuild": "^0.24.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", @@ -170,6 +171,9 @@ "@types/node": { "optional": true }, + "esbuild": { + "optional": true + }, "jiti": { "optional": true }, diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts index f56a73fd9d745d..498a7e6230450d 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 'rolldown' import type { TSConfckParseResult } from 'tsconfck' @@ -75,6 +74,12 @@ type TSConfigJSON = { } type TSCompilerOptions = NonNullable +let esbuild: Promise | undefined +const importEsbuild = () => { + esbuild ||= import('esbuild') + return esbuild +} + export async function transformWithEsbuild( code: string, filename: string, @@ -197,6 +202,7 @@ export async function transformWithEsbuild( delete resolvedOptions.jsxInject try { + const { transform } = await importEsbuild() const result = await transform(code, resolvedOptions) let map: SourceMap if (inMap && resolvedOptions.sourcemap) { diff --git a/packages/vite/src/node/publicUtils.ts b/packages/vite/src/node/publicUtils.ts index d27fed085e0890..32fd89306e622f 100644 --- a/packages/vite/src/node/publicUtils.ts +++ b/packages/vite/src/node/publicUtils.ts @@ -10,7 +10,6 @@ export { DEFAULT_SERVER_CONDITIONS as defaultServerConditions, DEFAULT_SERVER_MAIN_FIELDS as defaultServerMainFields, } from './constants' -export { version as esbuildVersion } from 'esbuild' export { splitVendorChunkPlugin, splitVendorChunk, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9bce40d45f75f4..3198c4a032b07a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -223,9 +223,6 @@ importers: packages/vite: dependencies: - esbuild: - specifier: ^0.24.0 - version: 0.24.0 lightningcss: specifier: ^1.28.1 version: 1.28.1 @@ -315,6 +312,9 @@ importers: es-module-lexer: specifier: ^1.5.4 version: 1.5.4 + esbuild: + specifier: ^0.24.0 + version: 0.24.0 escape-html: specifier: ^1.0.3 version: 1.0.3 From a0bcc0b08732db417810000925fac62e5aea07e9 Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:13:44 +0900 Subject: [PATCH 3/3] chore: fix types --- eslint.config.js | 1 + packages/vite/rollup.dts.config.ts | 11 ++---- packages/vite/src/node/build.ts | 6 ++-- packages/vite/src/node/index.ts | 2 +- packages/vite/src/node/optimizer/index.ts | 16 ++------- packages/vite/src/node/optimizer/scan.ts | 3 +- packages/vite/src/node/plugins/css.ts | 6 ++-- packages/vite/src/node/plugins/esbuild.ts | 34 +++++++++---------- .../vite/types/internal/esbuildOptions.d.ts | 28 +++++++++++++++ 9 files changed, 60 insertions(+), 47 deletions(-) create mode 100644 packages/vite/types/internal/esbuildOptions.d.ts diff --git a/eslint.config.js b/eslint.config.js index 968a7a89b5e1a4..840006457b7516 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -87,6 +87,7 @@ export default tseslint.config( { allowModules: [ 'vite', + 'esbuild', 'less', 'sass', 'sass-embedded', diff --git a/packages/vite/rollup.dts.config.ts b/packages/vite/rollup.dts.config.ts index 4eadc4653d1183..3ee504666ba8d4 100644 --- a/packages/vite/rollup.dts.config.ts +++ b/packages/vite/rollup.dts.config.ts @@ -51,16 +51,11 @@ const identifierReplacements: Record> = { Plugin$1: 'rolldown.Plugin', PluginContext$1: 'rolldown.PluginContext', TransformPluginContext$1: 'rolldown.TransformPluginContext', - TransformResult$3: 'rolldown.TransformResult', + TransformResult$2: 'rolldown.TransformResult', }, 'rolldown/experimental': { - TransformOptions$2: 'rolldown_experimental_TransformOptions', - TransformResult$2: 'rolldown_experimental_TransformResult', - }, - esbuild: { - TransformResult$1: 'esbuild_TransformResult', - TransformOptions$1: 'esbuild_TransformOptions', - BuildOptions$1: 'esbuild_BuildOptions', + TransformOptions$1: 'rolldown_experimental_TransformOptions', + TransformResult$1: 'rolldown_experimental_TransformResult', }, 'node:https': { Server$1: 'HttpsServer', diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index 3a7a7254d3cbdd..ffe31aef3ac5ec 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -26,7 +26,7 @@ import { } from 'rolldown/experimental' import type { RollupCommonJSOptions } from 'dep-types/commonjs' import type { RollupDynamicImportVarsOptions } from 'dep-types/dynamicImportVars' -import type { TransformOptions } from 'esbuild' +import type { EsbuildTarget } from 'types/internal/esbuildOptions' import type { ChunkMetadata } from 'types/metadata' import { withTrailingSlash } from '../shared/utils' import { @@ -101,7 +101,7 @@ export interface BuildEnvironmentOptions { * https://esbuild.github.io/content-types/#javascript for more details. * @default 'modules' */ - target?: 'modules' | TransformOptions['target'] | false + target?: 'modules' | EsbuildTarget | false /** * whether to inject module preload polyfill. * Note: does not apply to library mode. @@ -154,7 +154,7 @@ export interface BuildEnvironmentOptions { * doesn't support the #RGBA syntax. * @default target */ - cssTarget?: TransformOptions['target'] | false + cssTarget?: EsbuildTarget | false /** * Override CSS minification specifically instead of defaulting to `build.minify`, * so you can configure minification for JS and CSS separately. diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts index 04b5c7d8d6e621..5e3cb591ba2404 100644 --- a/packages/vite/src/node/index.ts +++ b/packages/vite/src/node/index.ts @@ -134,7 +134,7 @@ export type { StylusPreprocessorOptions, } from './plugins/css' export type { JsonOptions } from './plugins/json' -export type { TransformOptions as EsbuildTransformOptions } from 'esbuild' +export type { EsbuildTransformOptions } from 'types/internal/esbuildOptions' export type { ESBuildOptions, ESBuildTransformResult } from './plugins/esbuild' export type { Manifest, ManifestChunk } from './plugins/manifest' export type { ResolveOptions, InternalResolveOptions } from './plugins/resolve' diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 15ac2f8d94a71c..92fb57d5a9a9e6 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -4,7 +4,6 @@ import path from 'node:path' import { promisify } from 'node:util' import { performance } from 'node:perf_hooks' import colors from 'picocolors' -import type { BuildOptions as EsbuildBuildOptions } from 'esbuild' import { init, parse } from 'es-module-lexer' import { isDynamicPattern } from 'tinyglobby' import { @@ -13,6 +12,7 @@ import { type OutputOptions as RollupOutputOptions, rolldown, } from 'rolldown' +import type { DepsOptimizerEsbuildOptions } from 'types/internal/esbuildOptions' import type { ResolvedConfig } from '../config' import { arraify, @@ -96,19 +96,7 @@ export interface DepOptimizationConfig { * * https://esbuild.github.io/api */ - esbuildOptions?: Omit< - EsbuildBuildOptions, - | 'bundle' - | 'entryPoints' - | 'external' - | 'write' - | 'watch' - | 'outdir' - | 'outfile' - | 'outbase' - | 'outExtension' - | 'metafile' - > + esbuildOptions?: DepsOptimizerEsbuildOptions rollupOptions?: Omit & { output?: Omit< RollupOutputOptions, diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index a4356b509795a8..922a37b2864309 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -2,7 +2,6 @@ import fs from 'node:fs' import fsp from 'node:fs/promises' import path from 'node:path' import { performance } from 'node:perf_hooks' -import type { Loader } from 'esbuild' import { scan, transform } from 'rolldown/experimental' import type { PartialResolvedId, Plugin } from 'rolldown' import colors from 'picocolors' @@ -335,6 +334,8 @@ function globEntries(pattern: string | string[], environment: ScanEnvironment) { }) } +type Loader = 'js' | 'ts' | 'jsx' | 'tsx' + export const scriptRE = /(=\s]+))?)*\s*>)(.*?)<\/script>/gis export const commentRE = //gs diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 92419dec8fbe83..294cd5104ac768 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -23,7 +23,6 @@ import type Stylus from 'stylus' import type Less from 'less' import type { Alias } from 'dep-types/alias' import type { LightningCSSOptions } from 'types/internal/lightningcssOptions' -import type { TransformOptions } from 'esbuild' import type { RawSourceMap } from '@ampproject/remapping' import { WorkerWithFallback } from 'artichokie' import { globSync } from 'tinyglobby' @@ -37,6 +36,7 @@ import type { TransformAttributeResult as LightningCssTransformAttributeResult, TransformResult as LightningCssTransformResult, } from 'lightningcss' +import type { EsbuildTransformOptions } from 'types/internal/esbuildOptions' import { getCodeWithSourcemap, injectSourcesContent } from '../server/sourcemap' import type { EnvironmentModuleNode } from '../server/moduleGraph' import { @@ -1989,8 +1989,8 @@ async function minifyCSS( function resolveMinifyCssEsbuildOptions( options: ESBuildOptions, -): TransformOptions { - const base: TransformOptions = { +): EsbuildTransformOptions { + const base: EsbuildTransformOptions = { charset: options.charset ?? 'utf8', logLevel: options.logLevel, logLimit: options.logLimit, diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts index 498a7e6230450d..cf3c0ea7f8a0c9 100644 --- a/packages/vite/src/node/plugins/esbuild.ts +++ b/packages/vite/src/node/plugins/esbuild.ts @@ -1,16 +1,16 @@ import path from 'node:path' import colors from 'picocolors' -import type { - Loader, - Message, - TransformOptions, - TransformResult, -} from 'esbuild' import type { RawSourceMap } from '@ampproject/remapping' import type { InternalModuleFormat, SourceMap } from 'rolldown' import type { TSConfckParseResult } from 'tsconfck' import { TSConfckCache, TSConfckParseError, parse } from 'tsconfck' import type { FSWatcher } from 'dep-types/chokidar' +import type { + EsbuildLoader, + EsbuildMessage, + EsbuildTransformOptions, + EsbuildTransformResult as RawEsbuildTransformResult, +} from 'types/internal/esbuildOptions' import { combineSourcemaps, createDebugger, @@ -41,7 +41,7 @@ export const defaultEsbuildSupported = { 'import-meta': true, } -export interface ESBuildOptions extends TransformOptions { +export interface ESBuildOptions extends EsbuildTransformOptions { include?: string | RegExp | string[] | RegExp[] exclude?: string | RegExp | string[] | RegExp[] jsxInject?: string @@ -51,7 +51,7 @@ export interface ESBuildOptions extends TransformOptions { minify?: never } -export type ESBuildTransformResult = Omit & { +export type ESBuildTransformResult = Omit & { map: SourceMap } @@ -83,7 +83,7 @@ const importEsbuild = () => { export async function transformWithEsbuild( code: string, filename: string, - options?: TransformOptions, + options?: EsbuildTransformOptions, inMap?: object, config?: ResolvedConfig, watcher?: FSWatcher, @@ -102,7 +102,7 @@ export async function transformWithEsbuild( } else if (ext === 'cts' || ext === 'mts') { loader = 'ts' } else { - loader = ext as Loader + loader = ext as EsbuildLoader } } @@ -183,7 +183,7 @@ export async function transformWithEsbuild( } } - const resolvedOptions: TransformOptions = { + const resolvedOptions: EsbuildTransformOptions = { sourcemap: true, // ensure source file name contains full query sourcefile: filename, @@ -227,7 +227,7 @@ export async function transformWithEsbuild( // patch error information if (e.errors) { e.frame = '' - e.errors.forEach((m: Message) => { + e.errors.forEach((m: EsbuildMessage) => { if ( m.text === 'Experimental decorators are not currently enabled' || m.text === @@ -252,7 +252,7 @@ export function esbuildPlugin(config: ResolvedConfig): Plugin { // Remove optimization options for dev as we only need to transpile them, // and for build as the final optimization is in `buildEsbuildPlugin` - const transformOptions: TransformOptions = { + const transformOptions: EsbuildTransformOptions = { target: 'esnext', charset: 'utf8', ...esbuildTransformOptions, @@ -307,7 +307,7 @@ export function esbuildPlugin(config: ResolvedConfig): Plugin { const rollupToEsbuildFormatMap: Record< string, - TransformOptions['format'] | undefined + EsbuildTransformOptions['format'] | undefined > = { es: 'esm', cjs: 'cjs', @@ -381,7 +381,7 @@ export const buildEsbuildPlugin = (config: ResolvedConfig): Plugin => { export function resolveEsbuildTranspileOptions( config: ResolvedConfig, format: InternalModuleFormat, -): TransformOptions | null { +): EsbuildTransformOptions | null { const target = config.build.target const minify = config.build.minify === 'esbuild' @@ -395,7 +395,7 @@ export function resolveEsbuildTranspileOptions( const isEsLibBuild = config.build.lib && format === 'es' const esbuildOptions = config.esbuild || {} - const options: TransformOptions = { + const options: EsbuildTransformOptions = { charset: 'utf8', ...esbuildOptions, loader: 'js', @@ -467,7 +467,7 @@ export function resolveEsbuildTranspileOptions( } } -function prettifyMessage(m: Message, code: string): string { +function prettifyMessage(m: EsbuildMessage, code: string): string { let res = colors.yellow(m.text) if (m.location) { res += `\n` + generateCodeFrame(code, m.location) diff --git a/packages/vite/types/internal/esbuildOptions.d.ts b/packages/vite/types/internal/esbuildOptions.d.ts new file mode 100644 index 00000000000000..f1637a642a55ae --- /dev/null +++ b/packages/vite/types/internal/esbuildOptions.d.ts @@ -0,0 +1,28 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ + +// @ts-ignore `esbuild` may not be installed +import type esbuild from 'esbuild' + +/* eslint-enable @typescript-eslint/ban-ts-comment */ + +export type EsbuildTarget = string | string[] + +export type EsbuildLoader = esbuild.Loader +export type EsbuildTransformOptions = esbuild.TransformOptions +export type EsbuildTransformResult = esbuild.TransformResult + +export type EsbuildMessage = esbuild.Message + +export type DepsOptimizerEsbuildOptions = Omit< + esbuild.BuildOptions, + | 'bundle' + | 'entryPoints' + | 'external' + | 'write' + | 'watch' + | 'outdir' + | 'outfile' + | 'outbase' + | 'outExtension' + | 'metafile' +>