@modern-js/app-tools 3.3.0 → 3.5.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.
@@ -48,6 +48,13 @@ async function generateBuilder(options, bundlerType) {
48
48
  else mergedEnvironments[name] = builderConfig.environments[name];
49
49
  builderConfig.environments = mergedEnvironments;
50
50
  } else builderConfig.environments = environments;
51
+ const hooks = appContext._internalContext.pluginAPI?.getHooks();
52
+ if (hooks?.modifyBuilderEnvironments) {
53
+ const { environments: modifiedEnvironments } = await hooks.modifyBuilderEnvironments.call({
54
+ environments: builderConfig.environments
55
+ });
56
+ builderConfig.environments = modifiedEnvironments;
57
+ }
51
58
  const builder = await (0, builder_namespaceObject.createBuilder)({
52
59
  cwd: appContext.appDirectory,
53
60
  rscClientRuntimePath: `@${appContext.metaName}/runtime/rsc/client`,
@@ -127,7 +127,8 @@ function applyRouterPlugin(chain, pluginName, options, HtmlBundlerPlugin) {
127
127
  staticJsDir: normalizedConfig.output?.distPath?.js,
128
128
  disableFilenameHash: normalizedConfig.output?.filenameHash === false,
129
129
  scriptLoading: normalizedConfig.html?.scriptLoading,
130
- nonce: normalizedConfig.security?.nonce
130
+ nonce: normalizedConfig.security?.nonce,
131
+ useRsc: (0, utils_namespaceObject.isUseRsc)(normalizedConfig)
131
132
  }
132
133
  ]);
133
134
  }
@@ -96,6 +96,25 @@ class RouterPlugin {
96
96
  routeAssets: {}
97
97
  });
98
98
  const prevManifest = JSON.parse(prevManifestStr);
99
+ const namedChunkGroupInstances = new Map();
100
+ for (const cg of compilation.chunkGroups || [])if (cg.name) namedChunkGroupInstances.set(cg.name, cg);
101
+ const collectDescendantCssAssets = (name)=>{
102
+ const root = namedChunkGroupInstances.get(name);
103
+ if (!root) return [];
104
+ const cssFiles = new Set();
105
+ const visited = new Set();
106
+ const stack = [
107
+ ...root.childrenIterable
108
+ ];
109
+ while(stack.length){
110
+ const child = stack.pop();
111
+ if (visited.has(child)) continue;
112
+ visited.add(child);
113
+ for (const chunk of child.chunks)for (const file of chunk.files)if (/\.css$/.test(file)) cssFiles.add(publicPath ? normalizePath(publicPath) + file : file);
114
+ for (const c of child.childrenIterable)stack.push(c);
115
+ }
116
+ return Array.from(cssFiles);
117
+ };
99
118
  const asyncEntryNames = [];
100
119
  for (const [name, chunkGroup] of Object.entries(namedChunkGroups)){
101
120
  if (name.startsWith('async-')) asyncEntryNames.push(name);
@@ -103,7 +122,12 @@ class RouterPlugin {
103
122
  const filename = asset.name;
104
123
  return publicPath ? normalizePath(publicPath) + filename : filename;
105
124
  });
