3
3
/** @import * as Rollup from 'rollup' */
4
4
/** @import * as Vite from 'vite' */
5
5
6
- export { }
6
+ import { createRequire } from 'node:module'
7
+ import { join } from 'node:path'
8
+
9
+ import { isCSSRequest } from 'vite'
7
10
8
11
/**
12
+ * Modified from Vite deprecated splitVendorChunk plugin
13
+ * @see {@link https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/splitVendorChunk.ts }
14
+ * @license {@link https://github.com/vitejs/vite/blob/main/LICENSE | MIT }
15
+ *
9
16
* @returns {Vite.Plugin }
10
17
*/
11
18
export default function splitVendorChunk ( ) {
19
+ const frameworkPaths = getTopLevelFrameworkPaths ( [ 'react' , 'react-dom' ] )
20
+
21
+ /**
22
+ * @type {Rollup.GetManualChunk }
23
+ */
24
+ const manualChunks = ( id , { getModuleInfo } ) => {
25
+ if (
26
+ ! isCSSRequest ( id )
27
+ && isInNodeModules ( id )
28
+ && isStaticImported ( id ) ) {
29
+ if ( frameworkPaths . some ( ( path ) => id . includes ( path ) ) ) {
30
+ return 'framework'
31
+ }
32
+ return 'vendor'
33
+ }
34
+
35
+ /**
36
+ * @param {string } moduleId
37
+ * @param {string[] } importStack
38
+ * @returns {boolean }
39
+ */
40
+ function isStaticImported ( moduleId , importStack = [ ] ) {
41
+ if ( importStack . includes ( moduleId ) ) {
42
+ return false
43
+ }
44
+ const moduleInfo = getModuleInfo ( moduleId )
45
+ if ( ! moduleInfo ) {
46
+ return false
47
+ }
48
+ if ( moduleInfo . isEntry ) {
49
+ return true
50
+ }
51
+ return moduleInfo . importers . some ( ( importerId ) =>
52
+ isStaticImported ( importerId , importStack . concat ( moduleId ) ) )
53
+ }
54
+ }
55
+
12
56
return {
13
57
name : 'split-vendor-chunk' ,
14
58
config ( ) {
@@ -23,38 +67,6 @@ export default function splitVendorChunk() {
23
67
}
24
68
}
25
69
26
- /**
27
- * @type {Rollup.GetManualChunk }
28
- */
29
- const manualChunks = ( id , { getModuleInfo } ) => {
30
- if (
31
- isInNodeModules ( id )
32
- && ! isCSSRequest ( id )
33
- && isStaticImported ( id ) ) {
34
- return 'vendor'
35
- }
36
-
37
- /**
38
- * @param {string } moduleId
39
- * @param {string[] } importStack
40
- * @returns {boolean }
41
- */
42
- function isStaticImported ( moduleId , importStack = [ ] ) {
43
- if ( importStack . includes ( moduleId ) ) {
44
- return false
45
- }
46
- const moduleInfo = getModuleInfo ( moduleId )
47
- if ( ! moduleInfo ) {
48
- return false
49
- }
50
- if ( moduleInfo . isEntry ) {
51
- return true
52
- }
53
- return moduleInfo . importers . some ( ( importerId ) =>
54
- isStaticImported ( importerId , importStack . concat ( moduleId ) ) )
55
- }
56
- }
57
-
58
70
/**
59
71
* @param {string } id
60
72
* @returns {boolean }
@@ -64,11 +76,59 @@ function isInNodeModules(id) {
64
76
}
65
77
66
78
/**
67
- * @param {string } request
68
- * @returns {boolean }
79
+ * Modified from Sukka's webpack config
80
+ * @see {@link https://blog.skk.moe/post/webpack-react-without-create-react-app/#splitChunks }
81
+ * @license {@link https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh | CC BY-NC-SA 4.0 }
82
+ *
83
+ * @param {string[] } packages
84
+ * @param {string= } directory
85
+ * @returns {string[] }
69
86
*/
70
- function isCSSRequest ( request ) {
71
- return CSS_LANGS_RE . test ( request )
72
- }
87
+ function getTopLevelFrameworkPaths ( packages , directory = import . meta. dirname ) {
88
+ const require = createRequire ( import . meta. url )
89
+
90
+ /** @type {string[] } */
91
+ const toplevelPaths = [ ]
92
+
93
+ /** @type {Set<string> } */
94
+ const visitedPackages = new Set ( )
95
+
96
+ /**
97
+ * @param {string } packageName
98
+ * @param {string } relativePath
99
+ */
100
+ function addPath ( packageName , relativePath ) {
101
+ try {
102
+ if ( visitedPackages . has ( packageName ) ) {
103
+ return
104
+ }
105
+ visitedPackages . add ( packageName )
73
106
74
- const CSS_LANGS_RE = / \. ( c s s | l e s s | s a s s | s c s s | s t y l | s t y l u s | p c s s | p o s t c s s | s s s ) (?: $ | \? ) /
107
+ const packageJsonPath = require . resolve ( `${ packageName } /package.json` , {
108
+ paths : [ relativePath ] ,
109
+ } )
110
+
111
+ const packagePath = join ( packageJsonPath , '../' )
112
+ if ( toplevelPaths . includes ( packagePath ) ) {
113
+ return
114
+ }
115
+ toplevelPaths . push ( packagePath )
116
+
117
+ const { dependencies } = require ( packageJsonPath )
118
+ if ( dependencies ) {
119
+ Object . keys ( dependencies ) . forEach ( ( dependencyName ) => {
120
+ addPath ( dependencyName , packagePath )
121
+ } )
122
+ }
123
+ }
124
+ catch {
125
+ // ignore
126
+ }
127
+ }
128
+
129
+ packages . forEach ( ( packageName ) => {
130
+ addPath ( packageName , directory )
131
+ } )
132
+
133
+ return toplevelPaths
134
+ }
0 commit comments