@mui/internal-bundle-size-checker 1.0.9-canary.5 → 1.0.9-canary.51

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.
@@ -1,267 +0,0 @@
1
- import { promisify } from 'util';
2
- import path from 'path';
3
- import webpackCallbackBased from 'webpack';
4
- import CompressionPlugin from 'compression-webpack-plugin';
5
- import TerserPlugin from 'terser-webpack-plugin';
6
- import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
7
- import { createRequire } from 'node:module';
8
-
9
- /**
10
- * @type {(options: webpackCallbackBased.Configuration) => Promise<webpackCallbackBased.Stats>}
11
- */
12
- // @ts-expect-error Can't select the right overload
13
- const webpack = promisify(webpackCallbackBased);
14
- const rootDir = process.cwd();
15
- const require = createRequire(import.meta.url);
16
-
17
- /**
18
- * Creates webpack configuration for bundle size checking
19
- * @param {ObjectEntry} entry - Entry point (string or object)
20
- * @param {CommandLineArgs} args
21
- * @returns {Promise<{configuration: import('webpack').Configuration, externalsArray: string[]}>}
22
- */
23
- async function createWebpackConfig(entry, args) {
24
- const analyzerMode = args.analyze ? 'static' : 'disabled';
25
- const concatenateModules = !args.accurateBundles;
26
-
27
- const entryName = entry.id;
28
- let entryContent;
29
-
30
- if (entry.code && (entry.import || entry.importedNames)) {
31
- entryContent = entry.code;
32
- } else if (entry.code) {
33
- entryContent = entry.code;
34
- } else if (entry.import) {
35
- if (entry.importedNames && entry.importedNames.length > 0) {
36
- // Generate named imports for each name in the importedNames array
37
- const imports = entry.importedNames
38
- .map((name) => `import { ${name} } from '${entry.import}';`)
39
- .join('\n');
40
- const logs = entry.importedNames.map((name) => `console.log(${name});`).join('\n');
41
- entryContent = `${imports}\n${logs}`;
42
- } else {
43
- // Default to import * as if importedNames is not defined
44
- entryContent = `import * as _ from '${entry.import}';\nconsole.log(_);`;
45
- }
46
- } else {
47
- throw new Error(`Entry "${entry.id}" must have either code or import property defined`);
48
- }
49
-
50
- /**
51
- * Generate externals function from an array of package names
52
- * @param {string[]} packages - Array of package names to exclude (defaults to react and react-dom)
53
- * @returns {function} - Function to determine if a request should be treated as external
54
- */
55
- function createExternalsFunction(packages = ['react', 'react-dom']) {
56
- /**
57
- * Check if a request should be treated as external
58
- * Uses the new recommended format to avoid deprecation warnings
59
- * @param {{ context: string, request: string }} params - Object containing context and request
60
- * @param {Function} callback - Callback to handle the result
61
- */
62
- return ({ request }, callback) => {
63
- // Iterate through all packages and check if request is equal to or starts with package + '/'
64
- for (const pkg of packages) {
65
- if (request === pkg || request.startsWith(`${pkg}/`)) {
66
- return callback(null, `commonjs ${request}`);
67
- }
68
- }
69
-
70
- return callback();
71
- };
72
- }
73
-
74
- // Use externals from the entry object
75
- const externalsArray = entry.externals || ['react', 'react-dom'];
76
-
77
- /**
78
- * @type {import('webpack').Configuration}
79
- */
80
- const configuration = {
81
- externals: [
82
- // @ts-expect-error -- webpack types are not compatible with the current version
83
- createExternalsFunction(externalsArray),
84
- ],
85
- mode: 'production',
86
- optimization: {
87
- concatenateModules,
88
- minimizer: [
89
- new TerserPlugin({
90
- test: /\.m?js(\?.*)?$/i,
91
- // Avoid creating LICENSE.txt files for each module
92
- // See https://github.com/webpack-contrib/terser-webpack-plugin#remove-comments
93
- terserOptions: {
94
- format: {
95
- comments: false,
96
- },
97
- },
98
- extractComments: false,
99
- }),
100
- ],
101
- },
102
- module: {
103
- rules: [
104
- {
105
- test: /\.[jt]sx?$/,
106
- include: rootDir,
107
- exclude: /node_modules/,
108
- use: {
109
- loader: require.resolve('babel-loader'),
110
- options: {
111
- presets: [
112
- require.resolve('@babel/preset-react'),
113
- require.resolve('@babel/preset-typescript'),
114
- ],
115
- },
116
- },
117
- },
118
- {
119
- test: /\.css$/,
120
- use: [require.resolve('css-loader')],
121
- },
122
- {
123
- test: /\.(png|svg|jpg|gif)$/,
124
- use: [require.resolve('file-loader')],
125
- },
126
- ],
127
- },
128
- output: {
129
- filename: '[name].js',
130
- library: {
131
- // TODO: Use `type: 'module'` once it is supported (currently incompatible with `externals`)
132
- name: 'M',
133
- type: 'var',
134
- // type: 'module',
135
- },
136
- path: path.join(rootDir, 'build'),
137
- },
138
- plugins: [
139
- new CompressionPlugin({
140
- filename: '[path][base][fragment].gz',
141
- }),
142
- new BundleAnalyzerPlugin({
143
- analyzerMode,
144
- // We create a report for each bundle so around 120 reports.
145
- // Opening them all is spam.
146
- // If opened with `webpack --config . --analyze` it'll still open one new tab though.
147
- openAnalyzer: false,
148
- // '[name].html' not supported: https://github.com/webpack-contrib/webpack-bundle-analyzer/issues/12
149
- reportFilename: `${entryName}.html`,
150
- logLevel: 'warn',
151
- }),
152
- ],
153
- // A context to the current dir, which has a node_modules folder with workspace dependencies
154
- context: rootDir,
155
- entry: {
156
- // This format is a data: url combined with inline matchResource to obtain a virtual entry.
157
- // See https://github.com/webpack/webpack/issues/6437#issuecomment-874466638
158
- // See https://webpack.js.org/api/module-methods/#import
159
- // See https://webpack.js.org/api/loaders/#inline-matchresource
160
- [entryName]: `./index.js!=!data:text/javascript;charset=utf-8;base64,${Buffer.from(entryContent.trim()).toString('base64')}`,
161
- },
162
- // TODO: 'browserslist:modern'
163
- // See https://github.com/webpack/webpack/issues/14203
164
- target: 'web',
165
- };
166
-
167
- // Return both the configuration and the externals array
168
- return { configuration, externalsArray };
169
- }
170
-
171
- /**
172
- * Process webpack stats to extract bundle sizes
173
- * @param {import('webpack').Stats} webpackStats - The webpack stats object
174
- * @returns {Map<string, { parsed: number, gzip: number }>} - Map of bundle names to size information
175
- */
176
- function processBundleSizes(webpackStats) {
177
- /** @type {Map<string, { parsed: number, gzip: number }>} */
178
- const sizeMap = new Map();
179
-
180
- if (!webpackStats) {
181
- throw new Error('No webpack stats were returned');
182
- }
183
-
184
- if (webpackStats.hasErrors()) {
185
- const statsJson = webpackStats.toJson({
186
- all: false,
187
- entrypoints: true,
188
- errors: true,
189
- });
190
-
191
- const entrypointKeys = statsJson.entrypoints ? Object.keys(statsJson.entrypoints) : [];
192
-
193
- throw new Error(
194
- `ERROR: The following errors occurred during bundling of ${entrypointKeys.join(', ')} with webpack: \n${(
195
- statsJson.errors || []
196
- )
197
- .map((error) => {
198
- return `${JSON.stringify(error, null, 2)}`;
199
- })
200
- .join('\n')}`,
201
- );
202
- }
203
-
204
- const stats = webpackStats.toJson({
205
- all: false,
206
- assets: true,
207
- entrypoints: true,
208
- relatedAssets: true,
209
- });
210
-
211
- if (!stats.assets) {
212
- return sizeMap;
213
- }
214
-
215
- const assets = new Map(stats.assets.map((asset) => [asset.name, asset]));
216
-
217
- if (stats.entrypoints) {
218
- Object.values(stats.entrypoints).forEach((entrypoint) => {
219
- let parsedSize = 0;
220
- let gzipSize = 0;
221
-
222
- if (entrypoint.assets) {
223
- entrypoint.assets.forEach(({ name, size }) => {
224
- const asset = assets.get(name);
225
- if (asset && asset.related) {
226
- const gzippedAsset = asset.related.find((relatedAsset) => {
227
- return relatedAsset.type === 'gzipped';
228
- });
229
-
230
- if (size !== undefined) {
231
- parsedSize += size;
232
- }
233
-
234
- if (gzippedAsset && gzippedAsset.size !== undefined) {
235
- gzipSize += gzippedAsset.size;
236
- }
237
- }
238
- });
239
- }
240
-
241
- if (!entrypoint.name) {
242
- throw new Error('Entrypoint name is undefined');
243
- }
244
-
245
- sizeMap.set(entrypoint.name, { parsed: parsedSize, gzip: gzipSize });
246
- });
247
- }
248
-
249
- return sizeMap;
250
- }
251
-
252
- /**
253
- * Get sizes for a webpack bundle
254
- * @param {ObjectEntry} entry - The entry configuration
255
- * @param {CommandLineArgs} args - Command line arguments
256
- * @returns {Promise<Map<string, { parsed: number, gzip: number }>>}
257
- */
258
- export async function getWebpackSizes(entry, args) {
259
- // Create webpack configuration
260
- const { configuration } = await createWebpackConfig(entry, args);
261
-
262
- // Run webpack
263
- const webpackStats = await webpack(configuration);
264
-
265
- // Process the webpack stats to get bundle sizes
266
- return processBundleSizes(webpackStats);
267
- }