@bleedingdev/modern-js-builder 3.2.0-ultramodern.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.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +26 -0
  3. package/dist/cjs/createBuilder.js +94 -0
  4. package/dist/cjs/index.js +59 -0
  5. package/dist/cjs/plugins/devtools.js +47 -0
  6. package/dist/cjs/plugins/emitRouteFile.js +75 -0
  7. package/dist/cjs/plugins/environmentDefaults.js +100 -0
  8. package/dist/cjs/plugins/globalVars.js +55 -0
  9. package/dist/cjs/plugins/htmlMinify.js +115 -0
  10. package/dist/cjs/plugins/manifest.js +52 -0
  11. package/dist/cjs/plugins/postcss.js +162 -0
  12. package/dist/cjs/plugins/rscConfig.js +159 -0
  13. package/dist/cjs/plugins/rsdoctor.js +64 -0
  14. package/dist/cjs/plugins/runtimeChunk.js +55 -0
  15. package/dist/cjs/shared/devServer.js +87 -0
  16. package/dist/cjs/shared/getCssSupport.js +121 -0
  17. package/dist/cjs/shared/manifest.js +46 -0
  18. package/dist/cjs/shared/parseCommonConfig.js +210 -0
  19. package/dist/cjs/shared/rsc/rsc-server-entry-loader.js +41 -0
  20. package/dist/cjs/shared/rsc/rscClientBrowserFallback.js +64 -0
  21. package/dist/cjs/shared/rsc/rscEmptyModule.js +36 -0
  22. package/dist/cjs/shared/utils.js +115 -0
  23. package/dist/cjs/types.js +18 -0
  24. package/dist/esm/createBuilder.mjs +57 -0
  25. package/dist/esm/index.mjs +3 -0
  26. package/dist/esm/plugins/devtools.mjs +13 -0
  27. package/dist/esm/plugins/emitRouteFile.mjs +28 -0
  28. package/dist/esm/plugins/environmentDefaults.mjs +66 -0
  29. package/dist/esm/plugins/globalVars.mjs +21 -0
  30. package/dist/esm/plugins/htmlMinify.mjs +81 -0
  31. package/dist/esm/plugins/manifest.mjs +18 -0
  32. package/dist/esm/plugins/postcss.mjs +115 -0
  33. package/dist/esm/plugins/rscConfig.mjs +112 -0
  34. package/dist/esm/plugins/rsdoctor.mjs +30 -0
  35. package/dist/esm/plugins/runtimeChunk.mjs +21 -0
  36. package/dist/esm/shared/devServer.mjs +53 -0
  37. package/dist/esm/shared/getCssSupport.mjs +77 -0
  38. package/dist/esm/shared/manifest.mjs +12 -0
  39. package/dist/esm/shared/parseCommonConfig.mjs +173 -0
  40. package/dist/esm/shared/rsc/rsc-server-entry-loader.mjs +7 -0
  41. package/dist/esm/shared/rsc/rscClientBrowserFallback.mjs +20 -0
  42. package/dist/esm/shared/rsc/rscEmptyModule.mjs +2 -0
  43. package/dist/esm/shared/utils.mjs +53 -0
  44. package/dist/esm/types.mjs +0 -0
  45. package/dist/esm-node/createBuilder.mjs +58 -0
  46. package/dist/esm-node/index.mjs +4 -0
  47. package/dist/esm-node/plugins/devtools.mjs +14 -0
  48. package/dist/esm-node/plugins/emitRouteFile.mjs +29 -0
  49. package/dist/esm-node/plugins/environmentDefaults.mjs +67 -0
  50. package/dist/esm-node/plugins/globalVars.mjs +22 -0
  51. package/dist/esm-node/plugins/htmlMinify.mjs +82 -0
  52. package/dist/esm-node/plugins/manifest.mjs +19 -0
  53. package/dist/esm-node/plugins/postcss.mjs +116 -0
  54. package/dist/esm-node/plugins/rscConfig.mjs +117 -0
  55. package/dist/esm-node/plugins/rsdoctor.mjs +31 -0
  56. package/dist/esm-node/plugins/runtimeChunk.mjs +22 -0
  57. package/dist/esm-node/shared/devServer.mjs +54 -0
  58. package/dist/esm-node/shared/getCssSupport.mjs +78 -0
  59. package/dist/esm-node/shared/manifest.mjs +13 -0
  60. package/dist/esm-node/shared/parseCommonConfig.mjs +174 -0
  61. package/dist/esm-node/shared/rsc/rsc-server-entry-loader.mjs +8 -0
  62. package/dist/esm-node/shared/rsc/rscClientBrowserFallback.mjs +25 -0
  63. package/dist/esm-node/shared/rsc/rscEmptyModule.mjs +3 -0
  64. package/dist/esm-node/shared/utils.mjs +54 -0
  65. package/dist/esm-node/types.mjs +1 -0
  66. package/dist/types/createBuilder.d.ts +8 -0
  67. package/dist/types/index.d.ts +8 -0
  68. package/dist/types/plugins/devtools.d.ts +4 -0
  69. package/dist/types/plugins/emitRouteFile.d.ts +6 -0
  70. package/dist/types/plugins/environmentDefaults.d.ts +3 -0
  71. package/dist/types/plugins/globalVars.d.ts +3 -0
  72. package/dist/types/plugins/htmlMinify.d.ts +2 -0
  73. package/dist/types/plugins/manifest.d.ts +2 -0
  74. package/dist/types/plugins/postcss.d.ts +6 -0
  75. package/dist/types/plugins/rscConfig.d.ts +18 -0
  76. package/dist/types/plugins/rsdoctor.d.ts +3 -0
  77. package/dist/types/plugins/runtimeChunk.d.ts +2 -0
  78. package/dist/types/shared/devServer.d.ts +6 -0
  79. package/dist/types/shared/getCssSupport.d.ts +1 -0
  80. package/dist/types/shared/manifest.d.ts +2 -0
  81. package/dist/types/shared/parseCommonConfig.d.ts +9 -0
  82. package/dist/types/shared/rsc/rsc-server-entry-loader.d.ts +5 -0
  83. package/dist/types/shared/rsc/rscClientBrowserFallback.d.ts +2 -0
  84. package/dist/types/shared/rsc/rscEmptyModule.d.ts +2 -0
  85. package/dist/types/shared/utils.d.ts +12 -0
  86. package/dist/types/types.d.ts +287 -0
  87. package/package.json +88 -0
