@bleedingdev/modern-js-app-tools 3.9.0-ultramodern.9 → 3.9.3-ultramodern.1

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.
Files changed (145) hide show
  1. package/bin/modern-bundle-docs.js +2 -2
  2. package/bin/modern.js +2 -2
  3. package/dist/cjs/builder/generator/adapterCopy.js +26 -0
  4. package/dist/cjs/builder/generator/createCopyPattern.js +2 -1
  5. package/dist/cjs/builder/index.js +4 -0
  6. package/dist/cjs/builder/shared/builderPlugins/adapterHtml.js +2 -1
  7. package/dist/cjs/builder/shared/builderPlugins/adapterSSR.js +11 -6
  8. package/dist/cjs/builder/shared/lazyCompilation.js +26 -0
  9. package/dist/cjs/commands/build.js +1 -2
  10. package/dist/cjs/commands/deploy.js +1 -3
  11. package/dist/cjs/commands/index.js +10 -2
  12. package/dist/cjs/compat/hooks.js +1 -1
  13. package/dist/cjs/esm/ts-paths-loader.js +5 -4
  14. package/dist/cjs/esm/ts-paths-loader.mjs +5 -4
  15. package/dist/cjs/index.js +73 -99
  16. package/dist/cjs/plugins/analyze/getFileSystemEntry.js +1 -1
  17. package/dist/cjs/plugins/analyze/getServerRoutes.js +1 -1
  18. package/dist/cjs/plugins/analyze/index.js +2 -2
  19. package/dist/cjs/plugins/analyze/utils.js +6 -6
  20. package/dist/cjs/plugins/deploy/index.js +7 -28
  21. package/dist/cjs/plugins/deploy/platforms/netlify.js +2 -1
  22. package/dist/cjs/plugins/deploy/platforms/node.js +12 -3
  23. package/dist/cjs/plugins/deploy/platforms/templates/node-entry.cjs +3 -2
  24. package/dist/cjs/plugins/deploy/platforms/templates/node-entry.mjs +3 -2
  25. package/dist/cjs/plugins/deploy/platforms/vercel.js +2 -1
  26. package/dist/cjs/plugins/deploy/utils/index.js +15 -12
  27. package/dist/cjs/plugins/initialize/index.js +6 -5
  28. package/dist/cjs/plugins/serverBuild.js +0 -2
  29. package/dist/cjs/run/index.js +5 -5
  30. package/dist/cjs/types/config/base.js +62 -0
  31. package/dist/cjs/types/plugin-base.js +18 -0
  32. package/dist/cjs/types/plugin.js +46 -2
  33. package/dist/cjs/utils/initAppContext.js +1 -1
  34. package/dist/cjs/utils/loadPlugins.js +13 -7
  35. package/dist/cjs/utils/register.js +1 -1
  36. package/dist/esm/builder/generator/adapterCopy.mjs +23 -1
  37. package/dist/esm/builder/generator/createCopyPattern.mjs +2 -1
  38. package/dist/esm/builder/index.mjs +1 -0
  39. package/dist/esm/builder/shared/builderPlugins/adapterHtml.mjs +2 -1
  40. package/dist/esm/builder/shared/builderPlugins/adapterSSR.mjs +9 -7
  41. package/dist/esm/builder/shared/lazyCompilation.mjs +14 -1
  42. package/dist/esm/commands/build.mjs +1 -2
  43. package/dist/esm/commands/deploy.mjs +1 -3
  44. package/dist/esm/commands/index.mjs +10 -2
  45. package/dist/esm/compat/hooks.mjs +1 -1
  46. package/dist/esm/esm/ts-paths-loader.mjs +5 -4
  47. package/dist/esm/index.mjs +9 -18
  48. package/dist/esm/plugins/analyze/getFileSystemEntry.mjs +1 -1
  49. package/dist/esm/plugins/analyze/getServerRoutes.mjs +1 -1
  50. package/dist/esm/plugins/analyze/index.mjs +2 -2
  51. package/dist/esm/plugins/analyze/utils.mjs +7 -7
  52. package/dist/esm/plugins/deploy/index.mjs +5 -21
  53. package/dist/esm/plugins/deploy/platforms/netlify.mjs +2 -1
  54. package/dist/esm/plugins/deploy/platforms/node.mjs +12 -3
  55. package/dist/esm/plugins/deploy/platforms/templates/node-entry.cjs +3 -2
  56. package/dist/esm/plugins/deploy/platforms/templates/node-entry.mjs +3 -2
  57. package/dist/esm/plugins/deploy/platforms/vercel.mjs +2 -1
  58. package/dist/esm/plugins/deploy/utils/index.mjs +17 -14
  59. package/dist/esm/plugins/initialize/index.mjs +6 -5
  60. package/dist/esm/plugins/serverBuild.mjs +0 -2
  61. package/dist/esm/run/index.mjs +5 -5
  62. package/dist/esm/types/config/base.mjs +1 -0
  63. package/dist/esm/types/plugin-base.mjs +0 -0
  64. package/dist/esm/types/plugin.mjs +1 -0
  65. package/dist/esm/utils/initAppContext.mjs +2 -2
  66. package/dist/esm/utils/loadPlugins.mjs +4 -8
  67. package/dist/esm/utils/register.mjs +1 -1
  68. package/dist/esm-node/builder/generator/adapterCopy.mjs +23 -1
  69. package/dist/esm-node/builder/generator/createCopyPattern.mjs +2 -1
  70. package/dist/esm-node/builder/index.mjs +1 -0
  71. package/dist/esm-node/builder/shared/builderPlugins/adapterHtml.mjs +2 -1
  72. package/dist/esm-node/builder/shared/builderPlugins/adapterSSR.mjs +9 -7
  73. package/dist/esm-node/builder/shared/lazyCompilation.mjs +14 -1
  74. package/dist/esm-node/commands/build.mjs +1 -2
  75. package/dist/esm-node/commands/deploy.mjs +1 -3
  76. package/dist/esm-node/commands/index.mjs +10 -2
  77. package/dist/esm-node/compat/hooks.mjs +1 -1
  78. package/dist/esm-node/esm/ts-paths-loader.mjs +5 -4
  79. package/dist/esm-node/index.mjs +10 -20
  80. package/dist/esm-node/plugins/analyze/getFileSystemEntry.mjs +1 -1
  81. package/dist/esm-node/plugins/analyze/getServerRoutes.mjs +1 -1
  82. package/dist/esm-node/plugins/analyze/index.mjs +2 -2
  83. package/dist/esm-node/plugins/analyze/utils.mjs +7 -7
  84. package/dist/esm-node/plugins/deploy/index.mjs +5 -21
  85. package/dist/esm-node/plugins/deploy/platforms/netlify.mjs +2 -1
  86. package/dist/esm-node/plugins/deploy/platforms/node.mjs +12 -3
  87. package/dist/esm-node/plugins/deploy/platforms/templates/node-entry.cjs +3 -2
  88. package/dist/esm-node/plugins/deploy/platforms/templates/node-entry.mjs +3 -2
  89. package/dist/esm-node/plugins/deploy/platforms/vercel.mjs +2 -1
  90. package/dist/esm-node/plugins/deploy/utils/index.mjs +17 -15
  91. package/dist/esm-node/plugins/initialize/index.mjs +6 -5
  92. package/dist/esm-node/plugins/serverBuild.mjs +0 -2
  93. package/dist/esm-node/run/index.mjs +5 -5
  94. package/dist/esm-node/types/config/base.mjs +2 -0
  95. package/dist/esm-node/types/plugin-base.mjs +1 -0
  96. package/dist/esm-node/types/plugin.mjs +1 -0
  97. package/dist/esm-node/utils/initAppContext.mjs +2 -2
  98. package/dist/esm-node/utils/loadPlugins.mjs +4 -8
  99. package/dist/esm-node/utils/register.mjs +1 -1
  100. package/dist/types/builder/generator/adapterCopy.d.ts +13 -1
  101. package/dist/types/builder/index.d.ts +1 -0
  102. package/dist/types/builder/shared/builderPlugins/adapterBasic.d.ts +4 -2
  103. package/dist/types/builder/shared/builderPlugins/adapterSSR.d.ts +2 -1
  104. package/dist/types/builder/shared/builderPlugins/builderHooks.d.ts +10 -2
  105. package/dist/types/builder/shared/lazyCompilation.d.ts +15 -0
  106. package/dist/types/compat/hooks.d.ts +3 -2
  107. package/dist/types/index.d.ts +1 -3
  108. package/dist/types/plugins/analyze/getBundleEntry.d.ts +5 -4
  109. package/dist/types/plugins/analyze/getFileSystemEntry.d.ts +5 -4
  110. package/dist/types/plugins/analyze/utils.d.ts +2 -2
  111. package/dist/types/plugins/deploy/index.d.ts +1 -4
  112. package/dist/types/plugins/deploy/utils/index.d.ts +1 -1
  113. package/dist/types/run/index.d.ts +1 -1
  114. package/dist/types/types/config/base.d.ts +58 -0
  115. package/dist/types/types/config/deploy.d.ts +2 -50
  116. package/dist/types/types/config/dev.d.ts +1 -1
  117. package/dist/types/types/config/index.d.ts +18 -42
  118. package/dist/types/types/config/output.d.ts +2 -2
  119. package/dist/types/types/config/testing.d.ts +1 -1
  120. package/dist/types/types/config/tools.d.ts +1 -1
  121. package/dist/types/types/plugin-base.d.ts +188 -0
  122. package/dist/types/types/plugin.d.ts +9 -183
  123. package/dist/types/utils/initAppContext.d.ts +1 -1
  124. package/docs/apis/app/commands.md +1 -0
  125. package/docs/configure/app/bff/effect.md +5 -12
  126. package/docs/configure/app/output/disable-svgr.md +4 -0
  127. package/docs/configure/app/output/svg-default-export.md +4 -0
  128. package/docs/configure/app/source/react-compiler.md +2 -0
  129. package/docs/configure/app/tools/less.md +94 -19
  130. package/docs/configure/app/tools/sass.md +87 -18
  131. package/docs/configure/app/tools/svgr.md +91 -0
  132. package/docs/configure/app/tools/ts-checker.md +7 -21
  133. package/docs/guides/basic-features/render/ssr-cache.md +14 -1
  134. package/docs/guides/basic-features/static-assets/svg-assets.md +29 -17
  135. package/docs/guides/basic-features/testing/rstest.md +0 -2
  136. package/docs/guides/get-started/quick-start.md +1 -1
  137. package/docs/guides/get-started/ultramodern.md +45 -14
  138. package/docs/llms.txt +4 -3
  139. package/docs/plugin/introduction.md +10 -10
  140. package/docs/plugin/server-plugins/api.md +1 -0
  141. package/package.json +59 -30
  142. package/dist/cjs/plugins/serverRuntime.js +0 -53
  143. package/dist/esm/plugins/serverRuntime.mjs +0 -15
  144. package/dist/esm-node/plugins/serverRuntime.mjs +0 -16
  145. package/dist/types/plugins/serverRuntime.d.ts +0 -3
