Skip to content

Commit

Permalink
move to oxc and use babel for classes
Browse files Browse the repository at this point in the history
  • Loading branch information
natew committed Feb 9, 2025
1 parent 2301c95 commit cefcef9
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 89 deletions.
3 changes: 3 additions & 0 deletions packages/compiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
},
"dependencies": {
"@babel/core": "^7.26.0",
"@babel/plugin-transform-class-properties": "^7.25.9",
"@babel/plugin-transform-classes": "^7.25.9",
"@babel/plugin-transform-destructuring": "^7.25.9",
"@babel/plugin-transform-private-methods": "^7.25.9",
"@babel/plugin-transform-react-jsx": "^7.25.9",
Expand All @@ -37,6 +39,7 @@
"@vxrn/utils": "workspace:*",
"@vxrn/vite-native-client": "workspace:*",
"babel-plugin-react-compiler": "^19.0.0-beta-201e55d-20241215",
"oxc-transform": "^0.48.2",
"react-native-css-interop": "^0.1.22",
"ts-deepmerge": "^7.0.2",
"vite": "^6.1.0"
Expand Down
2 changes: 2 additions & 0 deletions packages/compiler/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ export const parsers: Record<string, ParserConfig> = {
}

export const validParsers = new Set([...Object.keys(parsers), '.css'])

export const USE_OXC = false
7 changes: 6 additions & 1 deletion packages/compiler/src/transformBabel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import babel from '@babel/core'
import { resolvePath } from '@vxrn/utils'
import { relative } from 'node:path'
import { configuration } from './configure'
import { asyncGeneratorRegex, debug } from './constants'
import { asyncGeneratorRegex, debug, USE_OXC } from './constants'
import type { GetTransformProps, GetTransformResponse } from './types'

type Props = GetTransformProps & {
Expand Down Expand Up @@ -52,6 +52,11 @@ const getOptions = (props: Props, force = false): babel.TransformOptions | null
plugins.push('react-native-reanimated/plugin')
}

if (USE_OXC && /class [a-z]+ \{/i.test(props.code)) {
plugins.push(`@babel/plugin-transform-class-properties`)
plugins.push(`@babel/plugin-transform-classes`)
}

if (shouldBabelReactCompiler(props)) {
debug?.(`Using babel react compiler on file`)
plugins.push(getBabelReactCompilerPlugin(props))
Expand Down
184 changes: 96 additions & 88 deletions packages/compiler/src/transformSWC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import { extname, sep } from 'node:path'
import { merge } from 'ts-deepmerge'
import { configuration } from './configure'
import { asyncGeneratorRegex, debug, parsers, runtimePublicPath } from './constants'
import { asyncGeneratorRegex, debug, parsers, runtimePublicPath, USE_OXC } from './constants'
import type { Options } from './types'

const ignoreId = new RegExp(`node_modules\\${sep}(\\.vite|vite)\\${sep}`)
Expand Down Expand Up @@ -45,108 +45,116 @@ export async function transformSWC(
!options.forceJSX &&
!id.includes('node_modules')

const reactConfig = {
refresh,
development: !options.forceJSX && !options.production,
runtime: 'automatic',
importSource: 'react',
...(configuration.enableNativewind && !id.includes('node_modules')
? {
importSource: 'nativewind',
// pragma: 'createInteropElement',
// pragmaFrag: '_InteropFragment',
// swc doesnt actually change the import right
// runtime: 'classic',
}
: {}),
} satisfies TransformConfig['react']

const transformOptions = ((): SWCOptions => {
if (options.environment === 'client' || options.environment === 'ssr') {
return {
sourceMaps: shouldSourceMap(),
jsc: {
target: 'es2020',
parser,
transform: {
useDefineForClassFields: true,
react: reactConfig,
},
},
}
}

const shouldEs5Transform =
options.es5 || (!process.env.VXRN_USE_BABEL_FOR_GENERATORS && asyncGeneratorRegex.test(code))

const opts: SWCOptions = shouldEs5Transform
? {
let result: Output

if (USE_OXC) {
const oxc = await import('oxc-transform')
result = oxc.transform(id, code, {})
} else {
const reactConfig = {
refresh,
development: !options.forceJSX && !options.production,
runtime: 'automatic',
importSource: 'react',
...(configuration.enableNativewind && !id.includes('node_modules')
? {
importSource: 'nativewind',
// pragma: 'createInteropElement',
// pragmaFrag: '_InteropFragment',
// swc doesnt actually change the import right
// runtime: 'classic',
}
: {}),
} satisfies TransformConfig['react']

const transformOptions = ((): SWCOptions => {
if (options.environment === 'client' || options.environment === 'ssr') {
return {
sourceMaps: shouldSourceMap(),
jsc: {
target: 'es2020',
parser,
target: 'es5',
transform: {
useDefineForClassFields: true,
react: reactConfig,
},
},
}
: {
...(!options.forceJSX && { env: SWC_ENV }),
jsc: {
...(options.forceJSX && { target: 'esnext' }),
parser,
transform: {
useDefineForClassFields: true,
react: reactConfig,
}

const shouldEs5Transform =
options.es5 ||
(!process.env.VXRN_USE_BABEL_FOR_GENERATORS && asyncGeneratorRegex.test(code))

const opts: SWCOptions = shouldEs5Transform
? {
jsc: {
parser,
target: 'es5',
transform: {
useDefineForClassFields: true,
react: reactConfig,
},
},
},
}
}
: {
...(!options.forceJSX && { env: SWC_ENV }),
jsc: {
...(options.forceJSX && { target: 'esnext' }),
parser,
transform: {
useDefineForClassFields: true,
react: reactConfig,
},
},
}

return {
sourceMaps: shouldSourceMap(),
module: {
importInterop: 'none',
type: 'nodenext',
},
...(options.mode === 'serve-cjs' && {
return {
sourceMaps: shouldSourceMap(),
module: {
importInterop: 'none',
type: 'commonjs',
strict: true,
type: 'nodenext',
},
}),
...opts,
}
})()

const finalOptions = merge(
{
filename: id,
swcrc: false,
configFile: false,
...transformOptions,
},
swcOptions || {}
) satisfies SWCOptions

const result: Output = await (async () => {
try {
debug?.(`transformSWC ${id} using options:\n${JSON.stringify(finalOptions, null, 2)}`)

return await transform(code, finalOptions)
} catch (e: any) {
const message: string = e.message
const fileStartIndex = message.indexOf('╭─[')
if (fileStartIndex !== -1) {
const match = message.slice(fileStartIndex).match(/:(\d+):(\d+)]/)
if (match) {
e.line = match[1]
e.column = match[2]
...(options.mode === 'serve-cjs' && {
module: {
importInterop: 'none',
type: 'commonjs',
strict: true,
},
}),
...opts,
}
})()

const finalOptions = merge(
{
filename: id,
swcrc: false,
configFile: false,
...transformOptions,
},
swcOptions || {}
) satisfies SWCOptions

result = await (async () => {
try {
debug?.(`transformSWC ${id} using options:\n${JSON.stringify(finalOptions, null, 2)}`)

return await transform(code, finalOptions)
} catch (e: any) {
const message: string = e.message
const fileStartIndex = message.indexOf('╭─[')
if (fileStartIndex !== -1) {
const match = message.slice(fileStartIndex).match(/:(\d+):(\d+)]/)
if (match) {
e.line = match[1]
e.column = match[2]
}
}
throw e
}
throw e
}
})()
})()
}

if (configuration.enableNativeCSS) {
if (result.code.includes(`createInteropElement(`)) {
Expand Down
1 change: 1 addition & 0 deletions packages/compiler/types/constants.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export declare const runtimePublicPath = "/@react-refresh";
export declare const asyncGeneratorRegex: RegExp;
export declare const parsers: Record<string, ParserConfig>;
export declare const validParsers: Set<string>;
export declare const USE_OXC = false;
//# sourceMappingURL=constants.d.ts.map
Loading

0 comments on commit cefcef9

Please sign in to comment.