Skip to content

Commit d97ef9e

Browse files
authored
feat: make esbuild optional peer dep (#78)
* feat: use transformWithOxc for extractExportsData * feat: make esbuild optional peer dep * chore: fix types
1 parent 7c66129 commit d97ef9e

File tree

13 files changed

+87
-61
lines changed

13 files changed

+87
-61
lines changed

eslint.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export default tseslint.config(
8787
{
8888
allowModules: [
8989
'vite',
90+
'esbuild',
9091
'less',
9192
'sass',
9293
'sass-embedded',

packages/vite/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@
8585
},
8686
"//": "READ CONTRIBUTING.md to understand what to put under deps vs. devDeps!",
8787
"dependencies": {
88-
"esbuild": "^0.24.0",
8988
"lightningcss": "^1.28.1",
9089
"postcss": "^8.4.49",
9190
"rolldown": "0.15.0-snapshot-3cea4f5-20241211003613",
@@ -119,6 +118,7 @@
119118
"dotenv": "^16.4.5",
120119
"dotenv-expand": "^12.0.1",
121120
"es-module-lexer": "^1.5.4",
121+
"esbuild": "^0.24.0",
122122
"escape-html": "^1.0.3",
123123
"estree-walker": "^3.0.3",
124124
"etag": "^1.8.1",
@@ -155,6 +155,7 @@
155155
},
156156
"peerDependencies": {
157157
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
158+
"esbuild": "^0.24.0",
158159
"jiti": ">=1.21.0",
159160
"less": "*",
160161
"lightningcss": "^1.21.0",
@@ -170,6 +171,9 @@
170171
"@types/node": {
171172
"optional": true
172173
},
174+
"esbuild": {
175+
"optional": true
176+
},
173177
"jiti": {
174178
"optional": true
175179
},

packages/vite/rollup.dts.config.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,11 @@ const identifierReplacements: Record<string, Record<string, string>> = {
5151
Plugin$1: 'rolldown.Plugin',
5252
PluginContext$1: 'rolldown.PluginContext',
5353
TransformPluginContext$1: 'rolldown.TransformPluginContext',
54-
TransformResult$3: 'rolldown.TransformResult',
54+
TransformResult$2: 'rolldown.TransformResult',
5555
},
5656
'rolldown/experimental': {
57-
TransformOptions$2: 'rolldown_experimental_TransformOptions',
58-
TransformResult$2: 'rolldown_experimental_TransformResult',
59-
},
60-
esbuild: {
61-
TransformResult$1: 'esbuild_TransformResult',
62-
TransformOptions$1: 'esbuild_TransformOptions',
63-
BuildOptions$1: 'esbuild_BuildOptions',
57+
TransformOptions$1: 'rolldown_experimental_TransformOptions',
58+
TransformResult$1: 'rolldown_experimental_TransformResult',
6459
},
6560
'node:https': {
6661
Server$1: 'HttpsServer',

packages/vite/src/node/build.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
} from 'rolldown/experimental'
2727
import type { RollupCommonJSOptions } from 'dep-types/commonjs'
2828
import type { RollupDynamicImportVarsOptions } from 'dep-types/dynamicImportVars'
29-
import type { TransformOptions } from 'esbuild'
29+
import type { EsbuildTarget } from 'types/internal/esbuildOptions'
3030
import type { ChunkMetadata } from 'types/metadata'
3131
import { withTrailingSlash } from '../shared/utils'
3232
import {
@@ -101,7 +101,7 @@ export interface BuildEnvironmentOptions {
101101
* https://esbuild.github.io/content-types/#javascript for more details.
102102
* @default 'modules'
103103
*/
104-
target?: 'modules' | TransformOptions['target'] | false
104+
target?: 'modules' | EsbuildTarget | false
105105
/**
106106
* whether to inject module preload polyfill.
107107
* Note: does not apply to library mode.
@@ -154,7 +154,7 @@ export interface BuildEnvironmentOptions {
154154
* doesn't support the #RGBA syntax.
155155
* @default target
156156
*/
157-
cssTarget?: TransformOptions['target'] | false
157+
cssTarget?: EsbuildTarget | false
158158
/**
159159
* Override CSS minification specifically instead of defaulting to `build.minify`,
160160
* so you can configure minification for JS and CSS separately.

packages/vite/src/node/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export type {
134134
StylusPreprocessorOptions,
135135
} from './plugins/css'
136136
export type { JsonOptions } from './plugins/json'
137-
export type { TransformOptions as EsbuildTransformOptions } from 'esbuild'
137+
export type { EsbuildTransformOptions } from 'types/internal/esbuildOptions'
138138
export type { ESBuildOptions, ESBuildTransformResult } from './plugins/esbuild'
139139
export type { Manifest, ManifestChunk } from './plugins/manifest'
140140
export type { ResolveOptions, InternalResolveOptions } from './plugins/resolve'

packages/vite/src/node/optimizer/index.ts

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import path from 'node:path'
44
import { promisify } from 'node:util'
55
import { performance } from 'node:perf_hooks'
66
import colors from 'picocolors'
7-
import type { BuildOptions as EsbuildBuildOptions } from 'esbuild'
87
import { init, parse } from 'es-module-lexer'
98
import { isDynamicPattern } from 'tinyglobby'
109
import {
@@ -13,6 +12,7 @@ import {
1312
type OutputOptions as RollupOutputOptions,
1413
rolldown,
1514
} from 'rolldown'
15+
import type { DepsOptimizerEsbuildOptions } from 'types/internal/esbuildOptions'
1616
import type { ResolvedConfig } from '../config'
1717
import {
1818
arraify,
@@ -28,10 +28,10 @@ import {
2828
tryStatSync,
2929
unique,
3030
} from '../utils'
31-
import { transformWithEsbuild } from '../plugins/esbuild'
3231
import { METADATA_FILENAME } from '../constants'
3332
import { isWindows } from '../../shared/utils'
3433
import type { Environment } from '../environment'
34+
import { transformWithOxc } from '../plugins/oxc'
3535
import { ScanEnvironment, scanImports } from './scan'
3636
import { createOptimizeDepsIncludeResolver, expandGlobIds } from './resolve'
3737
import {
@@ -96,19 +96,7 @@ export interface DepOptimizationConfig {
9696
*
9797
* https://esbuild.github.io/api
9898
*/
99-
esbuildOptions?: Omit<
100-
EsbuildBuildOptions,
101-
| 'bundle'
102-
| 'entryPoints'
103-
| 'external'
104-
| 'write'
105-
| 'watch'
106-
| 'outdir'
107-
| 'outfile'
108-
| 'outbase'
109-
| 'outExtension'
110-
| 'metafile'
111-
>
99+
esbuildOptions?: DepsOptimizerEsbuildOptions
112100
rollupOptions?: Omit<RollupOptions, 'input' | 'logLevel' | 'output'> & {
113101
output?: Omit<
114102
RollupOutputOptions,
@@ -1100,14 +1088,18 @@ export async function extractExportsData(
11001088
try {
11011089
parseResult = parse(entryContent)
11021090
} catch {
1103-
const loader = rollupOptions.moduleTypes?.[path.extname(filePath)] || 'jsx'
1091+
const lang = rollupOptions.moduleTypes?.[path.extname(filePath)] || 'jsx'
11041092
debug?.(
1105-
`Unable to parse: ${filePath}.\n Trying again with a ${loader} transform.`,
1093+
`Unable to parse: ${filePath}.\n Trying again with a ${lang} transform.`,
11061094
)
1107-
const transformed = await transformWithEsbuild(
1095+
if (lang !== 'jsx' && lang !== 'tsx' && lang !== 'ts') {
1096+
throw new Error(`Unable to parse : ${filePath}.`)
1097+
}
1098+
const transformed = await transformWithOxc(
1099+
undefined,
11081100
entryContent,
11091101
filePath,
1110-
{ loader },
1102+
{ lang },
11111103
undefined,
11121104
environment.config,
11131105
)

packages/vite/src/node/optimizer/scan.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import fs from 'node:fs'
22
import fsp from 'node:fs/promises'
33
import path from 'node:path'
44
import { performance } from 'node:perf_hooks'
5-
import type { Loader } from 'esbuild'
65
import { scan, transform } from 'rolldown/experimental'
76
import type { PartialResolvedId, Plugin } from 'rolldown'
87
import colors from 'picocolors'
@@ -335,6 +334,8 @@ function globEntries(pattern: string | string[], environment: ScanEnvironment) {
335334
})
336335
}
337336

337+
type Loader = 'js' | 'ts' | 'jsx' | 'tsx'
338+
338339
export const scriptRE =
339340
/(<script(?:\s+[a-z_:][-\w:]*(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^"'<>=\s]+))?)*\s*>)(.*?)<\/script>/gis
340341
export const commentRE = /<!--.*?-->/gs

packages/vite/src/node/plugins/css.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import type Stylus from 'stylus'
2323
import type Less from 'less'
2424
import type { Alias } from 'dep-types/alias'
2525
import type { LightningCSSOptions } from 'types/internal/lightningcssOptions'
26-
import type { TransformOptions } from 'esbuild'
2726
import type { RawSourceMap } from '@ampproject/remapping'
2827
import { WorkerWithFallback } from 'artichokie'
2928
import { globSync } from 'tinyglobby'
@@ -37,6 +36,7 @@ import type {
3736
TransformAttributeResult as LightningCssTransformAttributeResult,
3837
TransformResult as LightningCssTransformResult,
3938
} from 'lightningcss'
39+
import type { EsbuildTransformOptions } from 'types/internal/esbuildOptions'
4040
import { getCodeWithSourcemap, injectSourcesContent } from '../server/sourcemap'
4141
import type { EnvironmentModuleNode } from '../server/moduleGraph'
4242
import {
@@ -1989,8 +1989,8 @@ async function minifyCSS(
19891989

19901990
function resolveMinifyCssEsbuildOptions(
19911991
options: ESBuildOptions,
1992-
): TransformOptions {
1993-
const base: TransformOptions = {
1992+
): EsbuildTransformOptions {
1993+
const base: EsbuildTransformOptions = {
19941994
charset: options.charset ?? 'utf8',
19951995
logLevel: options.logLevel,
19961996
logLimit: options.logLimit,

packages/vite/src/node/plugins/esbuild.ts

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
import path from 'node:path'
22
import colors from 'picocolors'
3-
import type {
4-
Loader,
5-
Message,
6-
TransformOptions,
7-
TransformResult,
8-
} from 'esbuild'
9-
import { transform } from 'esbuild'
103
import type { RawSourceMap } from '@ampproject/remapping'
114
import type { InternalModuleFormat, SourceMap } from 'rolldown'
125
import type { TSConfckParseResult } from 'tsconfck'
136
import { TSConfckCache, TSConfckParseError, parse } from 'tsconfck'
147
import type { FSWatcher } from 'dep-types/chokidar'
8+
import type {
9+
EsbuildLoader,
10+
EsbuildMessage,
11+
EsbuildTransformOptions,
12+
EsbuildTransformResult as RawEsbuildTransformResult,
13+
} from 'types/internal/esbuildOptions'
1514
import {
1615
combineSourcemaps,
1716
createDebugger,
@@ -42,7 +41,7 @@ export const defaultEsbuildSupported = {
4241
'import-meta': true,
4342
}
4443

45-
export interface ESBuildOptions extends TransformOptions {
44+
export interface ESBuildOptions extends EsbuildTransformOptions {
4645
include?: string | RegExp | string[] | RegExp[]
4746
exclude?: string | RegExp | string[] | RegExp[]
4847
jsxInject?: string
@@ -52,7 +51,7 @@ export interface ESBuildOptions extends TransformOptions {
5251
minify?: never
5352
}
5453

55-
export type ESBuildTransformResult = Omit<TransformResult, 'map'> & {
54+
export type ESBuildTransformResult = Omit<RawEsbuildTransformResult, 'map'> & {
5655
map: SourceMap
5756
}
5857

@@ -75,10 +74,16 @@ type TSConfigJSON = {
7574
}
7675
type TSCompilerOptions = NonNullable<TSConfigJSON['compilerOptions']>
7776

77+
let esbuild: Promise<typeof import('esbuild')> | undefined
78+
const importEsbuild = () => {
79+
esbuild ||= import('esbuild')
80+
return esbuild
81+
}
82+
7883
export async function transformWithEsbuild(
7984
code: string,
8085
filename: string,
81-
options?: TransformOptions,
86+
options?: EsbuildTransformOptions,
8287
inMap?: object,
8388
config?: ResolvedConfig,
8489
watcher?: FSWatcher,
@@ -97,7 +102,7 @@ export async function transformWithEsbuild(
97102
} else if (ext === 'cts' || ext === 'mts') {
98103
loader = 'ts'
99104
} else {
100-
loader = ext as Loader
105+
loader = ext as EsbuildLoader
101106
}
102107
}
103108

@@ -178,7 +183,7 @@ export async function transformWithEsbuild(
178183
}
179184
}
180185

181-
const resolvedOptions: TransformOptions = {
186+
const resolvedOptions: EsbuildTransformOptions = {
182187
sourcemap: true,
183188
// ensure source file name contains full query
184189
sourcefile: filename,
@@ -197,6 +202,7 @@ export async function transformWithEsbuild(
197202
delete resolvedOptions.jsxInject
198203

199204
try {
205+
const { transform } = await importEsbuild()
200206
const result = await transform(code, resolvedOptions)
201207
let map: SourceMap
202208
if (inMap && resolvedOptions.sourcemap) {
@@ -221,7 +227,7 @@ export async function transformWithEsbuild(
221227
// patch error information
222228
if (e.errors) {
223229
e.frame = ''
224-
e.errors.forEach((m: Message) => {
230+
e.errors.forEach((m: EsbuildMessage) => {
225231
if (
226232
m.text === 'Experimental decorators are not currently enabled' ||
227233
m.text ===
@@ -246,7 +252,7 @@ export function esbuildPlugin(config: ResolvedConfig): Plugin {
246252

247253
// Remove optimization options for dev as we only need to transpile them,
248254
// and for build as the final optimization is in `buildEsbuildPlugin`
249-
const transformOptions: TransformOptions = {
255+
const transformOptions: EsbuildTransformOptions = {
250256
target: 'esnext',
251257
charset: 'utf8',
252258
...esbuildTransformOptions,
@@ -301,7 +307,7 @@ export function esbuildPlugin(config: ResolvedConfig): Plugin {
301307

302308
const rollupToEsbuildFormatMap: Record<
303309
string,
304-
TransformOptions['format'] | undefined
310+
EsbuildTransformOptions['format'] | undefined
305311
> = {
306312
es: 'esm',
307313
cjs: 'cjs',
@@ -375,7 +381,7 @@ export const buildEsbuildPlugin = (config: ResolvedConfig): Plugin => {
375381
export function resolveEsbuildTranspileOptions(
376382
config: ResolvedConfig,
377383
format: InternalModuleFormat,
378-
): TransformOptions | null {
384+
): EsbuildTransformOptions | null {
379385
const target = config.build.target
380386
const minify = config.build.minify === 'esbuild'
381387

@@ -389,7 +395,7 @@ export function resolveEsbuildTranspileOptions(
389395
const isEsLibBuild = config.build.lib && format === 'es'
390396
const esbuildOptions = config.esbuild || {}
391397

392-
const options: TransformOptions = {
398+
const options: EsbuildTransformOptions = {
393399
charset: 'utf8',
394400
...esbuildOptions,
395401
loader: 'js',
@@ -461,7 +467,7 @@ export function resolveEsbuildTranspileOptions(
461467
}
462468
}
463469

464-
function prettifyMessage(m: Message, code: string): string {
470+
function prettifyMessage(m: EsbuildMessage, code: string): string {
465471
let res = colors.yellow(m.text)
466472
if (m.location) {
467473
res += `\n` + generateCodeFrame(code, m.location)

packages/vite/src/node/plugins/oxc.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export interface OxcOptions extends OxcTransformOptions {
4242
}
4343

4444
export async function transformWithOxc(
45-
ctx: PluginContext,
45+
ctx: PluginContext | undefined,
4646
code: string,
4747
filename: string,
4848
options?: OxcTransformOptions,
@@ -110,7 +110,7 @@ export async function transformWithOxc(
110110
break
111111
case 'preserve':
112112
if (lang === 'tsx') {
113-
ctx.warn('The tsconfig jsx preserve is not supported by oxc')
113+
ctx?.warn('The tsconfig jsx preserve is not supported by oxc')
114114
}
115115
break
116116
default:
@@ -151,7 +151,7 @@ export async function transformWithOxc(
151151
resolvedOptions.typescript ??= {}
152152
resolvedOptions.typescript.onlyRemoveTypeImports = false
153153
} else {
154-
ctx.warn(
154+
ctx?.warn(
155155
`preserveValueImports=${preserveValueImports} + importsNotUsedAsValues=${importsNotUsedAsValues} is not supported by oxc.` +
156156
'Please migrate to the new verbatimModuleSyntax option.',
157157
)

0 commit comments

Comments
 (0)