@@ -1,188 +1,14 @@
1
- import type { AppContext, AsyncHook, InternalContext, PluginHook, PluginHookTap, TransformFunction } from '@modern-js/plugin';
2
- import type { Hooks } from '@modern-js/plugin/cli';
3
- import type { BffRuntimeFramework } from '@modern-js/plugin/server';
4
- import type { Entrypoint, HtmlPartials, HtmlTemplates, HttpMethodDecider, NestedRouteForCli, PageRoute, RouteLegacy, ServerPlugin, ServerRoute } from '@modern-js/types';
5
- import type { EagerRouteComponentFilesByEntry } from '@modern-js/utils';
6
- import type { EnvironmentConfig } from '@rsbuild/core';
7
- import type { getHookRunners } from '../compat/hooks.js';
8
- import type { AppTools } from './index.js';
9
- import type { AppToolsNormalizedConfig, AppToolsUserConfig } from './config/index.js';
10
- export interface BffCompilation {
11
- readonly appDirectory: string;
12
- readonly apiDirectory: string;
13
- readonly sourceDirectories: readonly string[];
14
- readonly outputDirectories: readonly string[];
15
- readonly distDirectory: string;
16
- readonly tsconfigPath?: string;
17
- readonly moduleType: AppToolsContext['moduleType'];
1
+ import type { AppContext, Hooks } from '@modern-js/plugin/cli';
2
+ import type { NestedRouteForCli, PageRoute } from '@modern-js/types/cli';
3
+ import type { AppTools, AppToolsNormalizedConfig, AppToolsUserConfig } from './config/index.js';
4
+ import type { AppToolsExtendAPIBase, AppToolsExtendContextBase, AppToolsExtendHooksBase, ModifyFileSystemRoutesFn as BaseModifyFileSystemRoutesFn } from './plugin-base.js';
5
+ export * from './plugin-base.js';
6
+ export type ModifyFileSystemRoutesFn = BaseModifyFileSystemRoutesFn<NestedRouteForCli | PageRoute>;
7
+ export interface AppToolsExtendAPI extends AppToolsExtendAPIBase<AppTools, NestedRouteForCli | PageRoute> {
18
8
  }
19
- export interface BffGeneration {
20
- readonly appDirectory: string;
21
- readonly apiDirectory: string;
22
- readonly lambdaDirectory: string;
23
- readonly existLambda: boolean;
24
- readonly apiFiles: readonly string[];
25
- readonly relativeDistPath: string;
26
- readonly prefix: string;
27
- readonly port?: number;
28
- readonly requestId: string;
29
- readonly requestCreator?: string;
30
- readonly httpMethodDecider?: HttpMethodDecider;
9
+ export interface AppToolsExtendHooks extends AppToolsExtendHooksBase<NestedRouteForCli | PageRoute> {
31
10
  }
32
- export interface BffClientArtifact {
33
- /** Canonical relative source path under generation.apiDirectory. */
34
- readonly sourcePath: string;
35
- readonly code: string;
36
- readonly declaration: string;
37
- }
38
- export interface BffClientArtifacts {
39
- readonly generation: BffGeneration;
40
- additionalArtifacts: BffClientArtifact[];
41
- }
42
- export interface BffGeneratedModule {
43
- readonly code: string;
44
- readonly declaration: string;
45
- }
46
- export interface BffGeneratedEntries {
47
- readonly generation: BffGeneration;
48
- plugin: BffGeneratedModule;
49
- runtime: BffGeneratedModule | null;
50
- /** Direct dependencies required by the emitted SDK modules. */
51
- packageDependencies: Record<string, string>;
52
- }
53
- export type BeforeBffCompileFn = (context: BffCompilation) => void | Promise<void>;
54
- export type AfterBffCompileFn = (context: BffCompilation) => void | Promise<void>;
55
- export type ModifyBffClientArtifactsFn = TransformFunction<BffClientArtifacts>;
56
- export type ModifyBffGeneratedEntriesFn = TransformFunction<BffGeneratedEntries>;
57
- export type AfterPrepareFn = () => Promise<void> | void;
58
- export type CheckEntryPointFn = TransformFunction<{
59
- path: string;
60
- entry: false | string;
61
- }>;
62
- export type ModifyEntrypointsFn = TransformFunction<{
63
- entrypoints: Entrypoint[];
64
- }>;
65
- export type ModifyBuilderEnvironmentsFn = TransformFunction<{
66
- environments: Record<string, EnvironmentConfig>;
67
- }>;
68
- export type ModifyFileSystemRoutesFn = TransformFunction<{
69
- entrypoint: Entrypoint;
70
- routes: RouteLegacy[] | (NestedRouteForCli | PageRoute)[];
71
- }>;
72
- export type DeplpoyFn = () => Promise<void> | void;
73
- export type GenerateEntryCodeFn = (params: {
74
- entrypoints: Entrypoint[];
75
- }) => Promise<void> | void;
76
- export type BeforeGenerateRoutesFn = TransformFunction<{
77
- entrypoint: Entrypoint;
78
- code: string;
79
- }>;
80
- export type BeforePrintInstructionsFn = TransformFunction<{
81
- instructions: string;
82
- }>;
83
- export type AddRuntimeExportsFn = () => Promise<void> | void;
84
- export interface AppToolsExtendAPI {
85
- onAfterPrepare: PluginHookTap<AfterPrepareFn>;
86
- deploy: PluginHookTap<DeplpoyFn>;
87
- checkEntryPoint: PluginHookTap<CheckEntryPointFn>;
88
- modifyEntrypoints: PluginHookTap<ModifyEntrypointsFn>;
89
- modifyBuilderEnvironments: PluginHookTap<ModifyBuilderEnvironmentsFn>;
90
- modifyFileSystemRoutes: PluginHookTap<ModifyFileSystemRoutesFn>;
91
- generateEntryCode: PluginHookTap<GenerateEntryCodeFn>;
92
- onBeforeGenerateRoutes: PluginHookTap<BeforeGenerateRoutesFn>;
93
- /**
94
- * @deprecated
95
- */
96
- onBeforePrintInstructions: PluginHookTap<BeforePrintInstructionsFn>;
97
- /**
98
- * @deprecated use getAppContext instead
99
- */
100
- useAppContext: () => AppToolsContext;
101
- /**
102
- * @deprecated use getConfig instead
103
- */
104
- useConfigContext: () => AppToolsUserConfig;
105
- /**
106
- * @deprecated use getNormalizedConfig instead
107
- */
108
- useResolvedConfigContext: () => AppToolsNormalizedConfig<AppToolsUserConfig>;
109
- /**
110
- * @deprecated use api.xx instead
111
- */
112
- useHookRunners: () => ReturnType<typeof getHookRunners>;
113
- }
114
- export interface AppToolsExtendHooks extends Record<string, PluginHook<(...args: any[]) => any>> {
115
- onBeforeBffCompile: AsyncHook<BeforeBffCompileFn>;
116
- onAfterBffCompile: AsyncHook<AfterBffCompileFn>;
117
- modifyBffClientArtifacts: AsyncHook<ModifyBffClientArtifactsFn>;
118
- modifyBffGeneratedEntries: AsyncHook<ModifyBffGeneratedEntriesFn>;
119
- onAfterPrepare: AsyncHook<AfterPrepareFn>;
120
- deploy: AsyncHook<DeplpoyFn>;
121
- checkEntryPoint: AsyncHook<CheckEntryPointFn>;
122
- modifyEntrypoints: AsyncHook<ModifyEntrypointsFn>;
123
- modifyBuilderEnvironments: AsyncHook<ModifyBuilderEnvironmentsFn>;
124
- modifyFileSystemRoutes: AsyncHook<ModifyFileSystemRoutesFn>;
125
- generateEntryCode: AsyncHook<GenerateEntryCodeFn>;
126
- onBeforeGenerateRoutes: AsyncHook<BeforeGenerateRoutesFn>;
127
- /**
128
- * @deprecated
129
- */
130
- onBeforePrintInstructions: AsyncHook<BeforePrintInstructionsFn>;
131
- }
132
- export interface AppToolsExtendContext {
133
- metaName: string;
134
- internalDirectory: string;
135
- sharedDirectory: string;
136
- internalDirAlias: string;
137
- internalSrcAlias: string;
138
- apiDirectory: string;
139
- lambdaDirectory: string;
140
- runtimeConfigFile: string;
141
- serverPlugins: ServerPlugin[];
142
- moduleType: 'module' | 'commonjs';
143
- /** Exact generated files excluded from server compilation. */
144
- serverCompileExcludedFiles?: string[];
145
- /** Information for entry points */
146
- entrypoints: Entrypoint[];
147
- /** Selected entry points */
148
- checkedEntries: string[];
149
- /** Information for server routes */
150
- serverRoutes: ServerRoute[];
151
- /** Whether to use api only mode */
152
- apiOnly: boolean;
153
- _internalContext: InternalContext<AppTools>;
154
- /**
155
- * Information for HTML templates by entry
156
- * @private
157
- */
158
- partialsByEntrypoint?: Record<string, HtmlPartials>;
159
- /**
160
- * Information for HTML templates
161
- * @private
162
- */
163
- htmlTemplates: HtmlTemplates;
164
- /**
165
- * @deprecated compat old plugin, default is app tools
166
- */
167
- toolsType?: string;
168
- /**
169
- * Identification for bff runtime framework
170
- * @private
171
- */
172
- bffRuntimeFramework?: BffRuntimeFramework;
173
- /**
174
- * Route component files collected from the FINAL file-system routes (after all
175
- * `modifyFileSystemRoutes` consumers ran), keyed by entry name. Populated by
176
- * the router plugin during route generation and consumed (currently by stream
177
- * SSR lazy compilation) to force route component chunks eager.
178
- *
179
- * Published via the app context (`api.updateAppContext`) by the router plugin,
180
- * then read fresh when assembling the builder options and threaded into
181
- * `BuilderOptions.eagerRouteComponentFilesByEntry`; the SSR builder plugin
182
- * reads it from those options (not from the context directly).
183
- * @private
184
- */
185
- eagerRouteComponentFilesByEntry?: EagerRouteComponentFilesByEntry;
11
+ export interface AppToolsExtendContext extends AppToolsExtendContextBase<AppTools> {
186
12
  }
187
13
  export type AppToolsContext = AppContext<AppTools> & AppToolsExtendContext;
188
14
  export type AppToolsHooks = Hooks<AppToolsUserConfig, AppToolsNormalizedConfig, {}, {}> & AppToolsExtendHooks;
@@ -13,7 +13,7 @@ export declare const initAppContext: ({ metaName, appDirectory, runtimeConfigFil
13
13
  tempDir?: string;
14
14
  }) => {
15
15
  runtimeConfigFile: string;
16
- ip: any;
16
+ ip: string | undefined;
17
17
  port: number;
18
18
  moduleType: any;
19
19
  apiDirectory: string;
@@ -227,6 +227,7 @@ Usage: modern deploy [options]
227
227
  Options:
228
228
  -c --config <config> Specify configuration file path, either relative or absolute
229
229
  -s --skip-build Skip the build stage
230
+ --deploy-target <target> Deploy target (node, vercel, netlify, ghPages, cloudflare); overrides deploy.target and MODERNJS_DEPLOY
230
231
  -h, --help Display command help
231
232
  ```
232
233
 
@@ -51,7 +51,7 @@ the framework use the same Effect instance. Before setting
51
51
  `/effect-edge` or `/effect-client`, install the exact cohort:
52
52
 
53
53
  ```bash
54
- pnpm add effect@4.0.0-rc.112 @effect/opentelemetry@4.0.0-rc.112
54
+ pnpm add effect@4.0.0-rc.117 @effect/opentelemetry@4.0.0-rc.117
55
55
  ```
56
56
 
57
57
  The pin is exact because UltraModern ships Effect as one lockstep cohort. Apps
@@ -227,14 +227,10 @@ through `pnpm-workspace.yaml` overrides. For the current UltraModern cohort,
227
227
  generated apps use:
228
228
 
229
229
  ```yaml
230
- trustPolicyExclude:
231
- - 'effect@4.0.0-rc.112'
232
- - '@effect/opentelemetry@4.0.0-rc.112'
233
-
234
230
  overrides:
235
- '@effect/opentelemetry': 4.0.0-rc.112
236
- '@effect/vitest': 4.0.0-rc.112
237
- effect: 4.0.0-rc.112
231
+ '@effect/opentelemetry': 4.0.0-rc.117
232
+ '@effect/vitest': 4.0.0-rc.117
233
+ effect: 4.0.0-rc.117
238
234
  ```
239
235
 
240
236
  Do not add a different direct `effect` version in an app package. A mismatched
@@ -242,10 +238,7 @@ Effect prerelease can fail while building layers or HTTP middleware because runt
242
238
  services come from different package instances. The strict 24-hour release-age
243
239
  gate applies to installed packages; the current cohort has no Effect age
244
240
  exemption, and override-only `@effect/vitest` is not an installed approval
245
- target. `trustPolicyExclude` is a separate policy:
246
- its exact `effect` and `@effect/opentelemetry` exceptions cover their
247
- trusted-publisher to provenance metadata transition and are not release-age
248
- approvals.
241
+ target.
249
242
 
250
243
  ## Contract tests
251
244
 
@@ -5,6 +5,10 @@
5
5
  - **Type:** `boolean`
6
6
  - **Default:** `false`
7
7
 
8
+ :::warning Deprecated
9
+ `output.disableSvgr` is deprecated and will be removed in the next major version. Replace `output.disableSvgr: true` with [tools.svgr](/configure/app/tools/svgr.md) set to `false`; `output.disableSvgr: false` is the default behavior and can simply be removed. When both are set, `tools.svgr` wins.
10
+ :::
11
+
8
12
  Whether to transform SVGs into React components. If true, will treat all .svg files as assets.
9
13
 
10
14
  By default, when an SVG resource is referenced in a JS file, Modern.js will call SVGR to convert the SVG into a React component. If you are sure that all SVG resources in your project are not being used as React components, you can turn off this conversion by setting `disableSvgr` to true to improve build performance.
@@ -5,6 +5,10 @@
5
5
  - **Type:** `'url' | 'component'`
6
6
  - **Default:** `'url'`
7
7
 
8
+ :::warning Deprecated
9
+ `output.svgDefaultExport` is deprecated and will be removed in the next major version. Use `svgrOptions.exportType` of [tools.svgr](/configure/app/tools/svgr.md) instead: `'component'` maps to `exportType: 'default'`, `'url'` maps to `exportType: 'named'`. When both are set, `tools.svgr` wins.
10
+ :::
11
+
8
12
  `output.svgDefaultExport` is used to configure the default export type of SVG files.
9
13
 
10
14
  When `output.svgDefaultExport` is set to `url` , the default export of SVG files is the URL of the file. For example:
@@ -9,6 +9,8 @@ Whether to enable [React Compiler](https://react.dev/learn/react-compiler). Reac
9
9
 
10
10
  Modern.js implements this capability based on the Rust-based React Compiler built into Rspack's `builtin:swc-loader` (equivalent to setting SWC's `jsc.transform.reactCompiler`), reusing Rspack's built-in SWC transform chain without introducing Babel.
11
11
 
12
+ The compiler only runs for browser environments (`output.target: 'web'`). Server environments (`node`, the `web-worker` SSR worker and BFF code) render once per request and gain nothing from memoization, so they are never compiled.
13
+
12
14
  :::tip
13
15
  This option is disabled by default. It must be enabled explicitly for any React version, including React 19.
14
16
  :::
@@ -7,49 +7,78 @@
7
7
 
8
8
  ```js
9
9
  const defaultOptions = {
10
- lessOptions: {
11
- javascriptEnabled: true,
10
+ lessLoaderOptions: {
11
+ lessOptions: {
12
+ javascriptEnabled: true,
13
+ },
14
+ // CSS Source Map enabled by default in development environment
15
+ sourceMap: isDev,
12
16
  },
13
- // CSS Source Map enabled by default in development environment
14
- sourceMap: isDev,
15
17
  };
16
18
  ```
17
19
 
18
- You can modify the config of [less-loader](https://github.com/webpack-contrib/less-loader) via `tools.less`.
20
+ `tools.less` modifies the options of [@rsbuild/plugin-less](https://rsbuild.rs/plugins/list/plugin-less). It accepts the full plugin options:
21
+
22
+ | Option | Description |
23
+ | ------------------- | --------------------------------------------------------------------------------------------------- |
24
+ | `lessLoaderOptions` | Options passed to [less-loader](https://github.com/webpack-contrib/less-loader), object or function |
25
+ | `include` | Files handled by less-loader, defaults to `/\.less$/` |
26
+ | `exclude` | Files that less-loader should skip |
27
+ | `parallel` | Whether to compile Less modules in worker threads, defaults to `false` |
28
+
29
+ ### Modifying less-loader options
19
30
 
20
- ### Object Type
31
+ When `lessLoaderOptions` is an `Object`, it is merged with the default config through Object.assign in a shallow way. It should be noted that `lessOptions` is merged through deepMerge in a deep way. For example:
32
+
33
+ ```js
34
+ export default {
35
+ tools: {
36
+ less: {
37
+ lessLoaderOptions: {
38
+ lessOptions: {
39
+ javascriptEnabled: false,
40
+ },
41
+ },
42
+ },
43
+ },
44
+ };
45
+ ```
21
46
 
22
- When `tools.less` is configured as `Object` type, it is merged with the default config through Object.assign in a shallow way. It should be noted that `lessOptions` is merged through deepMerge in a deep way. For example:
47
+ When `lessLoaderOptions` is a `Function`, the default config is passed as the first parameter, which can be directly modified or returned as the final result. The second parameter provides some utility functions that can be called directly. For example:
23
48
 
24
49
  ```js
25
50
  export default {
26
51
  tools: {
27
52
  less: {
28
- lessOptions: {
29
- javascriptEnabled: false,
53
+ lessLoaderOptions(config) {
54
+ // Modify the config of lessOptions
55
+ config.lessOptions = {
56
+ javascriptEnabled: false,
57
+ };
30
58
  },
31
59
  },
32
60
  },
33
61
  };
34
62
  ```
35
63
 
36
- ### Function Type
64
+ ### Parallel compilation
37
65
 
38
- When `tools.less` is a Function, the default config is passed as the first parameter, which can be directly modified or returned as the final result. The second parameter provides some utility functions that can be called directly. For example:
66
+ Less compilation is pure JavaScript and runs on the Node.js main thread by default. With `parallel` enabled, Less modules are compiled in a pool of worker threads, which shortens the build when a project has many Less files.
39
67
 
40
68
  ```js
41
69
  export default {
42
70
  tools: {
43
- less(config) {
44
- // Modify the config of lessOptions
45
- config.lessOptions = {
46
- javascriptEnabled: false,
47
- };
71
+ less: {
72
+ parallel: true,
48
73
  },
49
74
  },
50
75
  };
51
76
  ```
52
77
 
78
+ :::tip
79
+ Options sent to worker threads must satisfy the [structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm). With `parallel` enabled, `lessLoaderOptions` therefore cannot contain functions, such as an `additionalData` function or a custom `implementation`.
80
+ :::
81
+
53
82
  ### Modifying Less Version
54
83
 
55
84
  In some scenarios, if you need to use a specific version of Less instead of the built-in Less v4 in Modern.js, you can install the desired Less version in your project and set it up using the `implementation` option of the `less-loader`.
@@ -58,7 +87,9 @@ In some scenarios, if you need to use a specific version of Less instead of the
58
87
  export default {
59
88
  tools: {
60
89
  less: {
61
- implementation: require('less'),
90
+ lessLoaderOptions: {
91
+ implementation: require('less'),
92
+ },
62
93
  },
63
94
  },
64
95
  };
@@ -75,8 +106,52 @@ Used to specify which files `less-loader` does not compile, You can pass in one
75
106
  ```js
76
107
  export default {
77
108
  tools: {
78
- less(config, { addExcludes }) {
79
- addExcludes(/node_modules/);
109
+ less: {
110
+ lessLoaderOptions(config, { addExcludes }) {
111
+ addExcludes(/node_modules/);
112
+ },
113
+ },
114
+ },
115
+ };
116
+ ```
117
+
118
+ The plugin's `exclude` option is the recommended equivalent:
119
+
120
+ ```js
121
+ export default {
122
+ tools: {
123
+ less: {
124
+ exclude: /node_modules/,
125
+ },
126
+ },
127
+ };
128
+ ```
129
+
130
+ ### Legacy form
131
+
132
+ :::warning Do not mix the two layers
133
+ As soon as an object contains a plugin-level key (`lessLoaderOptions`, `include`, `exclude`, ...), the whole object is parsed as plugin options and any loader option in it has no effect. For example, `lessOptions` in `tools.less: { parallel: true, lessOptions: { ... } }` is ignored and must be moved under `lessLoaderOptions`; a hint is printed in development.
134
+ :::
135
+
136
+ In earlier versions, `tools.less` took the less-loader options directly, e.g. `tools.less: { lessOptions: {} }` or `tools.less(config, { addExcludes }) {}`. This form still works: Modern.js wraps it into `lessLoaderOptions` and produces exactly the same config as before. A migration hint is printed in development, and the legacy form will be removed in the next major version.
137
+
138
+ ```js
139
+ // legacy
140
+ export default {
141
+ tools: {
142
+ less: {
143
+ lessOptions: { javascriptEnabled: false },
144
+ },
145
+ },
146
+ };
147
+
148
+ // current
149
+ export default {
150
+ tools: {
151
+ less: {
152
+ lessLoaderOptions: {
153
+ lessOptions: { javascriptEnabled: false },
154
+ },
80
155
  },
81
156
  },
82
157
  };
@@ -7,41 +7,64 @@
7
7
 
8
8
  ```js
9
9
  const defaultOptions = {
10
- // CSS Source Map enabled by default in development environment
11
- sourceMap: isDev,
10
+ sassLoaderOptions: {
11
+ // CSS Source Map enabled by default in development environment
12
+ sourceMap: isDev,
13
+ },
12
14
  };
13
15
  ```
14
16
 
15
- You can modify the config of [sass-loader](https://github.com/webpack-contrib/sass-loader) via `tools.sass`.
17
+ `tools.sass` modifies the options of [@rsbuild/plugin-sass](https://rsbuild.rs/plugins/list/plugin-sass). It accepts the full plugin options:
16
18
 
17
- ### Object Type
19
+ | Option | Description | |
20
+ | ------------------- | --------------------------------------------------------------------------------------------------- | -------- |
21
+ | `sassLoaderOptions` | Options passed to [sass-loader](https://github.com/webpack-contrib/sass-loader), object or function | |
22
+ | `include` | Files handled by sass-loader, defaults to \`/.s(?:a | c)ss$/\` |
23
+ | `exclude` | Files that sass-loader should skip | |
24
+ | `rewriteUrls` | Whether to rewrite relative URLs in Sass files with resolve-url-loader, defaults to `true` | |
18
25
 
19
- When `tools.sass` is `Object` type, it is merged with the default config through Object.assign. It should be noted that `sassOptions` is merged through deepMerge in a deep way.
26
+ ### Modifying sass-loader options
20
27
 
21
- For example:
28
+ When `sassLoaderOptions` is an `Object`, it is merged with the default config through Object.assign in a shallow way. It should be noted that `sassOptions` is merged through deepMerge in a deep way. For example:
22
29
 
23
30
  ```js
24
31
  export default {
25
32
  tools: {
26
33
  sass: {
27
- sourceMap: true,
34
+ sassLoaderOptions: {
35
+ sourceMap: true,
36
+ },
37
+ },
38
+ },
39
+ };
40
+ ```
41
+
42
+ When `sassLoaderOptions` is a `Function`, the default config is passed as the first parameter, which can be directly modified or returned as the final result. The second parameter provides some utility functions that can be called directly. For example:
43
+
44
+ ```js
45
+ export default {
46
+ tools: {
47
+ sass: {
48
+ sassLoaderOptions(config) {
49
+ // Modify the additionalData config
50
+ config.additionalData = async (content, loaderContext) => {
51
+ // ...
52
+ };
53
+ },
28
54
  },
29
55
  },
30
56
  };
31
57
  ```
32
58
 
33
- ### Function Type
59
+ ### Disabling URL rewriting
34
60
 
35
- When `tools.sass` is a Function, the default config is passed as the first parameter, which can be directly modified or returned as the final result. The second parameter provides some utility functions that can be called directly. For Example:
61
+ By default, relative URLs in Sass files are rewritten by resolve-url-loader so that they resolve relative to the source file. If your project does not rely on this, turn it off to drop one loader from the chain:
36
62
 
37
63
  ```js
38
64
  export default {
39
65
  tools: {
40
- sass(config) {
41
- // Modify sourceMap config
42
- config.additionalData = async (content, loaderContext) => {
43
- // ...
44
- };
66
+ sass: {
67
+ rewriteUrls: false,
45
68
  },
46
69
  },
47
70
  };
@@ -55,13 +78,15 @@ In some scenarios, if you need to use a specific version of Sass instead of the
55
78
  export default {
56
79
  tools: {
57
80
  sass: {
58
- implementation: require('sass'),
81
+ sassLoaderOptions: {
82
+ implementation: require('sass'),
83
+ },
59
84
  },
60
85
  },
61
86
  };
62
87
  ```
63
88
 
64
- ### Utility Function
89
+ ### Util Function
65
90
 
66
91
  #### addExcludes
67
92
 
@@ -72,8 +97,52 @@ Used to specify which files `sass-loader` does not compile, You can pass in one
72
97
  ```js
73
98
  export default {
74
99
  tools: {
75
- sass(config, { addExcludes }) {
76
- addExcludes(/node_modules/);
100
+ sass: {
101
+ sassLoaderOptions(config, { addExcludes }) {
102
+ addExcludes(/node_modules/);
103
+ },
104
+ },
105
+ },
106
+ };
107
+ ```
108
+
109
+ The plugin's `exclude` option is the recommended equivalent:
110
+
111
+ ```js
112
+ export default {
113
+ tools: {
114
+ sass: {
115
+ exclude: /node_modules/,
116
+ },
117
+ },
118
+ };
119
+ ```
120
+
121
+ ### Legacy form
122
+
123
+ :::warning Do not mix the two layers
124
+ As soon as an object contains a plugin-level key (`sassLoaderOptions`, `include`, `exclude`, ...), the whole object is parsed as plugin options and any loader option in it has no effect. For example, `sassOptions` in `tools.sass: { rewriteUrls: false, sassOptions: { ... } }` is ignored and must be moved under `sassLoaderOptions`; a hint is printed in development.
125
+ :::
126
+
127
+ In earlier versions, `tools.sass` took the sass-loader options directly, e.g. `tools.sass: { sassOptions: {} }` or `tools.sass(config, { addExcludes }) {}`. This form still works: Modern.js wraps it into `sassLoaderOptions` and produces exactly the same config as before. A migration hint is printed in development, and the legacy form will be removed in the next major version.
128
+
129
+ ```js
130
+ // legacy
131
+ export default {
132
+ tools: {
133
+ sass: {
134
+ sourceMap: true,
135
+ },
136
+ },
137
+ };
138
+
139
+ // current
140
+ export default {
141
+ tools: {
142
+ sass: {
143
+ sassLoaderOptions: {
144
+ sourceMap: true,
145
+ },
77
146
  },
78
147
  },
79
148
  };