Skip to content

Commit

Permalink
perf: improve performance, disable not-needed slow plugins, and add O…
Browse files Browse the repository at this point in the history
…NE_DEBUG_BUILD_PERF env option to debug performance
  • Loading branch information
natew committed Dec 29, 2024
1 parent 7d9fc86 commit 2a6c1df
Show file tree
Hide file tree
Showing 8 changed files with 346 additions and 121 deletions.
2 changes: 1 addition & 1 deletion examples/one-tamagui/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default {
plugins: [
one({
react: {
compiler: true,
compiler: process.env.NODE_ENV === 'production',
},

web: {
Expand Down
2 changes: 1 addition & 1 deletion packages/one/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
"@react-navigation/native": "~7",
"@react-navigation/native-stack": "~7",
"@react-navigation/routers": "~7",
"@swc/core": "^1.7.14",
"@swc/core": "^1.10.3",
"@ungap/structured-clone": "^1.2.0",
"@vxrn/resolve": "workspace:*",
"@vxrn/tslib-lite": "workspace:*",
Expand Down
5 changes: 3 additions & 2 deletions packages/vite-native-swc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@
"@babel/plugin-transform-private-methods": "^7.25.9",
"@babel/plugin-transform-react-jsx": "^7.25.9",
"@babel/plugin-transform-regenerator": "^7.25.9",
"@swc/core": "^1.7.14",
"@swc/core": "^1.10.3",
"@vxrn/vite-native-client": "workspace:*",
"metro-react-native-babel-preset": "^0.77.0"
"metro-react-native-babel-preset": "^0.77.0",
"oxc-transform": "^0.44.0"
},
"devDependencies": {
"@biomejs/biome": "^1.8.3",
Expand Down
9 changes: 8 additions & 1 deletion packages/vite-native-swc/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export default (_options?: Options): PluginOption[] => {

return [
{
name: 'vite:react-swc',
name: 'vite:one-react-swc',
enforce: 'pre',

config: () => {
Expand Down Expand Up @@ -335,7 +335,14 @@ export const transformWithOptions = async (
...(options.forceJSX ? {} : { env: SWC_ENV }),
} satisfies SWCOptions

const start = performance.now()
result = await transform(code, transformOptions)

if (process.env.ONE_DEBUG_BUILD_PERF) {
if (performance.now() - start > 15) {
console.warn('slow swc compile on:', Math.round(performance.now() - start), id)
}
}
} catch (e: any) {
// try another config?
console.info(
Expand Down
81 changes: 41 additions & 40 deletions packages/vxrn/src/utils/getReactNativeBundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,55 +61,56 @@ export async function getReactNativeBundle(

nativeBuildConfig.plugins = filterPluginsForNative(nativeBuildConfig.plugins, { isNative: true })

// instrument plugins:
const buildStats: Record<string, number> = {}
if (process.env.ONE_DEBUG_BUILD_PERF) {
nativeBuildConfig.plugins = nativeBuildConfig.plugins.map((plugin) => {
return new Proxy(plugin, {
get(target, key) {
const value = Reflect.get(target, key)
// wrap with instrumentation
if (typeof value === 'function') {
return function (this, ...args) {
const name = `${plugin.name}:${key as any}`
const start = performance.now()
const logEnd = () => {
buildStats[name] ||= 0
buildStats[name] += performance.now() - start
}
const out = value.call(this, ...args)
if (out instanceof Promise) {
return out
.then((val) => {
logEnd()
return val
})
.catch((err) => {
logEnd()
throw err
})
}
logEnd()
return out
}
}
return value
},
})
})
}

const builder = await createBuilder(nativeBuildConfig)

const environment = builder.environments[platform]

const rollupCacheFile = join(options.cacheDir, `rn-rollup-cache-${platform}.json`)

// if (internal.useCache && !process.env.VXRN_DISABLE_CACHE) {
// // See: https://rollupjs.org/configuration-options/#cache
// environment.config.build.rollupOptions.cache =
// cache[platform] ||
// (await (async () => {
// // Try to load Rollup cache from disk
// try {
// if (await pathExists(rollupCacheFile)) {
// const c = await FSExtra.readJSON(rollupCacheFile, { reviver: bigIntReviver })
// return c
// }
// } catch (e) {
// console.error(`Error loading Rollup cache from ${rollupCacheFile}: ${e}`)
// }

// return null
// })()) ||
// true /* to initially enable Rollup cache */
// }

// We are using a forked version of the Vite internal function `buildEnvironment` (which is what `builder.build` calls) that will return the Rollup cache object with the build output, and also with some performance improvements.
// disabled due to differences in vite 6 stable upgrade

const buildOutput = await builder.build(environment)

// disable cache for new vite version
// const { cache: currentCache } = buildOutput
// if (currentCache) {
// // Do not cache some virtual modules that can dynamically change without an corresponding change in the source code to invalidate the cache.
// currentCache.modules = currentCache.modules.filter((m) => !m.id.endsWith('one-entry-native'))
// cache[platform] = currentCache

// // do not await cache write
// ;(async () => {
// if (!internal.useCache) return

// try {
// await FSExtra.writeJSON(rollupCacheFile, currentCache, { replacer: bigIntReplacer })
// } catch (e) {
// console.error(`Error saving Rollup cache to ${rollupCacheFile}: ${e}`)
// }
// })()
// }
if (process.env.ONE_DEBUG_BUILD_PERF) {
console.info(JSON.stringify(buildStats, null, 2))
}

if (!('output' in buildOutput)) {
throw `❌`
Expand Down
70 changes: 35 additions & 35 deletions packages/vxrn/src/utils/getReactNativeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,40 +58,40 @@ export async function getReactNativeConfig(
// vite doesnt support importing from a directory but its so common in react native
// so lets make it work, and node resolve theoretically fixes but you have to pass in moduleDirs
// but we need this to work anywhere including in normal source files
{
name: 'node-dir-imports',
enforce: 'pre',

async resolveId(importee, importer) {
if (!importer || !importee.startsWith('./')) {
return null
}
// let nodeResolve handle node_modules
if (importer?.includes('node_modules')) {
return
}
try {
const resolved = join(dirname(importer), importee)
if ((await stat(resolved)).isDirectory()) {
// fix for importing a directory
// TODO this would probably want to support their configured extensions
// TODO also platform-specific extensions
for (const ext of ['ts', 'tsx', 'mjs', 'js']) {
try {
const withExt = join(resolved, `index.${ext}`)
await stat(withExt)
// its a match
return withExt
} catch {
// keep going
}
}
}
} catch {
// not a dir keep going
}
},
} satisfies Plugin,
// {
// name: 'node-dir-imports',
// enforce: 'pre',

// async resolveId(importee, importer) {
// if (!importer || !importee.startsWith('./')) {
// return null
// }
// // let nodeResolve handle node_modules
// if (importer?.includes('node_modules')) {
// return
// }
// try {
// const resolved = join(dirname(importer), importee)
// if ((await stat(resolved)).isDirectory()) {
// // fix for importing a directory
// // TODO this would probably want to support their configured extensions
// // TODO also platform-specific extensions
// for (const ext of ['ts', 'tsx', 'mjs', 'js']) {
// try {
// const withExt = join(resolved, `index.${ext}`)
// await stat(withExt)
// // its a match
// return withExt
// } catch {
// // keep going
// }
// }
// }
// } catch {
// // not a dir keep going
// }
// },
// } satisfies Plugin,

{
name: 'native-special-case-resolver',
Expand Down Expand Up @@ -145,7 +145,7 @@ export async function getReactNativeConfig(

nodeResolve(),

swapPrebuiltReactModules(options.cacheDir, {
await swapPrebuiltReactModules(options.cacheDir, {
// TODO: a better way to pass the mode (dev/prod) to PrebuiltReactModules
mode: internal.mode || 'dev',
platform,
Expand Down
77 changes: 39 additions & 38 deletions packages/vxrn/src/utils/swapPrebuiltReactModules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,44 +196,45 @@ export async function swapPrebuiltReactModules(
// having trouble getting .native.js to be picked up via vite
// tried adding packages to optimizeDeps, tried resolveExtensions + extensions...
// tried this but seems to not be called for node_modules
if (id[0] === '.') {
const absolutePath = resolve(dirname(importer), id)
const nativePath = absolutePath.replace(/(.m?js)/, '.native.js')
if (nativePath === id) return
// Only comparing `nativePath === id` is not enough, because id can be a relative path while nativePath is an absolute path. We need to make sure things are not accidentally handled by this plugin so other plugins such as assets can work.
if (path.join(path.dirname(importer), id) === nativePath) {
return
}

// // if exists can skip
// if (await FSExtra.pathExists(absolutePath)) {
// return
// }

try {
const directoryPath = absolutePath + '/index.native.js'
const directoryNonNativePath = absolutePath + '/index.js'
if (await FSExtra.pathExists(directoryPath)) {
return directoryPath
}
if (await FSExtra.pathExists(directoryNonNativePath)) {
return directoryNonNativePath
}
try {
if (
(await FSExtra.stat(nativePath)).isFile() // Prevents "EISDIR: illegal operation on a directory, read" errors
) {
return nativePath
}
} catch (err: any) {
if (err.code !== 'ENOENT') {
throw err
}
}
} catch (err) {
console.warn(`error probably fine`, err)
}
}
// if (id[0] === '.') {
// const absolutePath = resolve(dirname(importer), id)
// const nativePath = absolutePath.replace(/(.m?js)/, '.native.js')
// if (nativePath === id) return
// // Only comparing `nativePath === id` is not enough, because id can be a relative path while nativePath is an absolute path. We need to make sure things are not accidentally handled by this plugin so other plugins such as assets can work.
// if (path.join(path.dirname(importer), id) === nativePath) {
// return
// }

// // // if exists can skip
// // if (await FSExtra.pathExists(absolutePath)) {
// // return
// // }

// try {
// const directoryPath = absolutePath + '/index.native.js'
// const directoryNonNativePath = absolutePath + '/index.js'
// if (await FSExtra.pathExists(directoryPath)) {
// return directoryPath
// }
// if (await FSExtra.pathExists(directoryNonNativePath)) {
// return directoryNonNativePath
// }
// try {
// console.log('stating', nativePath)
// if (
// (await FSExtra.stat(nativePath)).isFile() // Prevents "EISDIR: illegal operation on a directory, read" errors
// ) {
// return nativePath
// }
// } catch (err: any) {
// if (err.code !== 'ENOENT') {
// throw err
// }
// }
// } catch (err) {
// console.warn(`error probably fine`, err)
// }
// }
},

async load(id) {
Expand Down
Loading

0 comments on commit 2a6c1df

Please sign in to comment.