rari 0.2.1 → 0.2.3
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/client-dev.d.ts +2 -0
- package/dist/client-dev.js +3 -0
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/{runtime-client-CC4YQweh.js → runtime-client-CcEhh-F7.js} +48 -18
- package/dist/{runtime-client-BEWMJWMx.d.ts → runtime-client-P4vvSVPV.d.ts} +1 -0
- package/dist/{server-DeSCwqZZ.js → server-BwDou3Zb.js} +256 -33
- package/dist/{server-MY0-nRif.d.ts → server-Ph4oyo0B.d.ts} +47 -2
- package/dist/server.d.ts +3 -3
- package/dist/server.js +3 -3
- package/package.json +12 -7
- package/src/client-dev.ts +59 -0
- package/src/client.ts +3 -10
- package/src/router/index.ts +12 -6
- package/src/router/router.tsx +101 -45
- package/src/router/types.ts +2 -1
- package/src/server.ts +5 -14
- package/src/vite/index.ts +475 -48
package/src/vite/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import fs from 'node:fs'
|
|
|
6
6
|
import path from 'node:path'
|
|
7
7
|
import process from 'node:process'
|
|
8
8
|
import * as acorn from 'acorn'
|
|
9
|
+
import { minify } from 'rollup-plugin-esbuild'
|
|
9
10
|
import { createServerBuildPlugin } from './server-build'
|
|
10
11
|
|
|
11
12
|
interface RariOptions {
|
|
@@ -151,7 +152,10 @@ export function rari(options: RariOptions = {}): Plugin[] {
|
|
|
151
152
|
}
|
|
152
153
|
}
|
|
153
154
|
|
|
154
|
-
function hasTopLevelDirective(
|
|
155
|
+
function hasTopLevelDirective(
|
|
156
|
+
code: string,
|
|
157
|
+
directive: 'use client' | 'use server',
|
|
158
|
+
): boolean {
|
|
155
159
|
try {
|
|
156
160
|
const ast = acorn.parse(code, {
|
|
157
161
|
ecmaVersion: 2024,
|
|
@@ -224,7 +228,6 @@ export function rari(options: RariOptions = {}): Plugin[] {
|
|
|
224
228
|
|
|
225
229
|
newCode += `
|
|
226
230
|
|
|
227
|
-
// HMR acceptance for server components
|
|
228
231
|
if (import.meta.hot) {
|
|
229
232
|
import.meta.hot.accept(() => {
|
|
230
233
|
// Server component updated, no need to reload
|
|
@@ -370,30 +373,50 @@ if (import.meta.hot) {
|
|
|
370
373
|
config(config: UserConfig, { command }) {
|
|
371
374
|
config.resolve = config.resolve || {}
|
|
372
375
|
const existingDedupe = Array.isArray((config.resolve as any).dedupe)
|
|
373
|
-
? (config.resolve as any).dedupe as string[]
|
|
376
|
+
? ((config.resolve as any).dedupe as string[])
|
|
374
377
|
: []
|
|
375
|
-
const toAdd = ['react', 'react-dom']
|
|
376
|
-
|
|
378
|
+
const toAdd = ['react', 'react-dom'];
|
|
379
|
+
(config.resolve as any).dedupe = Array.from(
|
|
377
380
|
new Set([...(existingDedupe || []), ...toAdd]),
|
|
378
381
|
)
|
|
379
382
|
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
383
|
+
const existingResolveAlias = (config.resolve as any).alias || {};
|
|
384
|
+
(config.resolve as any).alias = {
|
|
385
|
+
...existingResolveAlias,
|
|
386
|
+
'react-dom/server': 'react-dom/server.browser',
|
|
387
|
+
'react-dom$': 'react-dom/client',
|
|
388
|
+
'react-dom/cjs/react-dom.production.min.js': 'react-dom/client',
|
|
389
|
+
'react-dom/cjs/react-dom.development.js': 'react-dom/client',
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const existingAlias: Array<{
|
|
393
|
+
find: string | RegExp
|
|
394
|
+
replacement: string
|
|
395
|
+
}> = Array.isArray((config.resolve as any).alias)
|
|
396
|
+
? (config.resolve as any).alias
|
|
397
|
+
: []
|
|
384
398
|
const aliasFinds = new Set(existingAlias.map(a => String(a.find)))
|
|
385
399
|
try {
|
|
386
400
|
const reactPath = require.resolve('react')
|
|
387
401
|
const reactDomClientPath = require.resolve('react-dom/client')
|
|
388
402
|
const reactJsxRuntimePath = require.resolve('react/jsx-runtime')
|
|
389
|
-
const aliasesToAppend: Array<{ find: string, replacement: string }>
|
|
403
|
+
const aliasesToAppend: Array<{ find: string, replacement: string }>
|
|
404
|
+
= []
|
|
390
405
|
if (!aliasFinds.has('react/jsx-runtime')) {
|
|
391
|
-
aliasesToAppend.push({
|
|
406
|
+
aliasesToAppend.push({
|
|
407
|
+
find: 'react/jsx-runtime',
|
|
408
|
+
replacement: reactJsxRuntimePath,
|
|
409
|
+
})
|
|
392
410
|
}
|
|
393
411
|
try {
|
|
394
|
-
const reactJsxDevRuntimePath = require.resolve(
|
|
412
|
+
const reactJsxDevRuntimePath = require.resolve(
|
|
413
|
+
'react/jsx-dev-runtime',
|
|
414
|
+
)
|
|
395
415
|
if (!aliasFinds.has('react/jsx-dev-runtime')) {
|
|
396
|
-
aliasesToAppend.push({
|
|
416
|
+
aliasesToAppend.push({
|
|
417
|
+
find: 'react/jsx-dev-runtime',
|
|
418
|
+
replacement: reactJsxDevRuntimePath,
|
|
419
|
+
})
|
|
397
420
|
}
|
|
398
421
|
}
|
|
399
422
|
catch { }
|
|
@@ -401,10 +424,16 @@ if (import.meta.hot) {
|
|
|
401
424
|
aliasesToAppend.push({ find: 'react', replacement: reactPath })
|
|
402
425
|
}
|
|
403
426
|
if (!aliasFinds.has('react-dom/client')) {
|
|
404
|
-
aliasesToAppend.push({
|
|
427
|
+
aliasesToAppend.push({
|
|
428
|
+
find: 'react-dom/client',
|
|
429
|
+
replacement: reactDomClientPath,
|
|
430
|
+
})
|
|
405
431
|
}
|
|
406
432
|
if (aliasesToAppend.length > 0) {
|
|
407
|
-
(config.resolve as any).alias = [
|
|
433
|
+
(config.resolve as any).alias = [
|
|
434
|
+
...existingAlias,
|
|
435
|
+
...aliasesToAppend,
|
|
436
|
+
]
|
|
408
437
|
}
|
|
409
438
|
}
|
|
410
439
|
catch { }
|
|
@@ -437,12 +466,22 @@ if (import.meta.hot) {
|
|
|
437
466
|
if (!config.optimizeDeps.include.includes('react-dom/server')) {
|
|
438
467
|
config.optimizeDeps.include.push('react-dom/server')
|
|
439
468
|
}
|
|
469
|
+
if (!config.optimizeDeps.include.includes('react')) {
|
|
470
|
+
config.optimizeDeps.include.push('react')
|
|
471
|
+
}
|
|
472
|
+
if (!config.optimizeDeps.include.includes('react-dom/client')) {
|
|
473
|
+
config.optimizeDeps.include.push('react-dom/client')
|
|
474
|
+
}
|
|
475
|
+
config.optimizeDeps.exclude = config.optimizeDeps.exclude || []
|
|
476
|
+
if (!config.optimizeDeps.exclude.includes('virtual:rsc-integration')) {
|
|
477
|
+
config.optimizeDeps.exclude.push('virtual:rsc-integration')
|
|
478
|
+
}
|
|
440
479
|
|
|
441
480
|
if (command === 'build') {
|
|
442
481
|
for (const envName of ['rsc', 'ssr', 'client']) {
|
|
443
482
|
const env = config.environments[envName]
|
|
444
483
|
if (env && env.build) {
|
|
445
|
-
env.build.
|
|
484
|
+
env.build.rolldownOptions = env.build.rolldownOptions || {}
|
|
446
485
|
}
|
|
447
486
|
}
|
|
448
487
|
}
|
|
@@ -478,38 +517,329 @@ if (import.meta.hot) {
|
|
|
478
517
|
|
|
479
518
|
if (command === 'build') {
|
|
480
519
|
config.build = config.build || {}
|
|
481
|
-
config.build.
|
|
520
|
+
config.build.rolldownOptions = config.build.rolldownOptions || {}
|
|
521
|
+
|
|
522
|
+
config.build.rolldownOptions.plugins
|
|
523
|
+
= config.build.rolldownOptions.plugins || []
|
|
524
|
+
if (Array.isArray(config.build.rolldownOptions.plugins)) {
|
|
525
|
+
config.build.rolldownOptions.plugins.push(minify())
|
|
526
|
+
|
|
527
|
+
config.build.rolldownOptions.plugins.push({
|
|
528
|
+
name: 'html-css-optimizer',
|
|
529
|
+
generateBundle(options, bundle) {
|
|
530
|
+
Object.keys(bundle).forEach((fileName) => {
|
|
531
|
+
const file = bundle[fileName]
|
|
532
|
+
if (file.type === 'asset' && fileName.endsWith('.html')) {
|
|
533
|
+
let html = file.source as string
|
|
534
|
+
|
|
535
|
+
html = html.replace(
|
|
536
|
+
/<link\s+rel="stylesheet"\s+crossorigin\s+href="([^"]+\.css)"\s*>/g,
|
|
537
|
+
(match, href) => {
|
|
538
|
+
return `<link rel="preload" as="style" crossorigin href="${href}" fetchpriority="high" onload="this.onload=null;this.rel='stylesheet'">
|
|
539
|
+
<noscript><link rel="stylesheet" crossorigin href="${href}"></noscript>`
|
|
540
|
+
},
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
const scriptMatch = html.match(
|
|
544
|
+
/<script\s+type="module"\s+crossorigin\s+src="([^"]+)"\s*><\/script>/,
|
|
545
|
+
)
|
|
546
|
+
if (scriptMatch) {
|
|
547
|
+
const mainJsHref = scriptMatch[1]
|
|
548
|
+
html = html.replace(
|
|
549
|
+
scriptMatch[0],
|
|
550
|
+
`<link rel="preload" as="script" crossorigin href="${mainJsHref}" fetchpriority="high">
|
|
551
|
+
<script type="module" crossorigin src="${mainJsHref}" fetchpriority="high"></script>`,
|
|
552
|
+
)
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
file.source = html
|
|
556
|
+
}
|
|
557
|
+
})
|
|
558
|
+
},
|
|
559
|
+
})
|
|
560
|
+
}
|
|
482
561
|
|
|
483
|
-
if (!config.build.
|
|
484
|
-
config.build.
|
|
562
|
+
if (!config.build.rolldownOptions.input) {
|
|
563
|
+
config.build.rolldownOptions.input = {
|
|
485
564
|
main: './index.html',
|
|
486
565
|
}
|
|
487
566
|
}
|
|
567
|
+
|
|
568
|
+
config.build.rolldownOptions.output
|
|
569
|
+
= config.build.rolldownOptions.output || {}
|
|
570
|
+
const outputConfig = Array.isArray(config.build.rolldownOptions.output)
|
|
571
|
+
? config.build.rolldownOptions.output[0] || {}
|
|
572
|
+
: config.build.rolldownOptions.output
|
|
573
|
+
|
|
574
|
+
outputConfig.manualChunks = (id) => {
|
|
575
|
+
if (
|
|
576
|
+
id.includes('node_modules/react-dom')
|
|
577
|
+
|| id.includes('react-dom/client')
|
|
578
|
+
|| id.includes('react-dom/server')
|
|
579
|
+
|| id.includes('react-dom/')
|
|
580
|
+
) {
|
|
581
|
+
return 'react-dom'
|
|
582
|
+
}
|
|
583
|
+
if (
|
|
584
|
+
(id.includes('node_modules/react') || id.includes('react/'))
|
|
585
|
+
&& !id.includes('react-dom')
|
|
586
|
+
) {
|
|
587
|
+
return 'react'
|
|
588
|
+
}
|
|
589
|
+
if (id.includes('scheduler') && id.includes('node_modules')) {
|
|
590
|
+
return 'scheduler'
|
|
591
|
+
}
|
|
592
|
+
if (id.includes('markdown-it') || id.includes('shiki')) {
|
|
593
|
+
return 'vendor'
|
|
594
|
+
}
|
|
595
|
+
if (id.includes('node_modules')) {
|
|
596
|
+
return 'vendor'
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
config.build.rolldownOptions.treeshake = config.build.rolldownOptions
|
|
601
|
+
.treeshake || {
|
|
602
|
+
moduleSideEffects: (id) => {
|
|
603
|
+
if (id.includes('.css') || id.includes('polyfill')) {
|
|
604
|
+
return true
|
|
605
|
+
}
|
|
606
|
+
if (
|
|
607
|
+
id.includes('react-dom')
|
|
608
|
+
|| id.includes('react')
|
|
609
|
+
|| id.includes('scheduler')
|
|
610
|
+
|| id.includes('react-dom/client')
|
|
611
|
+
|| id.includes('react-dom/server')
|
|
612
|
+
) {
|
|
613
|
+
return false
|
|
614
|
+
}
|
|
615
|
+
return false
|
|
616
|
+
},
|
|
617
|
+
unknownGlobalSideEffects: false,
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const existingExternal = config.build.rolldownOptions?.external || []
|
|
621
|
+
const reactDomExternals = [
|
|
622
|
+
'react-dom/profiling',
|
|
623
|
+
'react-dom/test-utils',
|
|
624
|
+
'react-dom/server',
|
|
625
|
+
'react-dom/server.browser',
|
|
626
|
+
'react-dom/server.node',
|
|
627
|
+
'react/jsx-dev-runtime',
|
|
628
|
+
'scheduler/tracing',
|
|
629
|
+
'scheduler/unstable_mock',
|
|
630
|
+
'react/cjs/react.development.js',
|
|
631
|
+
'react/cjs/react.production.min.js',
|
|
632
|
+
'react-dom/cjs/react-dom.development.js',
|
|
633
|
+
'react-dom/cjs/react-dom.production.min.js',
|
|
634
|
+
'react-dom/src/client/ReactDOMRoot.js',
|
|
635
|
+
'react-dom/src/events/plugins',
|
|
636
|
+
'react-dom/src/shared/HTMLDOMPropertyConfig.js',
|
|
637
|
+
'react-dom/src/shared/DOMPropertyOperations.js',
|
|
638
|
+
]
|
|
639
|
+
|
|
640
|
+
if (Array.isArray(existingExternal)) {
|
|
641
|
+
const external = [...existingExternal]
|
|
642
|
+
external.push(
|
|
643
|
+
...reactDomExternals.filter(dep => !external.includes(dep)),
|
|
644
|
+
)
|
|
645
|
+
config.build.rolldownOptions.external = external
|
|
646
|
+
}
|
|
647
|
+
else if (typeof existingExternal === 'function') {
|
|
648
|
+
const originalExternal = existingExternal
|
|
649
|
+
config.build.rolldownOptions.external = (
|
|
650
|
+
id,
|
|
651
|
+
parentId,
|
|
652
|
+
isResolved,
|
|
653
|
+
) => {
|
|
654
|
+
if (reactDomExternals.includes(id))
|
|
655
|
+
return true
|
|
656
|
+
return originalExternal(id, parentId, isResolved)
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
else {
|
|
660
|
+
config.build.rolldownOptions.external = [
|
|
661
|
+
...(Array.isArray(existingExternal)
|
|
662
|
+
? existingExternal
|
|
663
|
+
: [existingExternal]),
|
|
664
|
+
...reactDomExternals,
|
|
665
|
+
].filter(Boolean)
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
config.build.minify = true
|
|
669
|
+
config.build.target = config.build.target || [
|
|
670
|
+
'es2020',
|
|
671
|
+
'edge88',
|
|
672
|
+
'firefox78',
|
|
673
|
+
'chrome87',
|
|
674
|
+
'safari14',
|
|
675
|
+
]
|
|
676
|
+
config.build.cssMinify
|
|
677
|
+
= config.build.cssMinify !== false ? 'esbuild' : false
|
|
678
|
+
config.build.cssCodeSplit = true
|
|
679
|
+
config.build.assetsInlineLimit = 4096
|
|
680
|
+
config.build.chunkSizeWarningLimit = 1000
|
|
681
|
+
config.build.sourcemap
|
|
682
|
+
= config.build.sourcemap !== undefined ? config.build.sourcemap : true
|
|
683
|
+
|
|
684
|
+
config.build.terserOptions = config.build.terserOptions || {
|
|
685
|
+
compress: {
|
|
686
|
+
drop_console: true,
|
|
687
|
+
drop_debugger: true,
|
|
688
|
+
pure_funcs: [
|
|
689
|
+
'console.log',
|
|
690
|
+
'console.info',
|
|
691
|
+
'console.debug',
|
|
692
|
+
'console.warn',
|
|
693
|
+
'invariant',
|
|
694
|
+
'warning',
|
|
695
|
+
'__DEV__',
|
|
696
|
+
'ReactDOM.render',
|
|
697
|
+
'ReactDOM.unmountComponentAtNode',
|
|
698
|
+
'ReactDOM.findDOMNode',
|
|
699
|
+
'ReactDOM.createPortal',
|
|
700
|
+
],
|
|
701
|
+
passes: 3,
|
|
702
|
+
unsafe: true,
|
|
703
|
+
unsafe_comps: true,
|
|
704
|
+
unsafe_Function: true,
|
|
705
|
+
unsafe_math: true,
|
|
706
|
+
unsafe_symbols: true,
|
|
707
|
+
unsafe_methods: true,
|
|
708
|
+
unsafe_proto: true,
|
|
709
|
+
unsafe_regexp: true,
|
|
710
|
+
unsafe_undefined: true,
|
|
711
|
+
dead_code: true,
|
|
712
|
+
side_effects: false,
|
|
713
|
+
},
|
|
714
|
+
mangle: {
|
|
715
|
+
safari10: true,
|
|
716
|
+
properties: {
|
|
717
|
+
regex: /^_/,
|
|
718
|
+
},
|
|
719
|
+
},
|
|
720
|
+
format: {
|
|
721
|
+
comments: false,
|
|
722
|
+
},
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
outputConfig.format = outputConfig.format || 'es'
|
|
726
|
+
outputConfig.minify = true
|
|
727
|
+
|
|
728
|
+
if (Array.isArray(config.build.rolldownOptions.output)) {
|
|
729
|
+
config.build.rolldownOptions.output[0] = outputConfig
|
|
730
|
+
}
|
|
731
|
+
else {
|
|
732
|
+
config.build.rolldownOptions.output = outputConfig
|
|
733
|
+
}
|
|
488
734
|
}
|
|
489
735
|
|
|
490
736
|
if (config.environments && config.environments.client) {
|
|
491
737
|
if (!config.environments.client.build) {
|
|
492
738
|
config.environments.client.build = {}
|
|
493
739
|
}
|
|
494
|
-
if (!config.environments.client.build.
|
|
495
|
-
config.environments.client.build.
|
|
740
|
+
if (!config.environments.client.build.rolldownOptions) {
|
|
741
|
+
config.environments.client.build.rolldownOptions = {}
|
|
496
742
|
}
|
|
497
|
-
if (!config.environments.client.build.
|
|
498
|
-
config.environments.client.build.
|
|
743
|
+
if (!config.environments.client.build.rolldownOptions.input) {
|
|
744
|
+
config.environments.client.build.rolldownOptions.input = {}
|
|
499
745
|
}
|
|
500
746
|
|
|
501
747
|
if (
|
|
502
|
-
typeof config.environments.client.build.
|
|
748
|
+
typeof config.environments.client.build.rolldownOptions.input
|
|
503
749
|
=== 'object'
|
|
504
|
-
&& !Array.isArray(config.environments.client.build.
|
|
750
|
+
&& !Array.isArray(config.environments.client.build.rolldownOptions.input)
|
|
505
751
|
) {
|
|
506
752
|
(
|
|
507
|
-
config.environments.client.build.
|
|
753
|
+
config.environments.client.build.rolldownOptions.input as Record<
|
|
508
754
|
string,
|
|
509
755
|
string
|
|
510
756
|
>
|
|
511
757
|
)['client-components'] = 'virtual:rsc-client-components'
|
|
512
758
|
}
|
|
759
|
+
|
|
760
|
+
config.environments.client.build.rolldownOptions.plugins
|
|
761
|
+
= config.environments.client.build.rolldownOptions.plugins || []
|
|
762
|
+
if (
|
|
763
|
+
Array.isArray(
|
|
764
|
+
config.environments.client.build.rolldownOptions.plugins,
|
|
765
|
+
)
|
|
766
|
+
) {
|
|
767
|
+
config.environments.client.build.rolldownOptions.plugins.push(
|
|
768
|
+
minify(),
|
|
769
|
+
)
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
config.environments.client.build.minify = true
|
|
773
|
+
config.environments.client.build.target = config.environments.client
|
|
774
|
+
.build
|
|
775
|
+
.target || [
|
|
776
|
+
'es2020',
|
|
777
|
+
'edge88',
|
|
778
|
+
'firefox78',
|
|
779
|
+
'chrome87',
|
|
780
|
+
'safari14',
|
|
781
|
+
]
|
|
782
|
+
config.environments.client.build.cssMinify = 'esbuild'
|
|
783
|
+
config.environments.client.build.cssCodeSplit = true
|
|
784
|
+
config.environments.client.build.assetsInlineLimit = 4096
|
|
785
|
+
config.environments.client.build.rolldownOptions.treeshake = {
|
|
786
|
+
moduleSideEffects: false,
|
|
787
|
+
unknownGlobalSideEffects: false,
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
config.environments.client.build.rolldownOptions.output
|
|
791
|
+
= config.environments.client.build.rolldownOptions.output || {}
|
|
792
|
+
const clientOutputConfig = Array.isArray(
|
|
793
|
+
config.environments.client.build.rolldownOptions.output,
|
|
794
|
+
)
|
|
795
|
+
? config.environments.client.build.rolldownOptions.output[0] || {}
|
|
796
|
+
: config.environments.client.build.rolldownOptions.output
|
|
797
|
+
|
|
798
|
+
clientOutputConfig.manualChunks = (id) => {
|
|
799
|
+
if (
|
|
800
|
+
id.includes('node_modules/react-dom')
|
|
801
|
+
|| id.includes('react-dom/client')
|
|
802
|
+
|| id.includes('react-dom/server')
|
|
803
|
+
|| id.includes('react-dom/')
|
|
804
|
+
) {
|
|
805
|
+
return 'react-dom'
|
|
806
|
+
}
|
|
807
|
+
if (
|
|
808
|
+
(id.includes('node_modules/react') || id.includes('react/'))
|
|
809
|
+
&& !id.includes('react-dom')
|
|
810
|
+
) {
|
|
811
|
+
return 'react'
|
|
812
|
+
}
|
|
813
|
+
if (id.includes('scheduler') && id.includes('node_modules')) {
|
|
814
|
+
return 'scheduler'
|
|
815
|
+
}
|
|
816
|
+
if (
|
|
817
|
+
id.includes('rari')
|
|
818
|
+
&& (id.includes('router') || id.includes('navigation'))
|
|
819
|
+
) {
|
|
820
|
+
return 'router'
|
|
821
|
+
}
|
|
822
|
+
if (id.includes('markdown-it') || id.includes('shiki')) {
|
|
823
|
+
return 'vendor'
|
|
824
|
+
}
|
|
825
|
+
if (id.includes('node_modules')) {
|
|
826
|
+
return 'vendor'
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
clientOutputConfig.format = clientOutputConfig.format || 'es'
|
|
831
|
+
clientOutputConfig.minify = true
|
|
832
|
+
|
|
833
|
+
if (
|
|
834
|
+
Array.isArray(config.environments.client.build.rolldownOptions.output)
|
|
835
|
+
) {
|
|
836
|
+
config.environments.client.build.rolldownOptions.output[0]
|
|
837
|
+
= clientOutputConfig
|
|
838
|
+
}
|
|
839
|
+
else {
|
|
840
|
+
config.environments.client.build.rolldownOptions.output
|
|
841
|
+
= clientOutputConfig
|
|
842
|
+
}
|
|
513
843
|
}
|
|
514
844
|
|
|
515
845
|
return config
|
|
@@ -520,6 +850,20 @@ if (import.meta.hot) {
|
|
|
520
850
|
return null
|
|
521
851
|
}
|
|
522
852
|
|
|
853
|
+
if (code.includes('react-dom')) {
|
|
854
|
+
code = code.replace(
|
|
855
|
+
/import\s+ReactDOM\s+from\s+['"]react-dom\/client['"];?/g,
|
|
856
|
+
'import { createRoot, hydrateRoot } from \'react-dom/client\';',
|
|
857
|
+
)
|
|
858
|
+
code = code.replace(
|
|
859
|
+
/import\s+ReactDOM\s+from\s+['"]react-dom['"];?/g,
|
|
860
|
+
'import { createRoot, hydrateRoot } from \'react-dom/client\';',
|
|
861
|
+
)
|
|
862
|
+
|
|
863
|
+
code = code.replace(/ReactDOM\.createRoot/g, 'createRoot')
|
|
864
|
+
code = code.replace(/ReactDOM\.hydrateRoot/g, 'hydrateRoot')
|
|
865
|
+
}
|
|
866
|
+
|
|
523
867
|
const environment = (this as any).environment
|
|
524
868
|
|
|
525
869
|
if (hasTopLevelDirective(code, 'use client')) {
|
|
@@ -1235,7 +1579,6 @@ export const __CLIENT_REFERENCE_REGISTRY__ = clientReferenceRegistry;
|
|
|
1235
1579
|
export const __SERVER_REFERENCE_REGISTRY__ = serverReferenceRegistry;
|
|
1236
1580
|
export const __CLIENT_COMPONENT_REGISTRY__ = clientComponentRegistry;
|
|
1237
1581
|
|
|
1238
|
-
// Module map for React Server Components
|
|
1239
1582
|
export function createClientModuleMap() {
|
|
1240
1583
|
const moduleMap = {};
|
|
1241
1584
|
|
|
@@ -1261,7 +1604,6 @@ export function createClientModuleMap() {
|
|
|
1261
1604
|
return `
|
|
1262
1605
|
import React, { useState, useEffect, Suspense } from 'react';
|
|
1263
1606
|
|
|
1264
|
-
// Client component registration for RSC system compatibility
|
|
1265
1607
|
if (typeof globalThis.__clientComponents === 'undefined') {
|
|
1266
1608
|
globalThis.__clientComponents = {};
|
|
1267
1609
|
}
|
|
@@ -1279,7 +1621,6 @@ export function registerClientComponent(componentFunction, id, exportName) {
|
|
|
1279
1621
|
|
|
1280
1622
|
const componentId = componentName;
|
|
1281
1623
|
|
|
1282
|
-
// Register in global registry for RSC traversal
|
|
1283
1624
|
globalThis.__clientComponents[componentId] = {
|
|
1284
1625
|
id: componentId,
|
|
1285
1626
|
path: id,
|
|
@@ -2040,7 +2381,7 @@ class RscClient {
|
|
|
2040
2381
|
const processedChildren = value.map((child, index) => {
|
|
2041
2382
|
const result = this.reconstructElementFromRscData(child, modules);
|
|
2042
2383
|
return result;
|
|
2043
|
-
}).filter(child => child !== null && child !== undefined);
|
|
2384
|
+
}).filter(child => child !== null && child !== undefined);
|
|
2044
2385
|
|
|
2045
2386
|
if (processedChildren.length === 0) {
|
|
2046
2387
|
processed[key] = null;
|
|
@@ -2185,7 +2526,6 @@ function ServerComponentWrapper({
|
|
|
2185
2526
|
}
|
|
2186
2527
|
|
|
2187
2528
|
function createServerComponentWrapper(componentName, importPath) {
|
|
2188
|
-
// Use a global refresh counter to force re-mounting when components change
|
|
2189
2529
|
let globalRefreshCounter = 0;
|
|
2190
2530
|
|
|
2191
2531
|
if (typeof window !== 'undefined') {
|
|
@@ -2199,7 +2539,6 @@ function createServerComponentWrapper(componentName, importPath) {
|
|
|
2199
2539
|
const ServerComponent = (props) => {
|
|
2200
2540
|
const [mountKey, setMountKey] = useState(globalRefreshCounter);
|
|
2201
2541
|
|
|
2202
|
-
// Force re-mount when component is invalidated
|
|
2203
2542
|
useEffect(() => {
|
|
2204
2543
|
const handleRscInvalidate = (event) => {
|
|
2205
2544
|
const detail = event.detail;
|
|
@@ -2220,7 +2559,7 @@ function createServerComponentWrapper(componentName, importPath) {
|
|
|
2220
2559
|
return React.createElement(Suspense, {
|
|
2221
2560
|
fallback: null
|
|
2222
2561
|
}, React.createElement(ServerComponentWrapper, {
|
|
2223
|
-
key: componentName + '-' + mountKey,
|
|
2562
|
+
key: componentName + '-' + mountKey,
|
|
2224
2563
|
componentId: componentName,
|
|
2225
2564
|
props: props,
|
|
2226
2565
|
fallback: null
|
|
@@ -2237,9 +2576,7 @@ function createServerComponentWrapper(componentName, importPath) {
|
|
|
2237
2576
|
export const fetchServerComponent = (componentId, props) =>
|
|
2238
2577
|
rscClient.fetchServerComponent(componentId, props);
|
|
2239
2578
|
|
|
2240
|
-
// Helper function to check if a file is a server component (client-side)
|
|
2241
2579
|
function isServerComponent(filePath) {
|
|
2242
|
-
// Simple client-side check based on file path patterns
|
|
2243
2580
|
return filePath && (
|
|
2244
2581
|
filePath.includes('ServerWithClient') ||
|
|
2245
2582
|
filePath.includes('server') ||
|
|
@@ -2247,32 +2584,26 @@ function isServerComponent(filePath) {
|
|
|
2247
2584
|
);
|
|
2248
2585
|
}
|
|
2249
2586
|
|
|
2250
|
-
// HMR support for RSC cache invalidation
|
|
2251
2587
|
if (import.meta.hot) {
|
|
2252
|
-
// Listen for Vite's beforeFullReload event for server components
|
|
2253
2588
|
import.meta.hot.on('vite:beforeFullReload', async (data) => {
|
|
2254
2589
|
if (data?.path && isServerComponent(data.path)) {
|
|
2255
|
-
// Immediately invalidate cache and trigger re-registration before reload
|
|
2256
2590
|
await invalidateRscCache({ filePath: data.path, forceReload: true });
|
|
2257
2591
|
}
|
|
2258
2592
|
});
|
|
2259
2593
|
|
|
2260
2594
|
|
|
2261
2595
|
|
|
2262
|
-
// Helper function to invalidate RSC cache and trigger component re-registration
|
|
2263
2596
|
async function invalidateRscCache(data) {
|
|
2264
2597
|
const filePath = data?.filePath || data;
|
|
2265
2598
|
|
|
2266
|
-
// Wait for server to be ready
|
|
2267
2599
|
const waitForServerReady = async () => {
|
|
2268
|
-
for (let i = 0; i < 20; i++) {
|
|
2600
|
+
for (let i = 0; i < 20; i++) {
|
|
2269
2601
|
try {
|
|
2270
2602
|
const response = await fetch('/_rsc_status');
|
|
2271
2603
|
if (response.ok) {
|
|
2272
2604
|
return true;
|
|
2273
2605
|
}
|
|
2274
2606
|
} catch (e) {
|
|
2275
|
-
// Server not ready yet
|
|
2276
2607
|
}
|
|
2277
2608
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
2278
2609
|
}
|
|
@@ -2281,10 +2612,8 @@ if (import.meta.hot) {
|
|
|
2281
2612
|
|
|
2282
2613
|
const serverReady = await waitForServerReady();
|
|
2283
2614
|
if (serverReady) {
|
|
2284
|
-
// Clear client-side RSC cache immediately
|
|
2285
2615
|
rscClient.clearCache();
|
|
2286
2616
|
|
|
2287
|
-
// Trigger immediate server component re-registration
|
|
2288
2617
|
try {
|
|
2289
2618
|
await fetch('/api/rsc/hmr-register', {
|
|
2290
2619
|
method: 'POST',
|
|
@@ -2296,14 +2625,10 @@ if (import.meta.hot) {
|
|
|
2296
2625
|
})
|
|
2297
2626
|
});
|
|
2298
2627
|
|
|
2299
|
-
// Wait a bit for the server to re-register the component
|
|
2300
|
-
// The server now immediately reads and re-registers the component
|
|
2301
2628
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
2302
2629
|
} catch (error) {
|
|
2303
|
-
// Fallback to existing timeout-based approach
|
|
2304
2630
|
}
|
|
2305
2631
|
|
|
2306
|
-
// Trigger re-render of active server components
|
|
2307
2632
|
if (typeof window !== 'undefined') {
|
|
2308
2633
|
const event = new CustomEvent('rari:rsc-invalidate', {
|
|
2309
2634
|
detail: { filePath }
|
|
@@ -2388,6 +2713,108 @@ ${registrations.join('\n')}
|
|
|
2388
2713
|
return [mainPlugin, serverBuildPlugin]
|
|
2389
2714
|
}
|
|
2390
2715
|
|
|
2716
|
+
export function createReactDOMOptimization() {
|
|
2717
|
+
return {
|
|
2718
|
+
build: {
|
|
2719
|
+
rollupOptions: {
|
|
2720
|
+
output: {
|
|
2721
|
+
manualChunks: (id: string) => {
|
|
2722
|
+
if (
|
|
2723
|
+
id.includes('node_modules/react-dom')
|
|
2724
|
+
|| id.includes('react-dom/client')
|
|
2725
|
+
|| id.includes('react-dom/server')
|
|
2726
|
+
|| id.includes('react-dom/')
|
|
2727
|
+
) {
|
|
2728
|
+
return 'react-dom'
|
|
2729
|
+
}
|
|
2730
|
+
|
|
2731
|
+
if (
|
|
2732
|
+
(id.includes('node_modules/react') || id.includes('react/'))
|
|
2733
|
+
&& !id.includes('react-dom')
|
|
2734
|
+
) {
|
|
2735
|
+
return 'react'
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
if (id.includes('scheduler') && id.includes('node_modules')) {
|
|
2739
|
+
return 'scheduler'
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2742
|
+
if (id.includes('markdown-it') || id.includes('shiki')) {
|
|
2743
|
+
return 'vendor'
|
|
2744
|
+
}
|
|
2745
|
+
|
|
2746
|
+
if (id.includes('node_modules')) {
|
|
2747
|
+
return 'vendor'
|
|
2748
|
+
}
|
|
2749
|
+
},
|
|
2750
|
+
},
|
|
2751
|
+
treeshake: {
|
|
2752
|
+
moduleSideEffects: (id: string) => {
|
|
2753
|
+
if (id.includes('.css') || id.includes('polyfill')) {
|
|
2754
|
+
return true
|
|
2755
|
+
}
|
|
2756
|
+
if (
|
|
2757
|
+
id.includes('react-dom')
|
|
2758
|
+
|| id.includes('react')
|
|
2759
|
+
|| id.includes('scheduler')
|
|
2760
|
+
|| id.includes('react-dom/client')
|
|
2761
|
+
|| id.includes('react-dom/server')
|
|
2762
|
+
) {
|
|
2763
|
+
return false
|
|
2764
|
+
}
|
|
2765
|
+
return false
|
|
2766
|
+
},
|
|
2767
|
+
unknownGlobalSideEffects: false,
|
|
2768
|
+
},
|
|
2769
|
+
},
|
|
2770
|
+
minify: 'terser',
|
|
2771
|
+
target: ['es2020', 'edge88', 'firefox78', 'chrome87', 'safari14'],
|
|
2772
|
+
cssMinify: 'esbuild',
|
|
2773
|
+
sourcemap: false,
|
|
2774
|
+
terserOptions: {
|
|
2775
|
+
compress: {
|
|
2776
|
+
drop_console: true,
|
|
2777
|
+
drop_debugger: true,
|
|
2778
|
+
pure_funcs: [
|
|
2779
|
+
'console.log',
|
|
2780
|
+
'console.info',
|
|
2781
|
+
'console.debug',
|
|
2782
|
+
'console.warn',
|
|
2783
|
+
'invariant',
|
|
2784
|
+
'warning',
|
|
2785
|
+
'__DEV__',
|
|
2786
|
+
'ReactDOM.render',
|
|
2787
|
+
'ReactDOM.unmountComponentAtNode',
|
|
2788
|
+
'ReactDOM.findDOMNode',
|
|
2789
|
+
'ReactDOM.createPortal',
|
|
2790
|
+
],
|
|
2791
|
+
passes: 3,
|
|
2792
|
+
unsafe: true,
|
|
2793
|
+
unsafe_comps: true,
|
|
2794
|
+
unsafe_Function: true,
|
|
2795
|
+
unsafe_math: true,
|
|
2796
|
+
unsafe_symbols: true,
|
|
2797
|
+
unsafe_methods: true,
|
|
2798
|
+
unsafe_proto: true,
|
|
2799
|
+
unsafe_regexp: true,
|
|
2800
|
+
unsafe_undefined: true,
|
|
2801
|
+
dead_code: true,
|
|
2802
|
+
side_effects: false,
|
|
2803
|
+
},
|
|
2804
|
+
mangle: {
|
|
2805
|
+
safari10: true,
|
|
2806
|
+
properties: {
|
|
2807
|
+
regex: /^_/,
|
|
2808
|
+
},
|
|
2809
|
+
},
|
|
2810
|
+
format: {
|
|
2811
|
+
comments: false,
|
|
2812
|
+
},
|
|
2813
|
+
},
|
|
2814
|
+
},
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
|
|
2391
2818
|
export function defineRariConfig(
|
|
2392
2819
|
config: UserConfig & { plugins?: Plugin[] },
|
|
2393
2820
|
): UserConfig {
|