prebundle 0.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Rspack Contrib
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,171 @@
1
+ # dep-pre-bundler
2
+
3
+ This package is used to prebundle 3rd party dependencies, based on [ncc](https://github.com/vercel/ncc) and `dts-packer`.
4
+
5
+ ## Motivation
6
+
7
+ Prebundle is used to:
8
+
9
+ - Reduce dependencies of core packages, install faster.
10
+ - Improve stability by locking the sub-dependency version .
11
+ - Fix peer dependency warning of some packages.
12
+
13
+ ## Command
14
+
15
+ Run following command to prebundle all dependencies:
16
+
17
+ ```bash
18
+ pnpm start
19
+ ```
20
+
21
+ Run following command to prebundle single dependencies:
22
+
23
+ ```bash
24
+ pnpm start <pkgName>
25
+
26
+ # For example, prebundle commander
27
+ pnpm start commander
28
+ ```
29
+
30
+ ## Add a new dependency
31
+
32
+ 1. Remove the dependency from the `dependencies` of original package.
33
+ 2. Add the dependency to the `devDependencies` of `@rsbuild/prebundle`. If this package has a `@types/package-name` package, it also needs to be added. It is recommended to lock the version of dependencies.
34
+ 3. Add the task config to `src/constant.ts`:
35
+
36
+ ```ts
37
+ const TASKS: TaskConfig[] = [
38
+ {
39
+ packageDir: 'toolkit/utils',
40
+ packageName: '@rsbuild/utils',
41
+ dependencies: [
42
+ // Add the package name
43
+ 'address',
44
+ ],
45
+ },
46
+ ];
47
+ ```
48
+
49
+ 4. Run `pnpm start`.
50
+ 5. Import from the compiled directory:
51
+
52
+ ```ts
53
+ // Old
54
+ import foo from 'foo';
55
+
56
+ // New
57
+ import foo from '../compiled/foo';
58
+ ```
59
+
60
+ ## Dependency Config
61
+
62
+ Supported dependency config:
63
+
64
+ ### externals
65
+
66
+ Externals to leave as requires of the build.
67
+
68
+ ```ts
69
+ dependencies: [
70
+ {
71
+ name: 'foo',
72
+ externals: {
73
+ webpack: '../webpack',
74
+ },
75
+ },
76
+ ];
77
+ ```
78
+
79
+ ### minify
80
+
81
+ Whether to minify the code, default `true`.
82
+
83
+ ```ts
84
+ dependencies: [
85
+ {
86
+ name: 'foo',
87
+ minify: false,
88
+ },
89
+ ];
90
+ ```
91
+
92
+ ### packageJsonField
93
+
94
+ Copy extra fields from original package.json to target package.json.
95
+
96
+ ```ts
97
+ dependencies: [
98
+ {
99
+ name: 'foo',
100
+ packageJsonField: ['options'],
101
+ },
102
+ ];
103
+ ```
104
+
105
+ Following fields will be copied by default:
106
+
107
+ - `name`
108
+ - `author`
109
+ - `version`
110
+ - `funding`
111
+ - `license`
112
+ - `types`
113
+ - `typing`
114
+ - `typings`
115
+
116
+ ### beforeBundle
117
+
118
+ Callback before bundle.
119
+
120
+ ```ts
121
+ dependencies: [
122
+ {
123
+ name: 'foo',
124
+ beforeBundle(task) {
125
+ console.log('do something');
126
+ },
127
+ },
128
+ ];
129
+ ```
130
+
131
+ ### emitFiles
132
+
133
+ Emit extra entry files to map imports.
134
+
135
+ ```ts
136
+ dependencies: [
137
+ {
138
+ name: 'foo',
139
+ emitFiles: [
140
+ {
141
+ path: 'foo.js',
142
+ content: `module.exports = require('./').foo;`,
143
+ },
144
+ ],
145
+ },
146
+ ];
147
+ ```
148
+
149
+ ### ignoreDts
150
+
151
+ Ignore the original .d.ts declaration file, then generate a fake .d.ts file.
152
+
153
+ This can be used to reduce file size for the packages that do not require type definitions, such as webpack plugin.
154
+
155
+ ```ts
156
+ dependencies: [
157
+ {
158
+ name: 'foo',
159
+ ignoreDts: true,
160
+ },
161
+ ];
162
+ ```
163
+
164
+ ## Note
165
+
166
+ We will not prebundle the following packages because their dependencies are complex or are depended by many community packages:
167
+
168
+ - @babel/some-package
169
+ - webpack
170
+ - lodash
171
+ - caniuse-lite
package/bin.js ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,20 @@
1
+ import type { TaskConfig } from './types';
2
+ export declare const ROOT_DIR: string;
3
+ export declare const PACKAGES_DIR: string;
4
+ export declare const DIST_DIR = "compiled";
5
+ export declare const DEFAULT_EXTERNALS: {
6
+ 'caniuse-lite': string;
7
+ '/^caniuse-lite(/.*)/': string;
8
+ webpack: string;
9
+ '/^webpack(/.*)/': string;
10
+ lodash: string;
11
+ '/^lodash(/.*)/': string;
12
+ esbuild: string;
13
+ './package.json': string;
14
+ '../package.json': string;
15
+ '../../package.json': string;
16
+ postcss: string;
17
+ typescript: string;
18
+ '@babel/core': string;
19
+ };
20
+ export declare const TASKS: TaskConfig[];
@@ -0,0 +1,358 @@
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.TASKS = exports.DEFAULT_EXTERNALS = exports.DIST_DIR = exports.PACKAGES_DIR = exports.ROOT_DIR = void 0;
27
+ const node_path_1 = __importStar(require("node:path"));
28
+ const fs_extra_1 = __importStar(require("fs-extra"));
29
+ const helper_1 = require("./helper");
30
+ exports.ROOT_DIR = (0, node_path_1.join)(__dirname, '..', '..', '..');
31
+ exports.PACKAGES_DIR = (0, node_path_1.join)(exports.ROOT_DIR, 'packages');
32
+ exports.DIST_DIR = 'compiled';
33
+ exports.DEFAULT_EXTERNALS = {
34
+ // External caniuse-lite data, so users can update it manually.
35
+ 'caniuse-lite': 'caniuse-lite',
36
+ '/^caniuse-lite(/.*)/': 'caniuse-lite$1',
37
+ // External webpack, it's hard to bundle.
38
+ webpack: 'webpack',
39
+ '/^webpack(/.*)/': 'webpack$1',
40
+ // External lodash because lots of packages will depend on it.
41
+ lodash: 'lodash',
42
+ '/^lodash(/.*)/': 'lodash$1',
43
+ esbuild: 'esbuild',
44
+ // ncc bundled wrong package.json, using external to avoid this problem
45
+ './package.json': './package.json',
46
+ '../package.json': './package.json',
47
+ '../../package.json': './package.json',
48
+ postcss: 'postcss',
49
+ typescript: 'typescript',
50
+ '@babel/core': '@babel/core',
51
+ };
52
+ const writeEmptySchemaUtils = (task) => {
53
+ // The package size of `schema-utils` is large, and validate has a performance overhead of tens of ms.
54
+ // So we skip the validation and let TypeScript to ensure type safety.
55
+ const schemaUtilsPath = (0, node_path_1.join)(task.distPath, 'schema-utils.js');
56
+ fs_extra_1.default.outputFileSync(schemaUtilsPath, 'module.exports.validate = () => {};');
57
+ };
58
+ exports.TASKS = [
59
+ {
60
+ packageDir: 'core',
61
+ packageName: '@rsbuild/core',
62
+ dependencies: [
63
+ 'open',
64
+ 'commander',
65
+ 'dotenv',
66
+ 'dotenv-expand',
67
+ 'ws',
68
+ 'on-finished',
69
+ {
70
+ name: 'launch-editor-middleware',
71
+ ignoreDts: true,
72
+ externals: {
73
+ picocolors: '@rsbuild/shared/picocolors',
74
+ },
75
+ },
76
+ {
77
+ name: 'sirv',
78
+ afterBundle(task) {
79
+ (0, helper_1.replaceFileContent)((0, node_path_1.join)(task.distPath, 'sirv.d.ts'), (content) => `${content.replace("declare module 'sirv'", 'declare namespace sirv')}\nexport = sirv;`);
80
+ },
81
+ },
82
+ {
83
+ name: 'http-compression',
84
+ ignoreDts: true,
85
+ },
86
+ {
87
+ name: 'connect-history-api-fallback',
88
+ ignoreDts: true,
89
+ },
90
+ ],
91
+ },
92
+ {
93
+ packageDir: 'shared',
94
+ packageName: '@rsbuild/shared',
95
+ dependencies: [
96
+ 'jiti',
97
+ 'rslog',
98
+ 'deepmerge',
99
+ 'fs-extra',
100
+ 'chokidar',
101
+ 'webpack-merge',
102
+ 'mime-types',
103
+ 'connect',
104
+ 'browserslist',
105
+ 'gzip-size',
106
+ 'json5',
107
+ {
108
+ name: 'webpack-chain',
109
+ externals: {
110
+ deepmerge: '../deepmerge',
111
+ },
112
+ },
113
+ {
114
+ name: 'yaml',
115
+ ignoreDts: true,
116
+ afterBundle(task) {
117
+ fs_extra_1.default.writeFileSync((0, node_path_1.join)(task.distPath, 'index.d.ts'), 'export declare function parse(src: string, options?: any): any;');
118
+ },
119
+ },
120
+ {
121
+ name: 'line-diff',
122
+ ignoreDts: true,
123
+ },
124
+ {
125
+ name: 'semver',
126
+ ignoreDts: true,
127
+ },
128
+ {
129
+ name: 'icss-utils',
130
+ ignoreDts: true,
131
+ },
132
+ {
133
+ name: 'postcss-value-parser',
134
+ ignoreDts: true,
135
+ },
136
+ {
137
+ name: 'postcss-modules-local-by-default',
138
+ ignoreDts: true,
139
+ externals: {
140
+ 'icss-utils': '../icss-utils',
141
+ 'postcss-value-parser': '../postcss-value-parser',
142
+ },
143
+ },
144
+ {
145
+ name: 'postcss-modules-extract-imports',
146
+ ignoreDts: true,
147
+ },
148
+ {
149
+ name: 'postcss-modules-scope',
150
+ ignoreDts: true,
151
+ },
152
+ {
153
+ name: 'postcss-modules-values',
154
+ ignoreDts: true,
155
+ externals: {
156
+ 'icss-utils': '../icss-utils',
157
+ },
158
+ },
159
+ {
160
+ name: 'sass-loader',
161
+ externals: {
162
+ sass: '../sass',
163
+ },
164
+ },
165
+ {
166
+ name: 'sass',
167
+ externals: {
168
+ chokidar: '../chokidar',
169
+ },
170
+ afterBundle(task) {
171
+ (0, fs_extra_1.copySync)((0, node_path_1.join)(task.depPath, 'types'), (0, node_path_1.join)(task.distPath, 'types'));
172
+ },
173
+ },
174
+ {
175
+ name: 'style-loader',
176
+ ignoreDts: true,
177
+ afterBundle: (task) => {
178
+ fs_extra_1.default.copySync((0, node_path_1.join)(task.depPath, 'dist/runtime'), (0, node_path_1.join)(task.distPath, 'runtime'));
179
+ },
180
+ },
181
+ {
182
+ name: 'less',
183
+ externals: {
184
+ // needle is an optional dependency and no need to bundle it.
185
+ needle: 'needle',
186
+ },
187
+ afterBundle(task) {
188
+ (0, helper_1.replaceFileContent)((0, node_path_1.join)(task.distPath, 'index.d.ts'), (content) => content.replace(`declare module "less" {\n export = less;\n}`, 'export = Less;'));
189
+ },
190
+ },
191
+ {
192
+ name: 'less-loader',
193
+ ignoreDts: true,
194
+ externals: {
195
+ less: '../less',
196
+ },
197
+ },
198
+ {
199
+ name: 'css-loader',
200
+ ignoreDts: true,
201
+ externals: {
202
+ semver: '../semver',
203
+ 'postcss-value-parser': '../postcss-value-parser',
204
+ 'postcss-modules-local-by-default': '../postcss-modules-local-by-default',
205
+ 'postcss-modules-extract-imports': '../postcss-modules-extract-imports',
206
+ 'postcss-modules-scope': '../postcss-modules-scope',
207
+ 'postcss-modules-values': '../postcss-modules-values',
208
+ 'icss-utils': '../icss-utils',
209
+ },
210
+ },
211
+ {
212
+ name: 'postcss-loader',
213
+ externals: {
214
+ jiti: '../jiti',
215
+ semver: '../semver',
216
+ },
217
+ ignoreDts: true,
218
+ },
219
+ {
220
+ name: 'postcss-load-config',
221
+ externals: {
222
+ jiti: '../jiti',
223
+ yaml: '../yaml',
224
+ },
225
+ ignoreDts: true,
226
+ // this is a trick to avoid ncc compiling the dynamic import syntax
227
+ // https://github.com/vercel/ncc/issues/935
228
+ beforeBundle(task) {
229
+ (0, helper_1.replaceFileContent)((0, node_path_1.join)(task.depPath, 'src/req.js'), (content) => `${content.replace('await import', 'await __import')}`);
230
+ },
231
+ afterBundle(task) {
232
+ (0, helper_1.replaceFileContent)((0, node_path_1.join)(task.distPath, 'index.js'), (content) => `${content.replace('await __import', 'await import')}`);
233
+ },
234
+ },
235
+ {
236
+ name: 'loader-utils2',
237
+ ignoreDts: true,
238
+ externals: {
239
+ json5: '../json5',
240
+ },
241
+ },
242
+ {
243
+ name: 'picocolors',
244
+ beforeBundle({ depPath }) {
245
+ const typesFile = node_path_1.default.join(depPath, 'types.ts');
246
+ // Fix type bundle
247
+ if (fs_extra_1.default.existsSync(typesFile)) {
248
+ fs_extra_1.default.renameSync(typesFile, node_path_1.default.join(depPath, 'types.d.ts'));
249
+ }
250
+ },
251
+ },
252
+ {
253
+ name: 'resolve-url-loader',
254
+ ignoreDts: true,
255
+ externals: {
256
+ 'loader-utils': '../loader-utils2',
257
+ },
258
+ },
259
+ {
260
+ name: 'webpack-dev-middleware',
261
+ externals: {
262
+ 'schema-utils': './schema-utils',
263
+ 'schema-utils/declarations/validate': 'schema-utils/declarations/validate',
264
+ 'mime-types': '../mime-types',
265
+ },
266
+ afterBundle: writeEmptySchemaUtils,
267
+ },
268
+ {
269
+ name: 'autoprefixer',
270
+ externals: {
271
+ picocolors: '../picocolors',
272
+ browserslist: '../browserslist',
273
+ 'postcss-value-parser': '../postcss-value-parser',
274
+ },
275
+ },
276
+ {
277
+ name: 'http-proxy-middleware',
278
+ externals: {
279
+ // express is a peer dependency, no need to provide express type
280
+ express: 'express',
281
+ },
282
+ },
283
+ {
284
+ // The webpack-bundle-analyzer version was locked to v4.9.0 to be compatible with Rspack
285
+ // If we need to upgrade the version, please check if the chunk detail can be displayed correctly
286
+ name: 'webpack-bundle-analyzer',
287
+ externals: {
288
+ 'gzip-size': '../gzip-size',
289
+ },
290
+ },
291
+ ],
292
+ },
293
+ {
294
+ packageDir: 'plugin-babel',
295
+ packageName: '@rsbuild/plugin-babel',
296
+ dependencies: [
297
+ {
298
+ name: 'babel-loader',
299
+ ignoreDts: true,
300
+ externals: {
301
+ 'schema-utils': './schema-utils',
302
+ },
303
+ afterBundle: writeEmptySchemaUtils,
304
+ },
305
+ ],
306
+ },
307
+ {
308
+ packageDir: 'plugin-svgr',
309
+ packageName: '@rsbuild/plugin-svgr',
310
+ dependencies: [
311
+ {
312
+ name: 'file-loader',
313
+ ignoreDts: true,
314
+ externals: {
315
+ 'schema-utils': './schema-utils',
316
+ 'loader-utils': '@rsbuild/shared/loader-utils2',
317
+ },
318
+ afterBundle: writeEmptySchemaUtils,
319
+ },
320
+ {
321
+ name: 'url-loader',
322
+ ignoreDts: true,
323
+ externals: {
324
+ 'schema-utils': './schema-utils',
325
+ 'loader-utils': '@rsbuild/shared/loader-utils2',
326
+ 'mime-types': '@rsbuild/shared/mime-types',
327
+ },
328
+ afterBundle(task) {
329
+ writeEmptySchemaUtils(task);
330
+ (0, helper_1.replaceFileContent)((0, node_path_1.join)(task.distPath, 'index.js'), (content) => {
331
+ // use prebundle file-loader
332
+ return content.replace('"file-loader"', 'require.resolve("../file-loader")');
333
+ });
334
+ },
335
+ },
336
+ ],
337
+ },
338
+ {
339
+ packageDir: 'plugin-yaml',
340
+ packageName: '@rsbuild/plugin-yaml',
341
+ dependencies: [
342
+ {
343
+ name: 'yaml-loader',
344
+ ignoreDts: true,
345
+ },
346
+ ],
347
+ },
348
+ {
349
+ packageDir: 'plugin-rem',
350
+ packageName: '@rsbuild/plugin-rem',
351
+ dependencies: [
352
+ {
353
+ name: 'postcss-pxtorem',
354
+ ignoreDts: true,
355
+ },
356
+ ],
357
+ },
358
+ ];
@@ -0,0 +1,5 @@
1
+ import type { ParsedTask } from './types';
2
+ export declare function findDepPath(name: string): string;
3
+ export declare function parseTasks(): ParsedTask[];
4
+ export declare function pick<T, U extends keyof T>(obj: T, keys: ReadonlyArray<U>): Pick<T, U>;
5
+ export declare function replaceFileContent(filePath: string, replaceFn: (content: string) => string): void;
package/dist/helper.js ADDED
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.replaceFileContent = exports.pick = exports.parseTasks = exports.findDepPath = void 0;
7
+ const node_path_1 = require("node:path");
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const constant_1 = require("./constant");
10
+ function findDepPath(name) {
11
+ let entry = (0, node_path_1.dirname)(require.resolve((0, node_path_1.join)(name)));
12
+ while (!(0, node_path_1.dirname)(entry).endsWith('node_modules')) {
13
+ entry = (0, node_path_1.dirname)(entry);
14
+ }
15
+ if (name.includes('/')) {
16
+ return (0, node_path_1.join)((0, node_path_1.dirname)(entry), name);
17
+ }
18
+ return entry;
19
+ }
20
+ exports.findDepPath = findDepPath;
21
+ function parseTasks() {
22
+ const result = [];
23
+ for (const { packageName, packageDir, dependencies } of constant_1.TASKS) {
24
+ for (const dep of dependencies) {
25
+ const depName = typeof dep === 'string' ? dep : dep.name;
26
+ const importPath = (0, node_path_1.join)(packageName, constant_1.DIST_DIR, depName);
27
+ const packagePath = (0, node_path_1.join)(constant_1.PACKAGES_DIR, packageDir);
28
+ const distPath = (0, node_path_1.join)(packagePath, constant_1.DIST_DIR, depName);
29
+ const depPath = findDepPath(depName);
30
+ const depEntry = require.resolve(depName);
31
+ const info = {
32
+ depName,
33
+ depPath,
34
+ depEntry,
35
+ distPath,
36
+ importPath,
37
+ packageDir,
38
+ packagePath,
39
+ packageName,
40
+ };
41
+ if (typeof dep === 'string') {
42
+ result.push({
43
+ minify: true,
44
+ externals: {},
45
+ emitFiles: [],
46
+ packageJsonField: [],
47
+ ...info,
48
+ });
49
+ }
50
+ else {
51
+ result.push({
52
+ minify: dep.minify ?? true,
53
+ ignoreDts: dep.ignoreDts,
54
+ externals: dep.externals ?? {},
55
+ emitFiles: dep.emitFiles ?? [],
56
+ afterBundle: dep.afterBundle,
57
+ beforeBundle: dep.beforeBundle,
58
+ packageJsonField: dep.packageJsonField ?? [],
59
+ ...info,
60
+ });
61
+ }
62
+ }
63
+ }
64
+ return result;
65
+ }
66
+ exports.parseTasks = parseTasks;
67
+ function pick(obj, keys) {
68
+ return keys.reduce((ret, key) => {
69
+ if (obj[key] !== undefined) {
70
+ ret[key] = obj[key];
71
+ }
72
+ return ret;
73
+ }, {});
74
+ }
75
+ exports.pick = pick;
76
+ function replaceFileContent(filePath, replaceFn) {
77
+ const content = fs_extra_1.default.readFileSync(filePath, 'utf-8');
78
+ const newContent = replaceFn(content);
79
+ if (newContent !== content) {
80
+ fs_extra_1.default.writeFileSync(filePath, newContent);
81
+ }
82
+ }
83
+ exports.replaceFileContent = replaceFileContent;
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const helper_1 = require("./helper");
4
+ const prebundle_1 = require("./prebundle");
5
+ async function run() {
6
+ const parsedTasks = (0, helper_1.parseTasks)();
7
+ for (const task of parsedTasks) {
8
+ await (0, prebundle_1.prebundle)(task);
9
+ }
10
+ }
11
+ run();
@@ -0,0 +1,2 @@
1
+ import type { ParsedTask } from './types';
2
+ export declare function prebundle(task: ParsedTask): Promise<void>;
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.prebundle = void 0;
7
+ const node_path_1 = require("node:path");
8
+ const ncc_1 = __importDefault(require("@vercel/ncc"));
9
+ const dts_packer_1 = require("dts-packer");
10
+ const fast_glob_1 = __importDefault(require("fast-glob"));
11
+ const fs_extra_1 = __importDefault(require("fs-extra"));
12
+ const constant_1 = require("./constant");
13
+ const helper_1 = require("./helper");
14
+ function emitAssets(assets, distPath) {
15
+ for (const key of Object.keys(assets)) {
16
+ const asset = assets[key];
17
+ fs_extra_1.default.outputFileSync((0, node_path_1.join)(distPath, key), asset.source);
18
+ }
19
+ }
20
+ function emitIndex(code, distPath) {
21
+ const distIndex = (0, node_path_1.join)(distPath, 'index.js');
22
+ fs_extra_1.default.outputFileSync(distIndex, code);
23
+ }
24
+ function fixTypeExternalPath(file, task, externals) {
25
+ const filepath = (0, node_path_1.join)(task.distPath, file);
26
+ (0, helper_1.replaceFileContent)(filepath, (content) => {
27
+ let newContent = content;
28
+ for (const name of Object.keys(externals)) {
29
+ newContent = newContent.replace(new RegExp(`../../${name}`, 'g'), externals[name]);
30
+ }
31
+ return newContent;
32
+ });
33
+ }
34
+ function emitDts(task) {
35
+ if (task.ignoreDts) {
36
+ fs_extra_1.default.writeFileSync((0, node_path_1.join)(task.distPath, 'index.d.ts'), 'export = any;\n');
37
+ return;
38
+ }
39
+ try {
40
+ const externals = {
41
+ ...constant_1.DEFAULT_EXTERNALS,
42
+ ...task.externals,
43
+ };
44
+ const { files } = new dts_packer_1.Package({
45
+ cwd: process.cwd(),
46
+ name: task.depName,
47
+ typesRoot: task.distPath,
48
+ externals: Object.keys(externals),
49
+ });
50
+ for (const file of Object.keys(files)) {
51
+ fixTypeExternalPath(file, task, externals);
52
+ }
53
+ }
54
+ catch (error) {
55
+ console.error(`DtsPacker failed: ${task.depName}`);
56
+ console.error(error);
57
+ }
58
+ }
59
+ function emitPackageJson(task) {
60
+ const packageJsonPath = (0, node_path_1.join)(task.depPath, 'package.json');
61
+ const packageJson = fs_extra_1.default.readJsonSync(packageJsonPath, 'utf-8');
62
+ const outputPath = (0, node_path_1.join)(task.distPath, 'package.json');
63
+ const pickedPackageJson = (0, helper_1.pick)(packageJson, [
64
+ 'name',
65
+ 'author',
66
+ 'version',
67
+ 'funding',
68
+ 'license',
69
+ 'types',
70
+ 'typing',
71
+ 'typings',
72
+ ...task.packageJsonField,
73
+ ]);
74
+ if (task.depName !== pickedPackageJson.name) {
75
+ pickedPackageJson.name = task.depName;
76
+ }
77
+ if (task.ignoreDts) {
78
+ delete pickedPackageJson.typing;
79
+ delete pickedPackageJson.typings;
80
+ pickedPackageJson.types = 'index.d.ts';
81
+ }
82
+ fs_extra_1.default.writeJSONSync(outputPath, pickedPackageJson);
83
+ }
84
+ function emitLicense(task) {
85
+ const licensePath = (0, node_path_1.join)(task.depPath, 'LICENSE');
86
+ if (fs_extra_1.default.existsSync(licensePath)) {
87
+ fs_extra_1.default.copySync(licensePath, (0, node_path_1.join)(task.distPath, 'license'));
88
+ }
89
+ }
90
+ function emitExtraFiles(task) {
91
+ const { emitFiles } = task;
92
+ for (const item of emitFiles) {
93
+ const path = (0, node_path_1.join)(task.distPath, item.path);
94
+ fs_extra_1.default.outputFileSync(path, item.content);
95
+ }
96
+ }
97
+ function removeSourceMap(task) {
98
+ const maps = fast_glob_1.default.sync((0, node_path_1.join)(task.distPath, '**/*.map'));
99
+ for (const mapPath of maps) {
100
+ fs_extra_1.default.removeSync(mapPath);
101
+ }
102
+ }
103
+ function renameDistFolder(task) {
104
+ const pkgPath = (0, node_path_1.join)(task.distPath, 'package.json');
105
+ const pkgJson = fs_extra_1.default.readJsonSync(pkgPath, 'utf-8');
106
+ for (const key of ['types', 'typing', 'typings']) {
107
+ if (pkgJson[key]?.startsWith('dist/')) {
108
+ pkgJson[key] = pkgJson[key].replace('dist/', 'types/');
109
+ const distFolder = (0, node_path_1.join)(task.distPath, 'dist');
110
+ const typesFolder = (0, node_path_1.join)(task.distPath, 'types');
111
+ if (fs_extra_1.default.existsSync(distFolder)) {
112
+ fs_extra_1.default.renameSync(distFolder, typesFolder);
113
+ }
114
+ }
115
+ }
116
+ // compiled packages are always use commonjs
117
+ pkgJson.type = 'commonjs';
118
+ fs_extra_1.default.writeJSONSync(pkgPath, pkgJson);
119
+ }
120
+ const pkgName = process.argv[2];
121
+ async function prebundle(task) {
122
+ if (pkgName && task.depName !== pkgName) {
123
+ return;
124
+ }
125
+ console.log(`==== Start prebundle "${task.depName}" ====`);
126
+ fs_extra_1.default.removeSync(task.distPath);
127
+ if (task.beforeBundle) {
128
+ await task.beforeBundle(task);
129
+ }
130
+ const { code, assets } = await (0, ncc_1.default)(task.depEntry, {
131
+ minify: task.minify,
132
+ target: 'es2019',
133
+ externals: {
134
+ ...constant_1.DEFAULT_EXTERNALS,
135
+ ...task.externals,
136
+ },
137
+ assetBuilds: false,
138
+ });
139
+ emitIndex(code, task.distPath);
140
+ emitAssets(assets, task.distPath);
141
+ emitDts(task);
142
+ emitLicense(task);
143
+ emitPackageJson(task);
144
+ removeSourceMap(task);
145
+ renameDistFolder(task);
146
+ emitExtraFiles(task);
147
+ if (task.afterBundle) {
148
+ await task.afterBundle(task);
149
+ }
150
+ console.log(`==== Finish prebundle "${task.depName}" ====\n\n`);
151
+ }
152
+ exports.prebundle = prebundle;
@@ -0,0 +1,42 @@
1
+ export type ImportMap = {
2
+ path: string;
3
+ content: string;
4
+ };
5
+ export type DependencyConfig = {
6
+ /** Name of dependency */
7
+ name: string;
8
+ /** Whether to minify the code. */
9
+ minify?: boolean;
10
+ /** Externals to leave as requires of the build. */
11
+ externals?: Record<string, string>;
12
+ /** Emit extra entry files to map imports. */
13
+ emitFiles?: ImportMap[];
14
+ /** Copy extra fields from original package.json to target package.json. */
15
+ packageJsonField?: string[];
16
+ /** Whether to ignore type definitions */
17
+ ignoreDts?: boolean;
18
+ beforeBundle?: (task: ParsedTask) => void | Promise<void>;
19
+ afterBundle?: (task: ParsedTask) => void | Promise<void>;
20
+ };
21
+ export type TaskConfig = {
22
+ packageDir: string;
23
+ packageName: string;
24
+ dependencies: Array<string | DependencyConfig>;
25
+ };
26
+ export type ParsedTask = {
27
+ depPath: string;
28
+ depEntry: string;
29
+ distPath: string;
30
+ importPath: string;
31
+ packageDir: string;
32
+ ignoreDts?: boolean;
33
+ packagePath: string;
34
+ packageName: string;
35
+ minify: NonNullable<DependencyConfig['minify']>;
36
+ depName: NonNullable<DependencyConfig['name']>;
37
+ externals: NonNullable<DependencyConfig['externals']>;
38
+ emitFiles: NonNullable<DependencyConfig['emitFiles']>;
39
+ afterBundle?: NonNullable<DependencyConfig['afterBundle']>;
40
+ beforeBundle?: NonNullable<DependencyConfig['beforeBundle']>;
41
+ packageJsonField: NonNullable<DependencyConfig['packageJsonField']>;
42
+ };
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "prebundle",
3
+ "version": "0.0.1",
4
+ "main": "./dist/index.js",
5
+ "files": [
6
+ "dist"
7
+ ],
8
+ "bin": {
9
+ "prebundle": "./bin.js"
10
+ },
11
+ "dependencies": {
12
+ "@vercel/ncc": "0.38.1",
13
+ "dts-packer": "0.0.3",
14
+ "fast-glob": "^3.3.2",
15
+ "fs-extra": "^11.2.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/fs-extra": "^11.0.4",
19
+ "@types/node": "18.x",
20
+ "typescript": "^5.4.2"
21
+ },
22
+ "scripts": {
23
+ "dev": "tsc --watch",
24
+ "build": "tsc",
25
+ "start": "pnpm build && node ./dist/index.js"
26
+ }
27
+ }