@@ -0,0 +1,173 @@
1
+ import { mergeRsbuildConfig } from "@rsbuild/core";
2
+ import { pluginCssMinimizer } from "@rsbuild/plugin-css-minimizer";
3
+ import { pluginLess } from "@rsbuild/plugin-less";
4
+ import { pluginReact } from "@rsbuild/plugin-react";
5
+ import { pluginSass } from "@rsbuild/plugin-sass";
6
+ import { pluginDevtool } from "../plugins/devtools.mjs";
7
+ import { pluginEmitRouteFile } from "../plugins/emitRouteFile.mjs";
8
+ import { pluginEnvironmentDefaults } from "../plugins/environmentDefaults.mjs";
9
+ import { pluginGlobalVars } from "../plugins/globalVars.mjs";
10
+ import { pluginHtmlMinifierTerser } from "../plugins/htmlMinify.mjs";
11
+ import { pluginRuntimeChunk } from "../plugins/runtimeChunk.mjs";
12
+ import { transformToRsbuildServerOptions } from "./devServer.mjs";
13
+ import { NODE_MODULES_REGEX } from "./utils.mjs";
14
+ const CSS_MODULES_REGEX = /\.modules?\.\w+$/i;
15
+ const GLOBAL_CSS_REGEX = /\.global\.\w+$/;
16
+ const isLooseCssModules = (path)=>{
17
+ if (NODE_MODULES_REGEX.test(path)) return CSS_MODULES_REGEX.test(path);
18
+ return !GLOBAL_CSS_REGEX.test(path);
19
+ };
20
+ function removeUndefinedKey(obj) {
21
+ Object.keys(obj).forEach((key)=>{
22
+ if (void 0 === obj[key]) delete obj[key];
23
+ });
24
+ return obj;
25
+ }
26
+ async function parseCommonConfig(builderConfig, options) {
27
+ const frameworkConfigPath = options?.frameworkConfigPath;
28
+ const { plugins: [...plugins] = [], splitChunks, performance: { rsdoctor: rsdoctorConfig, ...performanceConfig } = {}, output: { module = false, enableCssModuleTSDeclaration, disableCssModuleExtension, disableTsChecker, disableSvgr, svgDefaultExport, assetsRetry, enableAssetManifest, sourceMap, convertToRem, polyfill, dataUriLimit = 10000, distPath = {}, ...outputConfig } = {}, html: { outputStructure, appIcon, ...htmlConfig } = {}, source: { alias, globalVars, transformImport, ...sourceConfig } = {}, dev = {}, server = {}, security: { checkSyntax, sri, ...securityConfig } = {}, tools: { devServer, tsChecker, minifyCss, less, sass, htmlPlugin, autoprefixer, ...toolsConfig } = {}, environments = {}, resolve = {} } = builderConfig;
29
+ let combinedAlias;
30
+ if (alias || resolve.alias) combinedAlias = [].concat(alias ?? []).concat(resolve.alias ?? []);
31
+ const rsbuildConfig = {
32
+ plugins,
33
+ splitChunks,
34
+ output: {
35
+ polyfill: 'ua' === polyfill ? 'off' : polyfill,
36
+ dataUriLimit,
37
+ sourceMap,
38
+ module,
39
+ ...outputConfig
40
+ },
41
+ resolve: {
42
+ ...resolve,
43
+ alias: combinedAlias
44
+ },
45
+ source: sourceConfig,
46
+ performance: performanceConfig,
47
+ html: htmlConfig,
48
+ tools: toolsConfig,
49
+ security: securityConfig,
50
+ environments
51
+ };
52
+ rsbuildConfig.tools.htmlPlugin = htmlPlugin;
53
+ rsbuildConfig.tools.lightningcssLoader ??= false;
54
+ const { html = {}, output = {}, source = {} } = rsbuildConfig;
55
+ source.transformImport = false === transformImport ? ()=>[] : transformImport;
56
+ if (!source.decorators) source.decorators = {
57
+ version: 'legacy'
58
+ };
59
+ output.charset ??= 'ascii';
60
+ if ('boolean' != typeof output.sourceMap) {
61
+ output.sourceMap ||= {};
62
+ output.sourceMap.css ??= 'production' !== process.env.NODE_ENV;
63
+ }
64
+ const { server: _server, worker, ...rsbuildDistPath } = distPath;
65
+ output.distPath = rsbuildDistPath;
66
+ output.distPath.html ??= 'html';
67
+ output.polyfill ??= 'entry';
68
+ if (disableCssModuleExtension) {
69
+ output.cssModules ||= {};
70
+ output.cssModules.auto ??= isLooseCssModules;
71
+ }
72
+ const extraConfig = {};
73
+ extraConfig.html ||= {};
74
+ extraConfig.html.outputStructure = outputStructure ?? 'nested';
75
+ html.title ??= '';
76
+ html.appIcon = appIcon;
77
+ extraConfig.tools ??= {};
78
+ if (false !== htmlPlugin) extraConfig.tools.htmlPlugin = (config)=>{
79
+ if ('function' == typeof config.templateParameters) {
80
+ const originFn = config.templateParameters;
81
+ config.templateParameters = (...args)=>{
82
+ const res = originFn(...args);
83
+ return {
84
+ title: config.title,
85
+ meta: void 0,
86
+ ...res
87
+ };
88
+ };
89
+ }
90
+ };
91
+ if (!dev.lazyCompilation) dev.lazyCompilation = false;
92
+ const { rsbuildDev, rsbuildServer } = transformToRsbuildServerOptions(dev || {}, devServer || {}, server || {});
93
+ rsbuildConfig.server = removeUndefinedKey(rsbuildServer);
94
+ rsbuildConfig.dev = removeUndefinedKey(rsbuildDev);
95
+ rsbuildConfig.html = html;
96
+ rsbuildConfig.output = output;
97
+ const rsbuildPlugins = [
98
+ pluginGlobalVars(globalVars),
99
+ pluginDevtool({
100
+ sourceMap
101
+ }),
102
+ pluginEmitRouteFile(),
103
+ pluginSass({
104
+ sassLoaderOptions: sass
105
+ }),
106
+ pluginLess({
107
+ lessLoaderOptions: less
108
+ }),
109
+ pluginEnvironmentDefaults(distPath),
110
+ pluginHtmlMinifierTerser()
111
+ ];
112
+ if (checkSyntax) {
113
+ const { pluginCheckSyntax } = await import("@rsbuild/plugin-check-syntax");
114
+ rsbuildPlugins.push(pluginCheckSyntax('boolean' == typeof checkSyntax ? {} : checkSyntax));
115
+ }
116
+ if (!disableTsChecker) {
117
+ const { pluginTypeCheck } = await import("@rsbuild/plugin-type-check");
118
+ rsbuildPlugins.push(pluginTypeCheck({
119
+ tsCheckerOptions: tsChecker
120
+ }));
121
+ }
122
+ if (convertToRem) {
123
+ const { pluginRem } = await import("@rsbuild/plugin-rem");
124
+ rsbuildPlugins.push(pluginRem('boolean' == typeof convertToRem ? {} : convertToRem));
125
+ }
126
+ if (enableCssModuleTSDeclaration) {
127
+ const { pluginTypedCSSModules } = await import("@rsbuild/plugin-typed-css-modules");
128
+ rsbuildPlugins.push(pluginTypedCSSModules());
129
+ }
130
+ rsbuildPlugins.push(pluginRuntimeChunk(builderConfig.output?.disableInlineRuntimeChunk));
131
+ const { sourceBuild } = builderConfig.experiments || {};
132
+ if (sourceBuild) {
133
+ const { pluginSourceBuild } = await import("@rsbuild/plugin-source-build");
134
+ rsbuildPlugins.push(pluginSourceBuild(true === sourceBuild ? {} : sourceBuild));
135
+ }
136
+ rsbuildPlugins.push(pluginReact());
137
+ if (!disableSvgr) {
138
+ const { pluginSvgr } = await import("@rsbuild/plugin-svgr");
139
+ rsbuildPlugins.push(pluginSvgr({
140
+ mixedImport: true,
141
+ svgrOptions: {
142
+ exportType: 'component' === svgDefaultExport ? 'default' : 'named'
143
+ }
144
+ }));
145
+ }
146
+ if (assetsRetry) {
147
+ const { pluginAssetsRetry } = await import("@rsbuild/plugin-assets-retry");
148
+ rsbuildPlugins.push(pluginAssetsRetry(assetsRetry));
149
+ }
150
+ if (frameworkConfigPath && false !== performanceConfig.buildCache) {
151
+ const buildCache = 'object' == typeof performanceConfig.buildCache ? performanceConfig.buildCache : {};
152
+ rsbuildConfig.performance.buildCache = {
153
+ ...buildCache,
154
+ buildDependencies: [
155
+ frameworkConfigPath,
156
+ ...buildCache.buildDependencies || []
157
+ ]
158
+ };
159
+ }
160
+ rsbuildPlugins.push(pluginCssMinimizer({
161
+ pluginOptions: minifyCss
162
+ }));
163
+ if (enableAssetManifest) {
164
+ const { pluginManifest } = await import("../plugins/manifest.mjs");
165
+ rsbuildPlugins.push(pluginManifest());
166
+ }
167
+ return {
168
+ rsbuildConfig: mergeRsbuildConfig(rsbuildConfig, extraConfig),
169
+ rsbuildPlugins,
170
+ rsdoctorConfig
171
+ };
172
+ }
173
+ export { isLooseCssModules, parseCommonConfig };
@@ -0,0 +1,7 @@
1
+ function rscServerEntryLoader(source) {
2
+ this.cacheable(true);
3
+ const hasServerEntryDirective = source.includes("'use server-entry'") || source.includes('"use server-entry"') || source.includes('`use server-entry`');
4
+ if (hasServerEntryDirective) return source;
5
+ return `'use server-entry';\n${source}`;
6
+ }
7
+ export default rscServerEntryLoader;
@@ -0,0 +1,20 @@
1
+ import path from "path";
2
+ function rscClientBrowserFallbackPlugin() {
3
+ return {
4
+ name: 'builder:rsc-client-browser-fallback',
5
+ setup (api) {
6
+ let emptyModulePath;
7
+ try {
8
+ emptyModulePath = require.resolve('./rscEmptyModule');
9
+ } catch {
10
+ emptyModulePath = path.resolve(__dirname, 'rscEmptyModule');
11
+ }
12
+ api.modifyRspackConfig((config)=>{
13
+ config.resolve ??= {};
14
+ config.resolve.fallback ??= {};
15
+ config.resolve.fallback['react-server-dom-rspack/client.browser'] = emptyModulePath;
16
+ });
17
+ }
18
+ };
19
+ }
20
+ export { rscClientBrowserFallbackPlugin };
@@ -0,0 +1,2 @@
1
+ const rscEmptyModule = {};
2
+ export default rscEmptyModule;
@@ -0,0 +1,53 @@
1
+ import browserslist from "browserslist";
2
+ const RUNTIME_CHUNK_NAME = 'builder-runtime';
3
+ const RUNTIME_CHUNK_REGEX = new RegExp(`${RUNTIME_CHUNK_NAME}([.].+)?\\.js$`);
4
+ const SERVICE_WORKER_ENVIRONMENT_NAME = 'workerSSR';
5
+ const NODE_MODULES_REGEX = /[\\/]node_modules[\\/]/;
6
+ const castArray = (arr)=>{
7
+ if (void 0 === arr) return [];
8
+ return Array.isArray(arr) ? arr : [
9
+ arr
10
+ ];
11
+ };
12
+ const browsersListCache = new Map();
13
+ async function getBrowserslist(path) {
14
+ const env = process.env.NODE_ENV;
15
+ const cacheKey = `${path}${env}`;
16
+ if (browsersListCache.has(cacheKey)) return browsersListCache.get(cacheKey);
17
+ const result = browserslist.loadConfig({
18
+ path,
19
+ env
20
+ });
21
+ if (result) {
22
+ browsersListCache.set(cacheKey, result);
23
+ return result;
24
+ }
25
+ return null;
26
+ }
27
+ const isHtmlDisabled = (config, target)=>{
28
+ const { htmlPlugin } = config.tools;
29
+ return false === htmlPlugin || Array.isArray(htmlPlugin) && htmlPlugin.includes(false) || 'web' !== target;
30
+ };
31
+ const DEFAULT_WEB_BROWSERSLIST = [
32
+ 'chrome >= 87',
33
+ 'edge >= 88',
34
+ 'firefox >= 78',
35
+ 'safari >= 14'
36
+ ];
37
+ const DEFAULT_BROWSERSLIST = {
38
+ web: DEFAULT_WEB_BROWSERSLIST,
39
+ node: [
40
+ 'node >= 16'
41
+ ],
42
+ 'web-worker': DEFAULT_WEB_BROWSERSLIST
43
+ };
44
+ async function getBrowserslistWithDefault(path, config, target) {
45
+ const { overrideBrowserslist: overrides } = config?.output || {};
46
+ if ('web' === target || 'web-worker' === target) {
47
+ if (overrides) return overrides;
48
+ const browserslistrc = await getBrowserslist(path);
49
+ if (browserslistrc) return browserslistrc;
50
+ }
51
+ return DEFAULT_BROWSERSLIST[target];
52
+ }
53
+ export { NODE_MODULES_REGEX, RUNTIME_CHUNK_NAME, RUNTIME_CHUNK_REGEX, SERVICE_WORKER_ENVIRONMENT_NAME, castArray, getBrowserslistWithDefault, isHtmlDisabled };
File without changes
@@ -0,0 +1,58 @@
1
+ import "node:module";
2
+ import { createRsbuild } from "@rsbuild/core";
3
+ import { getRscPlugins } from "./plugins/rscConfig.mjs";
4
+ import { pluginRsdoctor } from "./plugins/rsdoctor.mjs";
5
+ import { parseCommonConfig } from "./shared/parseCommonConfig.mjs";
6
+ import { rscClientBrowserFallbackPlugin } from "./shared/rsc/rscClientBrowserFallback.mjs";
7
+ async function parseConfig(builderConfig, options) {
8
+ builderConfig.performance ??= {};
9
+ builderConfig.performance.buildCache ??= true;
10
+ const { rsbuildConfig, rsbuildPlugins, rsdoctorConfig } = await parseCommonConfig(builderConfig, options);
11
+ const { sri } = builderConfig.security || {};
12
+ if (sri) if (true === sri) rsbuildConfig.security.sri = {
13
+ enable: 'auto'
14
+ };
15
+ else {
16
+ const algorithm = Array.isArray(sri.hashFuncNames) ? sri.hashFuncNames[0] : void 0;
17
+ rsbuildConfig.security.sri = {
18
+ enable: sri.enabled,
19
+ algorithm
20
+ };
21
+ }
22
+ if (false === Boolean(rsbuildConfig.tools.lightningcssLoader)) {
23
+ const { pluginPostcss } = await import("./plugins/postcss.mjs");
24
+ rsbuildPlugins.push(pluginPostcss({
25
+ autoprefixer: builderConfig.tools?.autoprefixer
26
+ }));
27
+ }
28
+ const enableRsc = builderConfig.server?.rsc ?? false;
29
+ if (enableRsc) {
30
+ const rscPlugins = await getRscPlugins(enableRsc, options.internalDirectory);
31
+ rsbuildPlugins.push(...rscPlugins);
32
+ } else rsbuildPlugins.push(rscClientBrowserFallbackPlugin());
33
+ const rsdoctorPlugin = pluginRsdoctor(rsdoctorConfig);
34
+ if (rsdoctorPlugin) rsbuildPlugins.push(rsdoctorPlugin);
35
+ return {
36
+ rsbuildConfig,
37
+ rsbuildPlugins
38
+ };
39
+ }
40
+ async function createRspackBuilder(options) {
41
+ const { cwd = process.cwd(), config, ...rest } = options;
42
+ const { rsbuildConfig, rsbuildPlugins } = await parseConfig(config, {
43
+ ...rest,
44
+ cwd
45
+ });
46
+ rsbuildConfig.plugins = [
47
+ ...rsbuildPlugins,
48
+ ...rsbuildConfig.plugins || []
49
+ ];
50
+ const rsbuild = await createRsbuild({
51
+ cwd,
52
+ rsbuildConfig
53
+ });
54
+ return {
55
+ ...rsbuild
56
+ };
57
+ }
58
+ export { createRspackBuilder, parseConfig };
@@ -0,0 +1,4 @@
1
+ import "node:module";
2
+ export { createRspackBuilder as createBuilder, parseConfig as parseRspackConfig } from "./createBuilder.mjs";
3
+ export { logger } from "@rsbuild/core";
4
+ export { RUNTIME_CHUNK_NAME, RUNTIME_CHUNK_REGEX, SERVICE_WORKER_ENVIRONMENT_NAME, castArray, isHtmlDisabled } from "./shared/utils.mjs";
@@ -0,0 +1,14 @@
1
+ import "node:module";
2
+ const pluginDevtool = (options)=>({
3
+ name: 'builder:devtool',
4
+ setup (api) {
5
+ const devtoolJs = 'boolean' == typeof options.sourceMap || options.sourceMap?.js !== void 0;
6
+ if (devtoolJs) return;
7
+ api.modifyBundlerChain((chain, { isProd, isServer })=>{
8
+ const prodDevTool = isServer ? 'source-map' : 'hidden-source-map';
9
+ const devtool = isProd ? prodDevTool : 'cheap-module-source-map';
10
+ chain.devtool(devtool);
11
+ });
12
+ }
13
+ });
14
+ export { pluginDevtool };
@@ -0,0 +1,29 @@
1
+ import "node:module";
2
+ import node_fs from "node:fs";
3
+ import { join } from "node:path";
4
+ async function isFileExists(file) {
5
+ return node_fs.promises.access(file, node_fs.constants.F_OK).then(()=>true).catch(()=>false);
6
+ }
7
+ const pluginEmitRouteFile = ()=>({
8
+ name: 'builder:emit-route-file',
9
+ setup (api) {
10
+ api.onBeforeStartDevServer(async ({ environments })=>{
11
+ const { fs, ROUTE_SPEC_FILE } = await import("@modern-js/utils");
12
+ const routeFilePath = join(api.context.distPath, ROUTE_SPEC_FILE);
13
+ const htmlPaths = Object.values(environments).reduce((prev, curr)=>({
14
+ ...prev,
15
+ ...curr.htmlPaths
16
+ }), {});
17
+ const routesInfo = Object.entries(htmlPaths).map(([entryName, filename], index)=>({
18
+ urlPath: 0 === index ? '/' : `/${entryName}`,
19
+ entryName,
20
+ entryPath: filename,
21
+ isSPA: true
22
+ }));
23
+ if (!await isFileExists(routeFilePath) && routesInfo.length) await fs.outputFile(routeFilePath, JSON.stringify({
24
+ routes: routesInfo
25
+ }, null, 2));
26
+ });
27
+ }
28
+ });
29
+ export { isFileExists, pluginEmitRouteFile };
@@ -0,0 +1,67 @@
1
+ import "node:module";
2
+ import { join } from "node:path";
3
+ import { SERVICE_WORKER_ENVIRONMENT_NAME, getBrowserslistWithDefault } from "../shared/utils.mjs";
4
+ const pluginEnvironmentDefaults = (distPath = {})=>({
5
+ name: 'builder:environment-defaults-plugin',
6
+ setup (api) {
7
+ api.modifyRsbuildConfig((config, { mergeRsbuildConfig })=>{
8
+ const compatConfig = {};
9
+ if (config.environments?.[SERVICE_WORKER_ENVIRONMENT_NAME]) {
10
+ compatConfig.environments ??= {};
11
+ compatConfig.environments[SERVICE_WORKER_ENVIRONMENT_NAME] = {
12
+ output: {
13
+ polyfill: 'off',
14
+ distPath: {
15
+ root: join(distPath.root || 'dist', distPath.worker || 'worker'),
16
+ js: '',
17
+ css: '',
18
+ jsAsync: '',
19
+ cssAsync: ''
20
+ },
21
+ filename: {
22
+ js: '[name].js'
23
+ }
24
+ }
25
+ };
26
+ }
27
+ if (config.environments?.server) {
28
+ compatConfig.environments ??= {};
29
+ compatConfig.environments.server = {
30
+ output: {
31
+ emitAssets: false,
32
+ distPath: {
33
+ root: join(distPath.root || 'dist', distPath.server || 'bundles'),
34
+ js: '',
35
+ css: '',
36
+ jsAsync: '',
37
+ cssAsync: ''
38
+ }
39
+ }
40
+ };
41
+ }
42
+ return compatConfig.environments ? mergeRsbuildConfig(compatConfig, config) : config;
43
+ });
44
+ api.modifyRsbuildConfig({
45
+ handler: (config)=>{
46
+ const environmentNameOrder = [
47
+ 'client',
48
+ 'server',
49
+ 'workerSSR'
50
+ ];
51
+ config.environments = Object.fromEntries(Object.entries(config.environments).sort((a1, a2)=>environmentNameOrder.includes(a1[0]) ? environmentNameOrder.indexOf(a1[0]) - environmentNameOrder.indexOf(a2[0]) : 1));
52
+ },
53
+ order: 'post'
54
+ });
55
+ api.modifyEnvironmentConfig(async (config, { name })=>{
56
+ config.output.overrideBrowserslist ??= await getBrowserslistWithDefault(api.context.rootPath, config, name === SERVICE_WORKER_ENVIRONMENT_NAME ? 'node' : config.output.target);
57
+ });
58
+ api.modifyBundlerChain(async (chain, { environment })=>{
59
+ const isServiceWorker = environment.name === SERVICE_WORKER_ENVIRONMENT_NAME;
60
+ if (isServiceWorker) chain.output.library({
61
+ ...chain.output.get('library') || {},
62
+ type: 'commonjs2'
63
+ });
64
+ });
65
+ }
66
+ });
67
+ export { pluginEnvironmentDefaults };
@@ -0,0 +1,22 @@
1
+ import "node:module";
2
+ import { applyOptionsChain } from "@modern-js/utils";
3
+ const pluginGlobalVars = (options)=>({
4
+ name: 'builder:global-vars',
5
+ setup (api) {
6
+ api.modifyBundlerChain((chain, { env, target, bundler })=>{
7
+ if (!options) return;
8
+ const globalVars = applyOptionsChain({}, options, {
9
+ env,
10
+ target
11
+ });
12
+ const serializedVars = {};
13
+ Object.entries(globalVars).forEach(([key, value])=>{
14
+ serializedVars[key] = JSON.stringify(value) ?? 'undefined';
15
+ });
16
+ chain.plugin('globalVars').use(bundler.DefinePlugin, [
17
+ serializedVars
18
+ ]);
19
+ });
20
+ }
21
+ });
22
+ export { pluginGlobalVars };
@@ -0,0 +1,82 @@
1
+ import "node:module";
2
+ import { merge } from "ts-deepmerge";
3
+ function applyRemoveConsole(options, config) {
4
+ const { removeConsole } = config.performance;
5
+ const compressOptions = 'boolean' == typeof options.compress ? {} : options.compress || {};
6
+ if (true === removeConsole) options.compress = {
7
+ ...compressOptions,
8
+ drop_console: true
9
+ };
10
+ else if (Array.isArray(removeConsole)) {
11
+ const pureFuncs = removeConsole.map((method)=>`console.${method}`);
12
+ options.compress = {
13
+ ...compressOptions,
14
+ pure_funcs: pureFuncs
15
+ };
16
+ }
17
+ return options;
18
+ }
19
+ function getTerserMinifyOptions(config) {
20
+ const options = {
21
+ mangle: {
22
+ safari10: true
23
+ },
24
+ format: {
25
+ ascii_only: 'ascii' === config.output.charset
26
+ }
27
+ };
28
+ if ('none' === config.output.legalComments) {
29
+ options.format ||= {};
30
+ options.format.comments = false;
31
+ }
32
+ const finalOptions = applyRemoveConsole(options, config);
33
+ return finalOptions;
34
+ }
35
+ function getMinifyOptions(config) {
36
+ const minifyJS = getTerserMinifyOptions(config);
37
+ return {
38
+ removeComments: false,
39
+ useShortDoctype: true,
40
+ keepClosingSlash: true,
41
+ collapseWhitespace: true,
42
+ removeRedundantAttributes: true,
43
+ removeScriptTypeAttributes: true,
44
+ removeStyleLinkTypeAttributes: true,
45
+ removeEmptyAttributes: true,
46
+ minifyJS,
47
+ minifyCSS: true,
48
+ minifyURLs: true
49
+ };
50
+ }
51
+ const pluginHtmlMinifierTerser = ()=>({
52
+ name: 'builder:plugin-html-minifier-terser',
53
+ setup (api) {
54
+ api.modifyBundlerChain(async (chain, { isProd, environment })=>{
55
+ const { output, tools: { htmlPlugin } } = environment.config;
56
+ const disableHtmlMinify = !isProd || false === output.minify || false === htmlPlugin;
57
+ const { minify } = await import("html-minifier-terser");
58
+ const pluginRecord = chain.plugins.entries();
59
+ const minifyOptions = getMinifyOptions(environment.config);
60
+ for (const id of Object.keys(pluginRecord)){
61
+ if (!id.startsWith('html-')) continue;
62
+ const values = pluginRecord[id].values();
63
+ const isHtmlRspackPlugin = values.some((item)=>{
64
+ const name = item?.name || item.constructor?.name;
65
+ return 'HtmlRspackPlugin' === name;
66
+ });
67
+ if (isHtmlRspackPlugin && !disableHtmlMinify) {
68
+ chain.plugin(id).tap((options)=>{
69
+ if (!options.length) return options;
70
+ const userMinifyOption = options[0].minify;
71
+ if (false === userMinifyOption) return options;
72
+ const minifyFn = (html)=>minify(html, userMinifyOption ? merge(minifyOptions, userMinifyOption) : minifyOptions);
73
+ options[0].minify = minifyFn;
74
+ return options;
75
+ });
76
+ continue;
77
+ }
78
+ }
79
+ });
80
+ }
81
+ });
82
+ export { pluginHtmlMinifierTerser };
@@ -0,0 +1,19 @@
1
+ import "node:module";
2
+ import { generateManifest } from "../shared/manifest.mjs";
3
+ const pluginManifest = ()=>({
4
+ name: 'builder:manifest',
5
+ setup (api) {
6
+ api.modifyBundlerChain(async (chain, { target, CHAIN_ID })=>{
7
+ const { RspackManifestPlugin } = await import("rspack-manifest-plugin");
8
+ const publicPath = chain.output.get('publicPath');
9
+ chain.plugin(CHAIN_ID.PLUGIN.MANIFEST).use(RspackManifestPlugin, [
10
+ {
11
+ fileName: 'web' === target ? 'asset-manifest.json' : `asset-manifest-${target}.json`,
12
+ publicPath,
13
+ generate: generateManifest
14
+ }
15
+ ]);
16
+ });
17
+ }
18
+ });
19
+ export { pluginManifest };