@vxrn/compiler 1.10.6 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/index.cjs +90 -94
- package/dist/cjs/index.js +94 -99
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/constants.mjs.map +1 -1
- package/dist/esm/index.js +93 -99
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +90 -94
- package/dist/esm/index.mjs.map +1 -1
- package/package.json +16 -9
- package/src/constants.ts +2 -3
- package/src/index.ts +147 -189
- package/types/constants.d.ts +1 -2
- package/types/constants.d.ts.map +1 -1
- package/types/index.d.ts +3 -2
- package/types/index.d.ts.map +1 -1
package/src/constants.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { ParserConfig } from '@swc/core'
|
|
2
|
-
|
|
3
1
|
import { createDebugger } from '@vxrn/utils'
|
|
4
2
|
|
|
5
3
|
export const { debug } = createDebugger('vxrn:compiler-plugin')
|
|
@@ -8,7 +6,8 @@ export const runtimePublicPath = '/@react-refresh'
|
|
|
8
6
|
|
|
9
7
|
export const asyncGeneratorRegex = /(async \*|async function\*|for await)/
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
// parser configs for swc (used by transformSWC consumers)
|
|
10
|
+
export const parsers: Record<string, any> = {
|
|
12
11
|
'.tsx': { syntax: 'typescript', tsx: true, decorators: true },
|
|
13
12
|
'.ts': { syntax: 'typescript', tsx: false, decorators: true },
|
|
14
13
|
'.jsx': {
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Compiler plugin for One/VXRN
|
|
3
|
+
* Automates babel transforms (react compiler, codegen, user transforms) and
|
|
4
|
+
* react native CSS-to-JS conversion.
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
7
|
import { readFileSync } from 'node:fs'
|
|
@@ -9,12 +10,11 @@ import { dirname, extname, join, relative, sep } from 'node:path'
|
|
|
9
10
|
import { fileURLToPath } from 'node:url'
|
|
10
11
|
import { resolvePath } from '@vxrn/utils'
|
|
11
12
|
import { cssToReactNativeRuntime } from 'react-native-css-interop/css-to-rn/index.js'
|
|
12
|
-
import type { OutputChunk } from '
|
|
13
|
+
import type { OutputChunk } from 'rolldown'
|
|
13
14
|
import type { PluginOption, ResolvedConfig, UserConfig } from 'vite'
|
|
14
15
|
import { configuration } from './configure'
|
|
15
16
|
import { debug, runtimePublicPath, validParsers } from './constants'
|
|
16
17
|
import { getBabelOptions, transformBabel } from './transformBabel'
|
|
17
|
-
import { transformSWC } from './transformSWC'
|
|
18
18
|
import type { Environment, GetTransformProps, Options } from './types'
|
|
19
19
|
import { getCachedTransform, logCacheStats, setCachedTransform } from './cache'
|
|
20
20
|
|
|
@@ -107,9 +107,7 @@ async function performBabelTransform({
|
|
|
107
107
|
return null
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (!isPreProcess && userTransform !== 'swc') {
|
|
110
|
+
if (userTransform !== 'swc') {
|
|
113
111
|
const babelOptions = getBabelOptions({
|
|
114
112
|
...transformProps,
|
|
115
113
|
userSetting: userTransform,
|
|
@@ -170,108 +168,6 @@ async function performBabelTransform({
|
|
|
170
168
|
return null
|
|
171
169
|
}
|
|
172
170
|
|
|
173
|
-
// Full transform (Babel + SWC) for Vite transform hook
|
|
174
|
-
async function performFullTransform({
|
|
175
|
-
codeIn,
|
|
176
|
-
_id,
|
|
177
|
-
environment,
|
|
178
|
-
production,
|
|
179
|
-
reactForRNVersion,
|
|
180
|
-
optionsIn,
|
|
181
|
-
mode,
|
|
182
|
-
}: {
|
|
183
|
-
codeIn: string
|
|
184
|
-
_id: string
|
|
185
|
-
environment: Environment
|
|
186
|
-
production: boolean
|
|
187
|
-
reactForRNVersion: '18' | '19'
|
|
188
|
-
optionsIn?: Partial<Options>
|
|
189
|
-
mode: 'serve' | 'build'
|
|
190
|
-
}) {
|
|
191
|
-
const shouldDebug =
|
|
192
|
-
process.env.NODE_ENV === 'development' && codeIn.startsWith('// debug')
|
|
193
|
-
|
|
194
|
-
if (shouldDebug) {
|
|
195
|
-
console.info(`[one] ${_id} input:`)
|
|
196
|
-
console.info(codeIn)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
let id = _id.split('?')[0]
|
|
200
|
-
|
|
201
|
-
const extension = extname(id)
|
|
202
|
-
|
|
203
|
-
if (extension === '.css') {
|
|
204
|
-
return
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (!validParsers.has(extension)) {
|
|
208
|
-
return
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const isPreProcess = id.startsWith(`vxrn-swc-preprocess:`)
|
|
212
|
-
if (isPreProcess) {
|
|
213
|
-
id = id.replace(`vxrn-swc-preprocess:`, '')
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (id.includes(`virtual:`)) {
|
|
217
|
-
return
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
let code = codeIn
|
|
221
|
-
let out: {
|
|
222
|
-
code: string
|
|
223
|
-
map?: any
|
|
224
|
-
} | null = null
|
|
225
|
-
|
|
226
|
-
// avoid double-processing files already handled by optimizeDeps
|
|
227
|
-
if (codeIn.endsWith(`// vxrn-did-babel`)) {
|
|
228
|
-
debug?.(`[skip babel] ${id}`)
|
|
229
|
-
} else {
|
|
230
|
-
const babelResult = await performBabelTransform({
|
|
231
|
-
id,
|
|
232
|
-
code,
|
|
233
|
-
environment,
|
|
234
|
-
production,
|
|
235
|
-
reactForRNVersion,
|
|
236
|
-
optionsIn,
|
|
237
|
-
})
|
|
238
|
-
|
|
239
|
-
if (babelResult) {
|
|
240
|
-
out = babelResult
|
|
241
|
-
code = babelResult.code
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Always run SWC for class transforms + react refresh
|
|
246
|
-
const swcOptions = {
|
|
247
|
-
environment,
|
|
248
|
-
mode: optionsIn?.mode || mode,
|
|
249
|
-
production,
|
|
250
|
-
...optionsIn,
|
|
251
|
-
} satisfies Options
|
|
252
|
-
|
|
253
|
-
const swcOut = await transformSWC(id, code, {
|
|
254
|
-
es5: true,
|
|
255
|
-
noHMR: isPreProcess || environment === 'ssr',
|
|
256
|
-
...swcOptions,
|
|
257
|
-
})
|
|
258
|
-
|
|
259
|
-
if (swcOut) {
|
|
260
|
-
debug?.(`[swc] ${id}`)
|
|
261
|
-
out = {
|
|
262
|
-
code: swcOut.code,
|
|
263
|
-
map: swcOut.map,
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (shouldDebug) {
|
|
268
|
-
console.info(`swcOptions`, swcOptions)
|
|
269
|
-
console.info(`final output:`, out?.code)
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
return out
|
|
273
|
-
}
|
|
274
|
-
|
|
275
171
|
export async function createVXRNCompilerPlugin(
|
|
276
172
|
optionsIn?: Partial<Options>
|
|
277
173
|
): Promise<PluginOption[]> {
|
|
@@ -297,9 +193,12 @@ export async function createVXRNCompilerPlugin(
|
|
|
297
193
|
|
|
298
194
|
const cssTransformCache = new Map<string, string>()
|
|
299
195
|
|
|
300
|
-
// fix so we can align the diff between vite and
|
|
301
|
-
const
|
|
302
|
-
const
|
|
196
|
+
// fix so we can align the diff between vite and rolldown id (rolldown resolves from root monorepo)
|
|
197
|
+
const rolldownPath = resolvePath('rolldown')
|
|
198
|
+
const rolldownNodeMods = rolldownPath.slice(
|
|
199
|
+
0,
|
|
200
|
+
rolldownPath.indexOf(sep + 'node_modules')
|
|
201
|
+
)
|
|
303
202
|
|
|
304
203
|
/**
|
|
305
204
|
* Vite config, filled by a `configResolved` hook.
|
|
@@ -349,7 +248,7 @@ export async function createVXRNCompilerPlugin(
|
|
|
349
248
|
const newId = `${id}.js`
|
|
350
249
|
|
|
351
250
|
// rollup uses relative to its node_modules parent dir, vite here uses absolute
|
|
352
|
-
const cssId = newId.replace(
|
|
251
|
+
const cssId = newId.replace(rolldownNodeMods + sep, '')
|
|
353
252
|
cssTransformCache.set(cssId, code)
|
|
354
253
|
|
|
355
254
|
return {
|
|
@@ -402,87 +301,76 @@ ${rootJS.code}
|
|
|
402
301
|
enforce: 'pre',
|
|
403
302
|
|
|
404
303
|
config: () => {
|
|
304
|
+
const nodeModulesFilter = /node_modules\/.*\.(tsx?|jsx?|mjs|cjs)$/
|
|
305
|
+
|
|
405
306
|
const createEnvironmentConfig = (environment: Environment) => {
|
|
307
|
+
// init stats for this environment
|
|
308
|
+
if (!perfStats.optimizeDeps.byEnvironment[environment]) {
|
|
309
|
+
perfStats.optimizeDeps.byEnvironment[environment] = {
|
|
310
|
+
filesChecked: 0,
|
|
311
|
+
filesTransformed: 0,
|
|
312
|
+
startTime: Date.now(),
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
406
316
|
return {
|
|
407
317
|
optimizeDeps: {
|
|
408
|
-
|
|
318
|
+
rolldownOptions: {
|
|
409
319
|
plugins: [
|
|
410
320
|
{
|
|
411
321
|
name: `transform-before-optimize-deps-${environment}`,
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
if (!
|
|
415
|
-
|
|
416
|
-
filesChecked: 0,
|
|
417
|
-
filesTransformed: 0,
|
|
418
|
-
startTime: Date.now(),
|
|
419
|
-
}
|
|
322
|
+
|
|
323
|
+
async transform(code: string, id: string) {
|
|
324
|
+
if (!nodeModulesFilter.test(id)) {
|
|
325
|
+
return null
|
|
420
326
|
}
|
|
421
327
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
environment,
|
|
438
|
-
production,
|
|
439
|
-
reactForRNVersion,
|
|
440
|
-
optionsIn,
|
|
441
|
-
})
|
|
442
|
-
|
|
443
|
-
if (!result) {
|
|
444
|
-
return null
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
perfStats.optimizeDeps.byEnvironment[environment]
|
|
448
|
-
.filesTransformed++
|
|
449
|
-
|
|
450
|
-
// Determine loader based on file extension
|
|
451
|
-
const ext = extname(args.path)
|
|
452
|
-
const loader =
|
|
453
|
-
ext === '.tsx'
|
|
454
|
-
? 'tsx'
|
|
455
|
-
: ext === '.ts'
|
|
456
|
-
? 'ts'
|
|
457
|
-
: ext === '.jsx'
|
|
458
|
-
? 'jsx'
|
|
459
|
-
: 'js'
|
|
460
|
-
|
|
461
|
-
return {
|
|
462
|
-
contents: result.code,
|
|
463
|
-
loader,
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
)
|
|
467
|
-
|
|
468
|
-
build.onEnd(() => {
|
|
469
|
-
// Only log detailed stats when debugging
|
|
470
|
-
if (process.env.DEBUG_COMPILER_PERF) {
|
|
471
|
-
const stats = perfStats.optimizeDeps.byEnvironment[environment]
|
|
472
|
-
const elapsed = Date.now() - stats.startTime
|
|
473
|
-
console.info(
|
|
474
|
-
`[optimizeDeps ${environment}] Done: ${stats.filesChecked} files checked, ${stats.filesTransformed} transformed (${elapsed}ms)`
|
|
475
|
-
)
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
// Log cache stats when all environments are done
|
|
479
|
-
const allDone =
|
|
480
|
-
Object.keys(perfStats.optimizeDeps.byEnvironment).length >= 2
|
|
481
|
-
if (allDone) {
|
|
482
|
-
logCacheStats()
|
|
483
|
-
logPerfSummary()
|
|
484
|
-
}
|
|
328
|
+
perfStats.optimizeDeps.byEnvironment[environment].filesChecked++
|
|
329
|
+
|
|
330
|
+
const production =
|
|
331
|
+
process.env.NODE_ENV === 'production' ||
|
|
332
|
+
process.env.NODE_ENV === 'test'
|
|
333
|
+
|
|
334
|
+
debug?.(`[rolldown optimizeDeps] ${id}`)
|
|
335
|
+
|
|
336
|
+
const result = await performBabelTransform({
|
|
337
|
+
id,
|
|
338
|
+
code,
|
|
339
|
+
environment,
|
|
340
|
+
production,
|
|
341
|
+
reactForRNVersion,
|
|
342
|
+
optionsIn,
|
|
485
343
|
})
|
|
344
|
+
|
|
345
|
+
if (!result) {
|
|
346
|
+
return null
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
perfStats.optimizeDeps.byEnvironment[environment].filesTransformed++
|
|
350
|
+
|
|
351
|
+
return {
|
|
352
|
+
code: result.code,
|
|
353
|
+
map: result.map,
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
|
|
357
|
+
buildEnd() {
|
|
358
|
+
// only log detailed stats when debugging
|
|
359
|
+
if (process.env.DEBUG_COMPILER_PERF) {
|
|
360
|
+
const stats = perfStats.optimizeDeps.byEnvironment[environment]
|
|
361
|
+
const elapsed = Date.now() - stats.startTime
|
|
362
|
+
console.info(
|
|
363
|
+
`[optimizeDeps ${environment}] Done: ${stats.filesChecked} files checked, ${stats.filesTransformed} transformed (${elapsed}ms)`
|
|
364
|
+
)
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// log cache stats when all environments are done
|
|
368
|
+
const allDone =
|
|
369
|
+
Object.keys(perfStats.optimizeDeps.byEnvironment).length >= 2
|
|
370
|
+
if (allDone) {
|
|
371
|
+
logCacheStats()
|
|
372
|
+
logPerfSummary()
|
|
373
|
+
}
|
|
486
374
|
},
|
|
487
375
|
},
|
|
488
376
|
],
|
|
@@ -539,16 +427,86 @@ ${rootJS.code}
|
|
|
539
427
|
return code
|
|
540
428
|
}
|
|
541
429
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
430
|
+
// filter out non-transformable files
|
|
431
|
+
const id = _id.split('?')[0]
|
|
432
|
+
const extension = extname(id)
|
|
433
|
+
|
|
434
|
+
if (extension === '.css' || !validParsers.has(extension)) {
|
|
435
|
+
return
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (id.includes(`virtual:`)) {
|
|
439
|
+
return
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// avoid double-processing files already handled by optimizeDeps
|
|
443
|
+
if (codeIn.endsWith(`// vxrn-did-babel`)) {
|
|
444
|
+
debug?.(`[skip babel] ${id}`)
|
|
445
|
+
return
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return performBabelTransform({
|
|
449
|
+
id,
|
|
450
|
+
code: codeIn,
|
|
545
451
|
environment,
|
|
546
452
|
production,
|
|
547
453
|
reactForRNVersion,
|
|
548
454
|
optionsIn,
|
|
549
|
-
mode: config.command,
|
|
550
455
|
})
|
|
551
456
|
},
|
|
552
457
|
},
|
|
458
|
+
|
|
459
|
+
// wraps client-side TSX/JSX with React Refresh preamble + import.meta.hot.accept
|
|
460
|
+
// runs after vite:oxc (no enforce:'pre') so it sees the already-transformed code
|
|
461
|
+
{
|
|
462
|
+
name: 'one:react-refresh-web',
|
|
463
|
+
apply: 'serve',
|
|
464
|
+
|
|
465
|
+
transform(code, _id) {
|
|
466
|
+
if (this.environment.name !== 'client') return
|
|
467
|
+
if (code.includes(runtimePublicPath)) return // already wrapped
|
|
468
|
+
|
|
469
|
+
const id = _id.split('?')[0]
|
|
470
|
+
if (id.includes('node_modules')) return
|
|
471
|
+
if (id.includes('virtual:')) return
|
|
472
|
+
if (id === runtimePublicPath) return
|
|
473
|
+
|
|
474
|
+
const ext = extname(id)
|
|
475
|
+
if (ext !== '.tsx' && ext !== '.jsx') return
|
|
476
|
+
|
|
477
|
+
const hasRefreshCalls = /\$RefreshReg\$\(/.test(code)
|
|
478
|
+
|
|
479
|
+
let out = `import * as RefreshRuntime from "${runtimePublicPath}";\n\n`
|
|
480
|
+
|
|
481
|
+
if (hasRefreshCalls) {
|
|
482
|
+
out += `if (!window.$RefreshReg$) throw new Error("React refresh preamble was not loaded. Something is wrong.");
|
|
483
|
+
const prevRefreshReg = window.$RefreshReg$;
|
|
484
|
+
const prevRefreshSig = window.$RefreshSig$;
|
|
485
|
+
window.$RefreshReg$ = RefreshRuntime.getRefreshReg("${id}");
|
|
486
|
+
window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
|
|
487
|
+
|
|
488
|
+
`
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
out += code
|
|
492
|
+
|
|
493
|
+
if (hasRefreshCalls) {
|
|
494
|
+
out += `\n\nwindow.$RefreshReg$ = prevRefreshReg;\nwindow.$RefreshSig$ = prevRefreshSig;\n`
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
out += `
|
|
498
|
+
RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {
|
|
499
|
+
RefreshRuntime.registerExportsForReactRefresh("${id}", currentExports);
|
|
500
|
+
import.meta.hot.accept((nextExports) => {
|
|
501
|
+
if (!nextExports) return;
|
|
502
|
+
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate("${id}", currentExports, nextExports);
|
|
503
|
+
if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);
|
|
504
|
+
});
|
|
505
|
+
});
|
|
506
|
+
`
|
|
507
|
+
|
|
508
|
+
return { code: out, map: null }
|
|
509
|
+
},
|
|
510
|
+
},
|
|
553
511
|
]
|
|
554
512
|
}
|
package/types/constants.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type { ParserConfig } from '@swc/core';
|
|
2
1
|
export declare const debug: (((...args: any[]) => any) & {
|
|
3
2
|
namespace: string;
|
|
4
3
|
}) | undefined;
|
|
5
4
|
export declare const runtimePublicPath = "/@react-refresh";
|
|
6
5
|
export declare const asyncGeneratorRegex: RegExp;
|
|
7
|
-
export declare const parsers: Record<string,
|
|
6
|
+
export declare const parsers: Record<string, any>;
|
|
8
7
|
export declare const validParsers: Set<string>;
|
|
9
8
|
//# sourceMappingURL=constants.d.ts.map
|
package/types/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAQ,KAAK;;cAA2C,CAAA;AAE/D,eAAO,MAAM,iBAAiB,oBAAoB,CAAA;AAElD,eAAO,MAAM,mBAAmB,QAA0C,CAAA;AAG1E,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CA8BvC,CAAA;AAED,eAAO,MAAM,YAAY,aAA6C,CAAA"}
|
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Compiler plugin for One/VXRN
|
|
3
|
+
* Automates babel transforms (react compiler, codegen, user transforms) and
|
|
4
|
+
* react native CSS-to-JS conversion.
|
|
4
5
|
*/
|
|
5
6
|
import type { PluginOption } from 'vite';
|
|
6
7
|
import type { Options } from './types';
|
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,YAAY,EAA8B,MAAM,MAAM,CAAA;AAIpE,OAAO,KAAK,EAAkC,OAAO,EAAE,MAAM,SAAS,CAAA;AAGtE,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAmJ3C,wBAAsB,wBAAwB,CAC5C,SAAS,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,GAC3B,OAAO,CAAC,YAAY,EAAE,CAAC,CAmVzB"}
|