@modern-js/builder 2.2.0 → 2.4.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # @modern-js/builder
2
2
 
3
+ ## 2.4.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 014d06b: feat: reuse bundleAnalyzer plugin, support performance.bundleAnalyze config in rspack-provider
8
+
9
+ feat: 复用 bundleAnalyzer 插件,在 rspack-provider 中支持 performance.bundleAnalyze 配置项
10
+
11
+ - 91db54e: feat: use 'devtool: source-map' for ssr webpack bundle
12
+ feat: 使用 'devtool: source-map' 作为 ssr 构建时的默认配置
13
+ - Updated dependencies [6f83037]
14
+ - Updated dependencies [014d06b]
15
+ - Updated dependencies [98a2733]
16
+ - Updated dependencies [a5572b8]
17
+ - Updated dependencies [a914be8]
18
+ - Updated dependencies [8c2db5f]
19
+ - @modern-js/builder-shared@2.4.0
20
+ - @modern-js/utils@2.4.0
21
+
22
+ ## 2.3.0
23
+
24
+ ### Minor Changes
25
+
26
+ - f9a26fe: fix(@modern-js/builder-shared): openBrowser add openChrome.applescript script
27
+
28
+ fix(@modern-js/builder-shared): openBrowser 添加 openChrome.applescript 脚本
29
+
30
+ ### Patch Changes
31
+
32
+ - 7cd8185: chore: reuse splitChunks plugin between rspack-provider and webpack-provider
33
+
34
+ chore: 在 rspack-provider 和 webpack-provider 间复用 splitChunks plugin
35
+
36
+ - Updated dependencies [fd5a3ed]
37
+ - Updated dependencies [67ba34a]
38
+ - Updated dependencies [2ad9fdf]
39
+ - Updated dependencies [f9a26fe]
40
+ - Updated dependencies [6ca1c0b]
41
+ - Updated dependencies [89b6739]
42
+ - @modern-js/utils@2.3.0
43
+ - @modern-js/builder-shared@2.3.0
44
+
3
45
  ## 2.2.0
4
46
 
5
47
  ### Patch Changes
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  </a>
11
11
  </p>
12
12
  <p align="center">
13
- A Universal Build Engine for Modern Web Development
13
+ A Build Engine for web development.
14
14
  </p>
15
15
 
16
16
  # @modern-js/builder
