Skip to content

Commit

Permalink
feat: using oxc transfomer
Browse files Browse the repository at this point in the history
  • Loading branch information
underfin committed Sep 29, 2024
1 parent d0518d3 commit 74677f5
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 7 deletions.
2 changes: 2 additions & 0 deletions packages/vite/src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ import type { ResolvedSSROptions, SSROptions } from './ssr'
import { resolveSSROptions } from './ssr'
import { PartialEnvironment } from './baseEnvironment'
import { createIdResolver } from './idResolver'
import type { OxcOptions } from './plugins/oxc'

const debug = createDebugger('vite:config')
const promisifiedRealpath = promisify(fs.realpath)
Expand Down Expand Up @@ -571,6 +572,7 @@ export type ResolvedConfig = Readonly<
plugins: readonly Plugin[]
css: ResolvedCSSOptions
esbuild: ESBuildOptions | false
oxc: OxcOptions | false
server: ResolvedServerOptions
dev: ResolvedDevEnvironmentOptions
builder: ResolvedBuilderOptions
Expand Down
9 changes: 4 additions & 5 deletions packages/vite/src/node/optimizer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ import {
unique,
} from '../utils'
import { transformWithEsbuild } from '../plugins/esbuild'
import { ESBUILD_MODULES_TARGET, METADATA_FILENAME } from '../constants'
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 {
Expand Down Expand Up @@ -752,12 +753,10 @@ async function prepareRolldownOptimizerRun(
name: 'optimizer-transform',
async transform(code, id) {
if (/\.(?:m?[jt]s|[jt]sx)$/.test(id)) {
const result = await transformWithEsbuild(code, id, {
const result = await transformWithOxc(code, id, {
sourcemap: true,
sourcefile: id,
loader: jsxLoader && /\.js$/.test(id) ? 'jsx' : undefined,
jsx: jsxLoader && /\.js$/.test(id) ? true : undefined,
define,
target: ESBUILD_MODULES_TARGET,
})
return {
code: result.code,
Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/node/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { getFsUtils } from '../fsUtils'
import { jsonPlugin } from './json'
import { filteredResolvePlugin, resolvePlugin } from './resolve'
import { optimizedDepsPlugin } from './optimizedDeps'
import { esbuildPlugin } from './esbuild'
import { importAnalysisPlugin } from './importAnalysis'
import { cssAnalysisPlugin, cssPlugin, cssPostPlugin } from './css'
import { assetPlugin } from './asset'
Expand All @@ -34,6 +33,7 @@ import { assetImportMetaUrlPlugin } from './assetImportMetaUrl'
import { metadataPlugin } from './metadata'
import { dynamicImportVarsPlugin } from './dynamicImportVars'
import { importGlobPlugin } from './importMetaGlob'
import { oxcPlugin } from './oxc'

export async function resolvePlugins(
config: ResolvedConfig,
Expand Down Expand Up @@ -114,7 +114,7 @@ export async function resolvePlugins(
config.esbuild !== false
? enableNativePlugin
? nativeTransformPlugin()
: esbuildPlugin(config)
: oxcPlugin(config)
: null,
enableNativePlugin
? nativeJsonPlugin({
Expand Down
119 changes: 119 additions & 0 deletions packages/vite/src/node/plugins/oxc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import path from 'node:path'
import { transform } from 'rolldown/experimental'
import type { RawSourceMap } from '@ampproject/remapping'
import type { SourceMap } from 'rolldown'
import { combineSourcemaps, createFilter } from '../utils'
import type { ResolvedConfig } from '../config'
import type { Plugin } from '../plugin'
import { cleanUrl } from '../../shared/utils'
import { loadTsconfigJsonForFile } from './esbuild'

const jsxExtensionsRE = /\.(?:j|t)sx\b/
const validExtensionRE = /\.\w+$/

// should import from rolldown
declare type TransformOptions = any
declare type TransformResult = any

export interface OxcOptions extends TransformOptions {
include?: string | RegExp | string[] | RegExp[]
exclude?: string | RegExp | string[] | RegExp[]
jsxInject?: string
}

export async function transformWithOxc(
code: string,
filename: string,
options?: TransformOptions,
inMap?: object,
): Promise<TransformResult> {
const resolvedOptions = {
sourcemap: true,
...options,
}

const ext = path
.extname(validExtensionRE.test(filename) ? filename : cleanUrl(filename))
.slice(1)

if (ext === 'cts' || ext === 'mts' || ext === 'tsx' || ext === 'ts') {
const loadedTsconfig = await loadTsconfigJsonForFile(filename)
const loadedCompilerOptions = loadedTsconfig.compilerOptions ?? {}
// tsc compiler alwaysStrict/experimentalDecorators/importsNotUsedAsValues/preserveValueImports/target/useDefineForClassFields/verbatimModuleSyntax

resolvedOptions.react = {
jsxFactory: loadedCompilerOptions.jsx,
pragma: loadedCompilerOptions.jsxFactory,
pragmaFrag: loadedCompilerOptions.jsxFragmentFactory,
importSource: loadedCompilerOptions.jsxImportSource,
development: loadedCompilerOptions.jsx === 'react-jsxdev',
runtime: loadedCompilerOptions.jsx === 'react-jsxdev',
}

switch (loadedCompilerOptions.jsx) {
case 'react-jsxdev':
resolvedOptions.react.runtime = 'automatic'
resolvedOptions.react.development = true
break

case 'react':
resolvedOptions.react.runtime = 'classic'
break

case 'react-jsx':
resolvedOptions.react.runtime = 'automatic'
break
case 'preserve':
// not support
break

default:
break
}
}

const result = await transform(filename, code, resolvedOptions)

if (result.errors.length > 0) {
throw new Error(result.errors[0])
}

let map: SourceMap
if (inMap && result.map) {
const nextMap = result.map
nextMap.sourcesContent = []
map = combineSourcemaps(filename, [
nextMap as RawSourceMap,
inMap as RawSourceMap,
]) as SourceMap
} else {
map = result.map as SourceMap
}
return {
...result,
map,
}
}

export function oxcPlugin(config: ResolvedConfig): Plugin {
const options = config.oxc as OxcOptions
const { jsxInject, include, exclude, ...oxcTransformOptions } = options

const filter = createFilter(include || /\.(m?ts|[jt]sx)$/, exclude || /\.js$/)

return {
name: 'vite:oxc',
async transform(code, id) {
if (filter(id) || filter(cleanUrl(id))) {
const result = await transformWithOxc(code, id, oxcTransformOptions)
if (jsxInject && jsxExtensionsRE.test(id)) {
result.code = jsxInject + ';' + result.code
}
return {
code: result.code,
map: result.map,
}
}
},
}
}

0 comments on commit 74677f5

Please sign in to comment.