106
- const referenceCssAssets = assets.filter((asset)=>/\.css$/.test(asset));
125
+ const directCssAssets = assets.filter((asset)=>/\.css$/.test(asset));
126
+ const descendantCssAssets = collectDescendantCssAssets(name).filter((asset)=>!directCssAssets.includes(asset));
127
+ const referenceCssAssets = [
128
+ ...directCssAssets,
129
+ ...descendantCssAssets
130
+ ];
107
131
  routeAssets[name] = {
108
132
  chunkIds: chunkGroup.chunks,
109
133
  assets,
@@ -145,10 +169,14 @@ class RouterPlugin {
145
169
  const manifest = {
146
170
  routeAssets: relatedAssets
147
171
  };
172
+ const { useRsc } = this;
148
173
  const injectedContent = `
149
174
  ;(function(){
150
175
  window.${constants_namespaceObject.ROUTE_MANIFEST} = ${JSON.stringify(manifest, (k, v)=>{
151
- if (('assets' === k || 'referenceCssAssets' === k) && Array.isArray(v)) return v.map((item)=>item.replace(publicPath, ''));
176
+ if (('assets' === k || 'referenceCssAssets' === k) && Array.isArray(v)) {
177
+ if (!useRsc) return;
178
+ return v.map((item)=>item.replace(publicPath, ''));
179
+ }
152
180
  return v;
153
181
  })};
154
182
  })();
@@ -176,7 +204,7 @@ class RouterPlugin {
176
204
  });
177
205
  });
178
206
  }
179
- constructor({ staticJsDir = 'static/js', HtmlBundlerPlugin, enableInlineRouteManifests, disableFilenameHash = false, scriptLoading = 'defer', nonce }){
207
+ constructor({ staticJsDir = 'static/js', HtmlBundlerPlugin, enableInlineRouteManifests, disableFilenameHash = false, scriptLoading = 'defer', nonce, useRsc = false }){
180
208
  this.name = 'RouterPlugin';
181
209
  this.HtmlBundlerPlugin = HtmlBundlerPlugin;
182
210
  this.enableInlineRouteManifests = enableInlineRouteManifests;
@@ -184,6 +212,7 @@ class RouterPlugin {
184
212
  this.disableFilenameHash = disableFilenameHash;
185
213
  this.scriptLoading = scriptLoading;
186
214
  this.nonce = nonce;
215
+ this.useRsc = useRsc;
187
216
  }
188
217
  }
189
218
  exports.RouterPlugin = __webpack_exports__.RouterPlugin;
package/dist/cjs/index.js CHANGED
@@ -195,6 +195,7 @@ var __webpack_exports__ = {};
195
195
  deploy: (0, _modern_js_plugin__rspack_import_3.createAsyncHook)(),
196
196
  checkEntryPoint: (0, _modern_js_plugin__rspack_import_3.createAsyncHook)(),
197
197
  modifyEntrypoints: (0, _modern_js_plugin__rspack_import_3.createAsyncHook)(),
198
+ modifyBuilderEnvironments: (0, _modern_js_plugin__rspack_import_3.createAsyncHook)(),
198
199
  modifyFileSystemRoutes: (0, _modern_js_plugin__rspack_import_3.createAsyncHook)(),
199
200
  generateEntryCode: (0, _modern_js_plugin__rspack_import_3.createAsyncHook)(),
200
201
  onBeforeGenerateRoutes: (0, _modern_js_plugin__rspack_import_3.createAsyncHook)(),
@@ -16,6 +16,13 @@ async function generateBuilder(options, bundlerType) {
16
16
  else mergedEnvironments[name] = builderConfig.environments[name];
17
17
  builderConfig.environments = mergedEnvironments;
18
18
  } else builderConfig.environments = environments;
19
+ const hooks = appContext._internalContext.pluginAPI?.getHooks();
20
+ if (hooks?.modifyBuilderEnvironments) {
21
+ const { environments: modifiedEnvironments } = await hooks.modifyBuilderEnvironments.call({
22
+ environments: builderConfig.environments
23
+ });
24
+ builderConfig.environments = modifiedEnvironments;
25
+ }
19
26
  const builder = await createBuilder({
20
27
  cwd: appContext.appDirectory,
21
28
  rscClientRuntimePath: `@${appContext.metaName}/runtime/rsc/client`,
@@ -95,7 +95,8 @@ function applyRouterPlugin(chain, pluginName, options, HtmlBundlerPlugin) {
95
95
  staticJsDir: normalizedConfig.output?.distPath?.js,
96
96
  disableFilenameHash: normalizedConfig.output?.filenameHash === false,
97
97
  scriptLoading: normalizedConfig.html?.scriptLoading,
98
- nonce: normalizedConfig.security?.nonce
98
+ nonce: normalizedConfig.security?.nonce,
99
+ useRsc: isUseRsc(normalizedConfig)
99
100
  }
100
101
  ]);
101
102
  }
@@ -64,6 +64,25 @@ class RouterPlugin {
64
64
  routeAssets: {}
65
65
  });
66
66
  const prevManifest = JSON.parse(prevManifestStr);
67
+ const namedChunkGroupInstances = new Map();
68
+ for (const cg of compilation.chunkGroups || [])if (cg.name) namedChunkGroupInstances.set(cg.name, cg);
69
+ const collectDescendantCssAssets = (name)=>{
70
+ const root = namedChunkGroupInstances.get(name);
71
+ if (!root) return [];
72
+ const cssFiles = new Set();
73
+ const visited = new Set();
74
+ const stack = [
75
+ ...root.childrenIterable
76
+ ];
77
+ while(stack.length){
78
+ const child = stack.pop();
79
+ if (visited.has(child)) continue;
80
+ visited.add(child);
81
+ for (const chunk of child.chunks)for (const file of chunk.files)if (/\.css$/.test(file)) cssFiles.add(publicPath ? normalizePath(publicPath) + file : file);
82
+ for (const c of child.childrenIterable)stack.push(c);
83
+ }
84
+ return Array.from(cssFiles);
85
+ };
67
86
  const asyncEntryNames = [];
68
87
  for (const [name, chunkGroup] of Object.entries(namedChunkGroups)){
69
88
  if (name.startsWith('async-')) asyncEntryNames.push(name);
@@ -71,7 +90,12 @@ class RouterPlugin {
71
90
  const filename = asset.name;
72
91
  return publicPath ? normalizePath(publicPath) + filename : filename;
73
92
  });
74
- const referenceCssAssets = assets.filter((asset)=>/\.css$/.test(asset));
93
+ const directCssAssets = assets.filter((asset)=>/\.css$/.test(asset));
94
+ const descendantCssAssets = collectDescendantCssAssets(name).filter((asset)=>!directCssAssets.includes(asset));
95
+ const referenceCssAssets = [
96
+ ...directCssAssets,
97
+ ...descendantCssAssets
98
+ ];
75
99
  routeAssets[name] = {
76
100
  chunkIds: chunkGroup.chunks,
77
101
  assets,
@@ -113,10 +137,14 @@ class RouterPlugin {
113
137
  const manifest = {
114
138
  routeAssets: relatedAssets
115
139
  };
140
+ const { useRsc } = this;
116
141
  const injectedContent = `
117
142
  ;(function(){
118
143
  window.${ROUTE_MANIFEST} = ${JSON.stringify(manifest, (k, v)=>{
119
- if (('assets' === k || 'referenceCssAssets' === k) && Array.isArray(v)) return v.map((item)=>item.replace(publicPath, ''));
144
+ if (('assets' === k || 'referenceCssAssets' === k) && Array.isArray(v)) {
145
+ if (!useRsc) return;
146
+ return v.map((item)=>item.replace(publicPath, ''));
147
+ }
120
148
  return v;
121
149
  })};
122
150
  })();
@@ -144,7 +172,7 @@ class RouterPlugin {
144
172
  });
145
173
  });