@@ -0,0 +1,2 @@
1
+ import { DefaultBuilderPlugin } from '@modern-js/builder-shared';
2
+ export declare function builderPluginBundleAnalyzer(): DefaultBuilderPlugin;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.builderPluginBundleAnalyzer = void 0;
27
+ function builderPluginBundleAnalyzer() {
28
+ return {
29
+ name: 'builder-plugin-bundle-analyzer',
30
+ setup(api) {
31
+ api.modifyBundlerChain(async (chain, { CHAIN_ID, target }) => {
32
+ const config = api.getNormalizedConfig();
33
+ // There are two ways to open the bundle analyzer:
34
+ // 1. Set environment variable `BUNDLE_ANALYZE`
35
+ // 2. Set performance.bundleAnalyze config
36
+ if (!process.env.BUNDLE_ANALYZE && !config.performance.bundleAnalyze) {
37
+ return;
38
+ }
39
+ const { default: BundleAnalyzer } = await Promise.resolve().then(() => __importStar(require('@modern-js/builder-shared/webpack-bundle-analyzer')));
40
+ chain
41
+ .plugin(CHAIN_ID.PLUGIN.BUNDLE_ANALYZER)
42
+ .use(BundleAnalyzer.BundleAnalyzerPlugin, [
43
+ {
44
+ analyzerMode: 'static',
45
+ openAnalyzer: false,
46
+ reportFilename: `report-${target}.html`,
47
+ ...(config.performance.bundleAnalyze || {}),
48
+ },
49
+ ]);
50
+ });
51
+ },
52
+ };
53
+ }
54
+ exports.builderPluginBundleAnalyzer = builderPluginBundleAnalyzer;
@@ -5,15 +5,16 @@ const builder_shared_1 = require("@modern-js/builder-shared");
5
5
  const builderPluginDevtool = () => ({
6
6
  name: 'builder-plugin-devtool',
7
7
  setup(api) {
8
- api.modifyBundlerChain((chain, { isProd }) => {
8
+ api.modifyBundlerChain((chain, { isProd, isServer }) => {
9
9
  const config = api.getNormalizedConfig();
10
10
  if (!(0, builder_shared_1.isUseJsSourceMap)(config)) {
11
11
  chain.devtool(false);
12
12
  }
13
13
  else {
14
+ const prodDevTool = isServer ? 'source-map' : 'hidden-source-map';
14
15
  const devtool = isProd
15
16
  ? // hide the source map URL in production to avoid Chrome warning
16
- 'hidden-source-map'
17
+ prodDevTool
17
18
  : 'cheap-module-source-map';
18
19
  chain.devtool(devtool);
19
20
  }
@@ -8,4 +8,6 @@ export declare const plugins: {
8
8
  cache: () => Promise<import("@modern-js/builder-shared").DefaultBuilderPlugin>;
9
9
  yaml: () => Promise<import("@modern-js/builder-shared").DefaultBuilderPlugin>;
10
10
  toml: () => Promise<import("@modern-js/builder-shared").DefaultBuilderPlugin>;
11
+ splitChunks: () => Promise<import("@modern-js/builder-shared").DefaultBuilderPlugin>;
12
+ bundleAnalyzer: () => Promise<import("@modern-js/builder-shared").DefaultBuilderPlugin>;
11
13
  };
@@ -34,4 +34,6 @@ exports.plugins = {
34
34
  cache: () => Promise.resolve().then(() => __importStar(require('./cache'))).then(m => m.builderPluginCache()),
35
35
  yaml: () => Promise.resolve().then(() => __importStar(require('./yaml'))).then(m => m.builderPluginYaml()),
36
36
  toml: () => Promise.resolve().then(() => __importStar(require('./toml'))).then(m => m.builderPluginToml()),
37
+ splitChunks: () => Promise.resolve().then(() => __importStar(require('./splitChunks'))).then(m => m.builderPluginSplitChunks()),
38
+ bundleAnalyzer: () => Promise.resolve().then(() => __importStar(require('./bundleAnalyzer'))).then(m => m.builderPluginBundleAnalyzer()),
37
39
  };
@@ -0,0 +1,2 @@
1
+ import { DefaultBuilderPlugin } from '@modern-js/builder-shared';
2
+ export declare function builderPluginSplitChunks(): DefaultBuilderPlugin;
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.builderPluginSplitChunks = void 0;
30
+ const assert_1 = __importDefault(require("assert"));
31
+ const builder_shared_1 = require("@modern-js/builder-shared");
32
+ function getUserDefinedCacheGroups(forceSplitting) {
33
+ const cacheGroups = {};
34
+ forceSplitting.forEach((reg, index) => {
35
+ const key = `force-split-${index}`;
36
+ cacheGroups[key] = {
37
+ test: reg,
38
+ name: key,
39
+ chunks: 'all',
40
+ // Ignore minimum size, minimum chunks and maximum requests and always create chunks for user defined cache group.
41
+ enforce: true,
42
+ };
43
+ });
44
+ return cacheGroups;
45
+ }
46
+ async function splitByExperience(ctx) {
47
+ const { isPackageInstalled } = await Promise.resolve().then(() => __importStar(require('@modern-js/utils')));
48
+ const { override, polyfill, rootPath, defaultConfig, userDefinedCacheGroups, } = ctx;
49
+ const experienceCacheGroup = {};
50
+ const packageRegExps = {
51
+ react: /[\\/]react|react-dom[\\/]/,
52
+ router: /[\\/]react-router|react-router-dom|history[\\/]/,
53
+ lodash: /[\\/]lodash|lodash-es[\\/]/,
54
+ };
55
+ // Detect if the package is installed in current project
56
+ // If installed, add the package to cache group
57
+ if (isPackageInstalled('antd', rootPath)) {
58
+ packageRegExps.antd = /[\\/]antd[\\/]/;
59
+ }
60
+ if (isPackageInstalled('@arco-design/web-react', rootPath)) {
61
+ packageRegExps.arco = /[\\/]arco-design[\\/]/;
62
+ }
63
+ if (isPackageInstalled('@douyinfe/semi-ui', rootPath)) {
64
+ packageRegExps.semi = /[\\/]semi-ui[\\/]/;
65
+ }
66
+ if (polyfill === 'entry' || polyfill === 'usage') {
67
+ packageRegExps.polyfill = /[\\/]core-js|@babel\/runtime[\\/]/;
68
+ }
69
+ Object.entries(packageRegExps).forEach(([name, test]) => {
70
+ const key = `lib-${name}`;
71
+ experienceCacheGroup[key] = {
72
+ test,
73
+ priority: 0,
74
+ name: key,
75
+ reuseExistingChunk: true,
76
+ };
77
+ });
78
+ (0, assert_1.default)(defaultConfig !== false);
79
+ (0, assert_1.default)(override !== false);
80
+ return {
81
+ ...defaultConfig,
82
+ ...override,
83
+ cacheGroups: {
84
+ ...defaultConfig.cacheGroups,
85
+ ...experienceCacheGroup,
86
+ ...userDefinedCacheGroups,
87
+ ...override.cacheGroups,
88
+ },
89
+ };
90
+ }
91
+ function splitByModule(ctx) {
92
+ const { override, userDefinedCacheGroups, defaultConfig } = ctx;
93
+ (0, assert_1.default)(defaultConfig !== false);
94
+ (0, assert_1.default)(override !== false);
95
+ return {
96
+ ...defaultConfig,
97
+ minSize: 0,
98
+ maxInitialRequests: Infinity,
99
+ ...override,
100
+ cacheGroups: {
101
+ ...defaultConfig.cacheGroups,
102
+ ...userDefinedCacheGroups,
103
+ // Core group
104
+ vendors: {
105
+ priority: -10,
106
+ test: /[\\/]node_modules[\\/]/,
107
+ // todo: not support in rspack
108
+ name(module) {
109
+ return (0, builder_shared_1.getPackageNameFromModulePath)(module.context);
110
+ },
111
+ },
112
+ ...override.cacheGroups,
113
+ },
114
+ };
115
+ }
116
+ function splitBySize(ctx) {
117
+ var _a, _b;
118
+ const { override, userDefinedCacheGroups, defaultConfig, builderConfig } = ctx;
119
+ (0, assert_1.default)(defaultConfig !== false);
120
+ (0, assert_1.default)(override !== false);
121
+ (0, assert_1.default)(builderConfig.strategy === 'split-by-size');
122
+ return {
123
+ ...defaultConfig,
124
+ minSize: (_a = builderConfig.minSize) !== null && _a !== void 0 ? _a : 0,
125
+ maxSize: (_b = builderConfig.maxSize) !== null && _b !== void 0 ? _b : Infinity,
126
+ ...override,
127
+ cacheGroups: {
128
+ ...defaultConfig.cacheGroups,
129
+ ...userDefinedCacheGroups,
130
+ ...override.cacheGroups,
131
+ },
132
+ };
133
+ }
134
+ function splitCustom(ctx) {
135
+ const { override, userDefinedCacheGroups, defaultConfig } = ctx;
136
+ (0, assert_1.default)(defaultConfig !== false);
137
+ (0, assert_1.default)(override !== false);
138
+ return {
139
+ ...defaultConfig,
140
+ ...override,
141
+ cacheGroups: {
142
+ ...defaultConfig.cacheGroups,
143
+ ...userDefinedCacheGroups,
144
+ ...override.cacheGroups,
145
+ },
146
+ };
147
+ }
148
+ function allInOne(_ctx) {
149
+ // Set false to avoid chunk split.
150
+ return false;
151
+ }
152
+ // Ignore user defined cache group to get single vendor chunk.
153
+ function singleVendor(ctx) {
154
+ const { override, defaultConfig } = ctx;
155
+ (0, assert_1.default)(defaultConfig !== false);
156
+ (0, assert_1.default)(override !== false);
157
+ return {
158
+ ...defaultConfig,
159
+ ...override,
160
+ cacheGroups: {
161
+ ...defaultConfig.cacheGroups,
162
+ ...override.cacheGroups,
163
+ },
164
+ };
165
+ }
166
+ const SPLIT_STRATEGY_DISPATCHER = {
167
+ 'split-by-experience': splitByExperience,
168
+ 'split-by-module': splitByModule,
169
+ 'split-by-size': splitBySize,
170
+ custom: splitCustom,
171
+ 'all-in-one': allInOne,
172
+ 'single-vendor': singleVendor,
173
+ };
174
+ function builderPluginSplitChunks() {
175
+ return {
176
+ name: 'builder-plugin-split-chunks',
177
+ setup(api) {
178
+ api.modifyBundlerChain(async (chain, { isServer, isWebWorker }) => {
179
+ var _a;
180
+ if (isServer || isWebWorker) {
181
+ chain.optimization.splitChunks(false);
182
+ // web worker does not support dynamic imports, dynamicImportMode need set to eager
183
+ if (isWebWorker) {
184
+ // todo: not support in rspack
185
+ // @ts-expect-error
186
+ chain.module.parser.merge({
187
+ javascript: {
188
+ dynamicImportMode: 'eager',
189
+ },
190
+ });
191
+ }
192
+ return;
193
+ }
194
+ const config = api.getNormalizedConfig();
195
+ const defaultConfig = {
196
+ // Optimize both `initial` and `async` chunks
197
+ chunks: 'all',
198
+ // When chunk size >= 50000 bytes, split it into separate chunk
199
+ enforceSizeThreshold: 50000,
200
+ cacheGroups: {},
201
+ };
202
+ const { chunkSplit } = config.performance;
203
+ let userDefinedCacheGroups = {};
204
+ if (chunkSplit.forceSplitting) {
205
+ userDefinedCacheGroups = getUserDefinedCacheGroups(chunkSplit.forceSplitting);
206
+ }
207
+ // Patch the override config difference between the `custom` strategy and other strategy.
208
+ const override = chunkSplit.strategy === 'custom'
209
+ ? // `chunkSplit.splitChunks` compat for Eden
210
+ (_a = chunkSplit.splitChunks) !== null && _a !== void 0 ? _a : chunkSplit.override
211
+ : chunkSplit.override;
212
+ // Apply different strategy
213
+ const splitChunksOptions = await SPLIT_STRATEGY_DISPATCHER[chunkSplit.strategy]({
214
+ defaultConfig,
215
+ override: override || {},
216
+ userDefinedCacheGroups,
217
+ builderConfig: chunkSplit,
218
+ rootPath: api.context.rootPath,
219
+ polyfill: config.output.polyfill,
220
+ });
221
+ chain.optimization.splitChunks(splitChunksOptions);
222
+ // should not extract runtime chunk when strategy is `all-in-one`
223
+ if (chunkSplit.strategy !== 'all-in-one') {
224
+ chain.optimization.runtimeChunk({
225
+ name: builder_shared_1.RUNTIME_CHUNK_NAME,
226
+ });
227
+ }
228
+ });
229
+ },
230
+ };
231
+ }
232
+ exports.builderPluginSplitChunks = builderPluginSplitChunks;
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "engines": {
15
15
  "node": ">=14.0.0"
16
16
  },
17
- "version": "2.2.0",
17
+ "version": "2.4.0",
18
18
  "jsnext:source": "./src/index.ts",
19
19
  "types": "./dist/index.d.ts",
20
20
  "main": "./dist/index.js",
@@ -27,8 +27,8 @@
27
27
  }
28
28
  },
29
29
  "dependencies": {
30
- "@modern-js/builder-shared": "2.2.0",
31
- "@modern-js/utils": "2.2.0"
30
+ "@modern-js/builder-shared": "2.4.0",
31
+ "@modern-js/utils": "2.4.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@babel/core": "7.18.0",
@@ -36,7 +36,7 @@
36
36
  "@types/babel__preset-env": "^7.9.2",
37
37
  "@types/node": "^14",
38
38
  "typescript": "^4",
39
- "@scripts/vitest-config": "2.2.0"
39
+ "@scripts/vitest-config": "2.4.0"
40
40
  },
41
41
  "publishConfig": {
42
42
  "registry": "https://registry.npmjs.org/",