146
174
  }
147
- constructor({ staticJsDir = 'static/js', HtmlBundlerPlugin, enableInlineRouteManifests, disableFilenameHash = false, scriptLoading = 'defer', nonce }){
175
+ constructor({ staticJsDir = 'static/js', HtmlBundlerPlugin, enableInlineRouteManifests, disableFilenameHash = false, scriptLoading = 'defer', nonce, useRsc = false }){
148
176
  this.name = 'RouterPlugin';
149
177
  this.HtmlBundlerPlugin = HtmlBundlerPlugin;
150
178
  this.enableInlineRouteManifests = enableInlineRouteManifests;
@@ -152,6 +180,7 @@ class RouterPlugin {
152
180
  this.disableFilenameHash = disableFilenameHash;
153
181
  this.scriptLoading = scriptLoading;
154
182
  this.nonce = nonce;
183
+ this.useRsc = useRsc;
155
184
  }
156
185
  }
157
186
  export { RouterPlugin };
@@ -40,6 +40,7 @@ const appTools = ()=>({
40
40
  deploy: createAsyncHook(),
41
41
  checkEntryPoint: createAsyncHook(),
42
42
  modifyEntrypoints: createAsyncHook(),
43
+ modifyBuilderEnvironments: createAsyncHook(),
43
44
  modifyFileSystemRoutes: createAsyncHook(),
44
45
  generateEntryCode: createAsyncHook(),
45
46
  onBeforeGenerateRoutes: createAsyncHook(),
@@ -17,6 +17,13 @@ async function generateBuilder(options, bundlerType) {
17
17
  else mergedEnvironments[name] = builderConfig.environments[name];
18
18
  builderConfig.environments = mergedEnvironments;
19
19
  } else builderConfig.environments = environments;
20
+ const hooks = appContext._internalContext.pluginAPI?.getHooks();
21
+ if (hooks?.modifyBuilderEnvironments) {
22
+ const { environments: modifiedEnvironments } = await hooks.modifyBuilderEnvironments.call({
23
+ environments: builderConfig.environments
24
+ });
25
+ builderConfig.environments = modifiedEnvironments;
26
+ }
20
27
  const builder = await createBuilder({
21
28
  cwd: appContext.appDirectory,
22
29
  rscClientRuntimePath: `@${appContext.metaName}/runtime/rsc/client`,
@@ -97,7 +97,8 @@ function applyRouterPlugin(chain, pluginName, options, HtmlBundlerPlugin) {
97
97
  staticJsDir: normalizedConfig.output?.distPath?.js,
98
98
  disableFilenameHash: normalizedConfig.output?.filenameHash === false,
99
99
  scriptLoading: normalizedConfig.html?.scriptLoading,
100
- nonce: normalizedConfig.security?.nonce
100
+ nonce: normalizedConfig.security?.nonce,
101
+ useRsc: isUseRsc(normalizedConfig)
101
102
  }
102
103
  ]);
103
104
  }
@@ -65,6 +65,25 @@ class RouterPlugin {
65
65
  routeAssets: {}
66
66
  });
67
67
  const prevManifest = JSON.parse(prevManifestStr);
68
+ const namedChunkGroupInstances = new Map();
69
+ for (const cg of compilation.chunkGroups || [])if (cg.name) namedChunkGroupInstances.set(cg.name, cg);
70
+ const collectDescendantCssAssets = (name)=>{
71
+ const root = namedChunkGroupInstances.get(name);
72
+ if (!root) return [];
73
+ const cssFiles = new Set();
74
+ const visited = new Set();
75
+ const stack = [
76
+ ...root.childrenIterable
77
+ ];
78
+ while(stack.length){
79
+ const child = stack.pop();
80
+ if (visited.has(child)) continue;
81
+ visited.add(child);
82
+ for (const chunk of child.chunks)for (const file of chunk.files)if (/\.css$/.test(file)) cssFiles.add(publicPath ? normalizePath(publicPath) + file : file);
83
+ for (const c of child.childrenIterable)stack.push(c);
84
+ }
85
+ return Array.from(cssFiles);
86
+ };
68
87
  const asyncEntryNames = [];
69
88
  for (const [name, chunkGroup] of Object.entries(namedChunkGroups)){
70
89
  if (name.startsWith('async-')) asyncEntryNames.push(name);
@@ -72,7 +91,12 @@ class RouterPlugin {
72
91
  const filename = asset.name;
73
92
  return publicPath ? normalizePath(publicPath) + filename : filename;
74
93
  });
75
- const referenceCssAssets = assets.filter((asset)=>/\.css$/.test(asset));
94
+ const directCssAssets = assets.filter((asset)=>/\.css$/.test(asset));
95
+ const descendantCssAssets = collectDescendantCssAssets(name).filter((asset)=>!directCssAssets.includes(asset));
96
+ const referenceCssAssets = [
97
+ ...directCssAssets,
98
+ ...descendantCssAssets
99
+ ];
76
100
  routeAssets[name] = {
77
101
  chunkIds: chunkGroup.chunks,
78
102
  assets,
@@ -114,10 +138,14 @@ class RouterPlugin {
114
138
  const manifest = {
115
139
  routeAssets: relatedAssets
116
140
  };
141
+ const { useRsc } = this;
117
142
  const injectedContent = `
118
143
  ;(function(){
119
144
  window.${ROUTE_MANIFEST} = ${JSON.stringify(manifest, (k, v)=>{
120
- if (('assets' === k || 'referenceCssAssets' === k) && Array.isArray(v)) return v.map((item)=>item.replace(publicPath, ''));
145
+ if (('assets' === k || 'referenceCssAssets' === k) && Array.isArray(v)) {
146
+ if (!useRsc) return;
147
+ return v.map((item)=>item.replace(publicPath, ''));
148
+ }
121
149
  return v;
122
150
  })};
123
151
  })();
@@ -145,7 +173,7 @@ class RouterPlugin {
145
173
  });
146
174
  });
147
175
  }
148
- constructor({ staticJsDir = 'static/js', HtmlBundlerPlugin, enableInlineRouteManifests, disableFilenameHash = false, scriptLoading = 'defer', nonce }){
176
+ constructor({ staticJsDir = 'static/js', HtmlBundlerPlugin, enableInlineRouteManifests, disableFilenameHash = false, scriptLoading = 'defer', nonce, useRsc = false }){
149
177
  this.name = 'RouterPlugin';
150
178
  this.HtmlBundlerPlugin = HtmlBundlerPlugin;
151
179
  this.enableInlineRouteManifests = enableInlineRouteManifests;
@@ -153,6 +181,7 @@ class RouterPlugin {
153
181
  this.disableFilenameHash = disableFilenameHash;
154
182
  this.scriptLoading = scriptLoading;
155
183
  this.nonce = nonce;
184
+ this.useRsc = useRsc;
156
185
  }
157
186
  }
158
187
  export { RouterPlugin };
@@ -42,6 +42,7 @@ const appTools = ()=>({
42
42
  deploy: createAsyncHook(),
43
43
  checkEntryPoint: createAsyncHook(),
44
44
  modifyEntrypoints: createAsyncHook(),
45
+ modifyBuilderEnvironments: createAsyncHook(),
45
46
  modifyFileSystemRoutes: createAsyncHook(),
46
47
  generateEntryCode: createAsyncHook(),
47
48
  onBeforeGenerateRoutes: createAsyncHook(),
@@ -14,6 +14,7 @@ type Options = {
14
14
  disableFilenameHash?: boolean;
15
15
  scriptLoading?: ScriptLoading;
16
16
  nonce?: string;
17
+ useRsc?: boolean;
17
18
  };
18
19
  export declare class RouterPlugin {
19
20
  readonly name: string;
@@ -23,7 +24,8 @@ export declare class RouterPlugin {
23
24
  private disableFilenameHash?;
24
25
  private scriptLoading?;
25
26
  private nonce?;
26
- constructor({ staticJsDir, HtmlBundlerPlugin, enableInlineRouteManifests, disableFilenameHash, scriptLoading, nonce, }: Options);
27
+ private useRsc;
28
+ constructor({ staticJsDir, HtmlBundlerPlugin, enableInlineRouteManifests, disableFilenameHash, scriptLoading, nonce, useRsc, }: Options);
27
29
  private isTargetNodeOrWebWorker;
28
30
  private getEntryChunks;
29
31
  private getEntryChunkFiles;
@@ -2,6 +2,7 @@ import type { AppContext, AsyncHook, InternalContext, PluginHook, PluginHookTap,
2
2
  import type { Hooks } from '@modern-js/plugin/cli';
3
3
  import type { Entrypoint, HtmlPartials, HtmlTemplates, NestedRouteForCli, PageRoute, RouteLegacy, ServerPlugin, ServerRoute } from '@modern-js/types';
4
4
  import type { EagerRouteComponentFilesByEntry } from '@modern-js/utils';
5
+ import type { EnvironmentConfig } from '@rsbuild/core';
5
6
  import type { AppTools } from '.';
6
7
  import type { getHookRunners } from '../compat/hooks';
7
8
  import type { AppToolsNormalizedConfig, AppToolsUserConfig } from './config';
@@ -13,6 +14,9 @@ export type CheckEntryPointFn = TransformFunction<{
13
14
  export type ModifyEntrypointsFn = TransformFunction<{
14
15
  entrypoints: Entrypoint[];
15
16
  }>;
17
+ export type ModifyBuilderEnvironmentsFn = TransformFunction<{
18
+ environments: Record<string, EnvironmentConfig>;
19
+ }>;
16
20
  export type ModifyFileSystemRoutesFn = TransformFunction<{
17
21
  entrypoint: Entrypoint;
18
22
  routes: RouteLegacy[] | (NestedRouteForCli | PageRoute)[];
@@ -34,6 +38,7 @@ export interface AppToolsExtendAPI {
34
38
  deploy: PluginHookTap<DeplpoyFn>;
35
39
  checkEntryPoint: PluginHookTap<CheckEntryPointFn>;
36
40
  modifyEntrypoints: PluginHookTap<ModifyEntrypointsFn>;
41
+ modifyBuilderEnvironments: PluginHookTap<ModifyBuilderEnvironmentsFn>;
37
42
  modifyFileSystemRoutes: PluginHookTap<ModifyFileSystemRoutesFn>;
38
43
  generateEntryCode: PluginHookTap<GenerateEntryCodeFn>;
39
44
  onBeforeGenerateRoutes: PluginHookTap<BeforeGenerateRoutesFn>;
@@ -63,6 +68,7 @@ export interface AppToolsExtendHooks extends Record<string, PluginHook<(...args:
63
68
  deploy: AsyncHook<DeplpoyFn>;
64
69
  checkEntryPoint: AsyncHook<CheckEntryPointFn>;
65
70
  modifyEntrypoints: AsyncHook<ModifyEntrypointsFn>;
71
+ modifyBuilderEnvironments: AsyncHook<ModifyBuilderEnvironmentsFn>;
66
72
  modifyFileSystemRoutes: AsyncHook<ModifyFileSystemRoutesFn>;
67
73
  generateEntryCode: AsyncHook<GenerateEntryCodeFn>;
68
74
  onBeforeGenerateRoutes: AsyncHook<BeforeGenerateRoutesFn>;
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "modern",
16
16
  "modern.js"
17
17
  ],
18
- "version": "3.3.0",
18
+ "version": "3.5.0",
19
19
  "types": "./dist/types/index.d.ts",
20
20
  "main": "./dist/cjs/index.js",
21
21
  "exports": {
@@ -83,8 +83,8 @@
83
83
  "@babel/parser": "^7.29.7",
84
84
  "@babel/traverse": "^7.29.7",
85
85
  "@babel/types": "^7.29.7",
86
- "@rsbuild/core": "2.0.10",
87
- "@swc/core": "1.15.40",
86
+ "@rsbuild/core": "2.1.0",
87
+ "@swc/core": "1.15.41",
88
88
  "@swc/helpers": "^0.5.17",
89
89
  "es-module-lexer": "^1.7.0",
90
90
  "flatted": "^3.4.2",
@@ -93,19 +93,19 @@
93
93
  "ndepe": "^0.1.13",
94
94
  "pkg-types": "^1.3.1",
95
95
  "std-env": "^3.10.0",
96
- "@modern-js/i18n-utils": "3.3.0",
97
- "@modern-js/plugin": "3.3.0",
98
- "@modern-js/builder": "3.3.0",
99
- "@modern-js/plugin-data-loader": "3.3.0",
100
- "@modern-js/prod-server": "3.3.0",
101
- "@modern-js/server": "3.3.0",
102
- "@modern-js/server-core": "3.3.0",
103
- "@modern-js/server-utils": "3.3.0",
104
- "@modern-js/types": "3.3.0",
105
- "@modern-js/utils": "3.3.0"
96
+ "@modern-js/builder": "3.5.0",
97
+ "@modern-js/i18n-utils": "3.5.0",
98
+ "@modern-js/plugin": "3.5.0",
99
+ "@modern-js/plugin-data-loader": "3.5.0",
100
+ "@modern-js/prod-server": "3.5.0",
101
+ "@modern-js/server": "3.5.0",
102
+ "@modern-js/server-core": "3.5.0",
103
+ "@modern-js/server-utils": "3.5.0",
104
+ "@modern-js/types": "3.5.0",
105
+ "@modern-js/utils": "3.5.0"
106
106
  },
107
107
  "devDependencies": {
108
- "@rslib/core": "0.22.0",
108
+ "@rslib/core": "0.23.0",
109
109
  "@types/babel__traverse": "7.28.0",
110
110
  "@types/node": "^20",
111
111
  "ts-node": "^10.9.2",