quickbundle 0.0.0-next-6c096f7 → 0.0.0-next-63542e6
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/README.md +16 -16
- package/bin/index.mjs +1 -1
- package/dist/index.mjs +116 -115
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
Quickbundle allows you to bundle a library in a **quick**, **fast** and **easy** way:
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
13
|
+
- Fast build and watch mode powered by Rollup[^1] and SWC[^2].
|
|
14
|
+
- Zero configuration: define the build artifacts in your `package.json`, and you're all set!
|
|
15
|
+
- Support of `cjs` & `esm` module formats output.
|
|
16
|
+
- Support of several loaders including JavaScript, TypeScript, JSX, JSON, and Images.
|
|
17
|
+
- TypeScript's declaration file (`.d.ts`) bundling.
|
|
18
|
+
- Automatic dependency inclusion (`peerDependencies` and `dependencies` are not bundled in the final output, `devDependencies` are unless they're not imported).
|
|
19
19
|
|
|
20
20
|
[^1]: A [module bundler](https://rollupjs.org/) optimized for better tree-shaking processing and seamless interoperability of CommonJS and ESM formats with minimal code footprint.
|
|
21
21
|
|
|
@@ -38,7 +38,7 @@ yarn add quickbundle
|
|
|
38
38
|
|
|
39
39
|
2️⃣ Set up your package configuration (`package.json`):
|
|
40
40
|
|
|
41
|
-
-
|
|
41
|
+
- When exporting exclusively ESM format:
|
|
42
42
|
|
|
43
43
|
```jsonc
|
|
44
44
|
{
|
|
@@ -63,7 +63,7 @@ yarn add quickbundle
|
|
|
63
63
|
}
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
-
|
|
66
|
+
- When exporting both CommonJS (CJS) and ECMAScript Modules (ESM) format (please be aware of [dual package hazard risk](https://nodejs.org/api/packages.html#dual-package-hazard)):
|
|
67
67
|
|
|
68
68
|
```jsonc
|
|
69
69
|
{
|
|
@@ -109,14 +109,14 @@ yarn build
|
|
|
109
109
|
|
|
110
110
|
By default, Quickbundle does the following built-in optimizations during the bundling process:
|
|
111
111
|
|
|
112
|
-
-
|
|
113
|
-
-
|
|
112
|
+
- Include, in the build output, only the code that is effectively imported and used in the source code. Setting the `sideEffects` package.json field to `false` marks the package as a side-effect-free one and helps Quickbundle to safely prune unused exports.
|
|
113
|
+
- [Identify and annotate](https://rollupjs.org/configuration-options/#treeshake-annotations) side-effect-free code (functions, ...) to enable a fine-grained dead-code elimination process later consumer side. For example, if a consumer uses only one library API, build output annotations added by Quickbundle allow the consumer's bundler remove all other unused APIs.
|
|
114
114
|
|
|
115
115
|
However, Quickbundle doesn't minify the build output. Indeed, in general, **if the build targets a library (the most Quickbundle use case)**, minification is not necessary since enabling it can introduce some challenges:
|
|
116
116
|
|
|
117
|
-
-
|
|
118
|
-
-
|
|
119
|
-
-
|
|
117
|
+
- Reduce the build output discoverability inside the `node_modules` folder (minified code is an obfuscated code that can be hard to read for code audit/debugging purposes).
|
|
118
|
+
- Generate suboptimal source maps for the bundled library, as the consumer bundler will generate source maps based on the already minified library build (transformed code, mangled variable names, etc.).
|
|
119
|
+
- Risk of side effects with double optimizations (producer side and then consumer side).
|
|
120
120
|
|
|
121
121
|
Popular open source libraries ([Vue](https://unpkg.com/browse/vue@3.4.24/dist/), [SolidJS](https://unpkg.com/browse/solid-js@1.8.17/dist/), [Material UI](https://unpkg.com/browse/@material-ui/core@4.12.4/), ...) do not provide minified builds as the build optimization is sensitive to the consumer context (e.g. environment targets (browser support), ...) and needs to be fully owned upstream (i.e. consumer/application-side).
|
|
122
122
|
|
|
@@ -142,7 +142,7 @@ Enabling source map generation is needed only if a build is [obfuscated (minifie
|
|
|
142
142
|
|
|
143
143
|
## 🤩 Used by
|
|
144
144
|
|
|
145
|
-
-
|
|
145
|
+
- [@adbayb/stack](https://github.com/adbayb/stack) My opinionated toolbox for JavaScript/TypeScript projects.
|
|
146
146
|
|
|
147
147
|
<br>
|
|
148
148
|
|
|
@@ -154,8 +154,8 @@ We're open to new contributions, you can find more details [here](./CONTRIBUTING
|
|
|
154
154
|
|
|
155
155
|
## 💙 Acknowledgements
|
|
156
156
|
|
|
157
|
-
-
|
|
158
|
-
-
|
|
157
|
+
- The backend is powered by [Rollup](https://github.com/rollup/rollup) and its plugin ecosystem (including [SWC](https://github.com/swc-project/swc)) to make blazing-fast builds. A special shoutout to all contributors involved.
|
|
158
|
+
- The zero-configuration approach was inspired by [microbundle](https://github.com/developit/microbundle). A special shoutout to its author [Jason Miller](https://github.com/developit) and [all contributors](https://github.com/developit/microbundle/graphs/contributors).
|
|
159
159
|
|
|
160
160
|
<br>
|
|
161
161
|
|
package/bin/index.mjs
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
import { helpers, termost } from 'termost';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import json from '@rollup/plugin-json';
|
|
7
|
-
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
8
|
-
import url from '@rollup/plugin-url';
|
|
9
|
-
import { createRequire } from 'node:module';
|
|
2
|
+
import { readFile as readFile$1 } from 'node:fs/promises';
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
import { watch as watch$1, rollup } from 'rollup';
|
|
10
5
|
import { join } from 'node:path';
|
|
11
|
-
import
|
|
12
|
-
import externals from 'rollup-plugin-node-externals';
|
|
6
|
+
import { createRequire } from 'node:module';
|
|
13
7
|
import { swc } from 'rollup-plugin-swc3';
|
|
14
|
-
import
|
|
8
|
+
import externals from 'rollup-plugin-node-externals';
|
|
9
|
+
import dts from 'rollup-plugin-dts';
|
|
10
|
+
import url from '@rollup/plugin-url';
|
|
11
|
+
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
12
|
+
import json from '@rollup/plugin-json';
|
|
13
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
14
|
+
import { gzipSize } from 'gzip-size';
|
|
15
|
+
|
|
16
|
+
const CWD = process.cwd();
|
|
17
|
+
|
|
18
|
+
const readFile = readFile$1;
|
|
19
|
+
const createCommand = (program, input)=>{
|
|
20
|
+
return program.command(input).option({
|
|
21
|
+
key: "minification",
|
|
22
|
+
name: "minification",
|
|
23
|
+
description: "Enable minification",
|
|
24
|
+
defaultValue: false
|
|
25
|
+
}).option({
|
|
26
|
+
key: "sourceMaps",
|
|
27
|
+
name: "source-maps",
|
|
28
|
+
description: "Enable source maps generation",
|
|
29
|
+
defaultValue: false
|
|
30
|
+
});
|
|
31
|
+
};
|
|
15
32
|
|
|
16
33
|
const onLog = (_, log)=>{
|
|
17
34
|
if (log.message.includes("Generated an empty chunk")) return;
|
|
@@ -20,41 +37,51 @@ const isRecord = (value)=>{
|
|
|
20
37
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21
38
|
};
|
|
22
39
|
|
|
23
|
-
const
|
|
24
|
-
process.env.NODE_ENV ??= "
|
|
25
|
-
const
|
|
26
|
-
for (const config of configurations){
|
|
27
|
-
const initialTime = Date.now();
|
|
28
|
-
const bundle = await rollup({
|
|
40
|
+
const watch = (configurations)=>{
|
|
41
|
+
process.env.NODE_ENV ??= "development";
|
|
42
|
+
const watcher = watch$1(configurations.map((config)=>({
|
|
29
43
|
...config,
|
|
30
44
|
onLog
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
})));
|
|
46
|
+
let startDuration;
|
|
47
|
+
console.clear();
|
|
48
|
+
watcher.on("event", async (event)=>{
|
|
49
|
+
switch(event.code){
|
|
50
|
+
case "START":
|
|
51
|
+
{
|
|
52
|
+
startDuration = Date.now();
|
|
53
|
+
clearLog(`Build in progress...`, {
|
|
54
|
+
type: "information"
|
|
55
|
+
});
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
case "BUNDLE_END":
|
|
59
|
+
await event.result.close();
|
|
60
|
+
break;
|
|
61
|
+
case "END":
|
|
62
|
+
{
|
|
63
|
+
const duration = Date.now() - startDuration;
|
|
64
|
+
clearLog(`Build done in ${duration}ms (at ${new Date().toLocaleTimeString()})`, {
|
|
65
|
+
type: "success"
|
|
66
|
+
});
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
case "ERROR":
|
|
70
|
+
{
|
|
71
|
+
const { error } = event;
|
|
72
|
+
clearLog(error.message, {
|
|
73
|
+
type: "error"
|
|
74
|
+
});
|
|
75
|
+
console.error("\n", error);
|
|
76
|
+
return;
|
|
41
77
|
}
|
|
42
|
-
promises.push(new Promise((resolve, reject)=>{
|
|
43
|
-
bundle.write(outputEntry).then(()=>{
|
|
44
|
-
resolve({
|
|
45
|
-
elapsedTime: Date.now() - initialTime,
|
|
46
|
-
filename: outputFilename
|
|
47
|
-
});
|
|
48
|
-
}).catch(reject);
|
|
49
|
-
}));
|
|
50
|
-
}
|
|
51
|
-
output.push(...await Promise.all(promises));
|
|
52
78
|
}
|
|
53
|
-
}
|
|
54
|
-
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
const clearLog = (...input)=>{
|
|
82
|
+
console.clear();
|
|
83
|
+
helpers.message(...input);
|
|
55
84
|
};
|
|
56
|
-
|
|
57
|
-
const CWD = process.cwd();
|
|
58
85
|
|
|
59
86
|
const require = createRequire(import.meta.url);
|
|
60
87
|
const PKG = require(join(CWD, "./package.json"));
|
|
@@ -218,24 +245,59 @@ const createTypesConfig = (entryPoints)=>{
|
|
|
218
245
|
}))
|
|
219
246
|
};
|
|
220
247
|
};
|
|
221
|
-
// eslint-disable-next-line import/no-default-export
|
|
222
248
|
createConfigurations();
|
|
223
249
|
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
250
|
+
const createWatchCommand = (program)=>{
|
|
251
|
+
return createCommand(program, {
|
|
252
|
+
name: "watch",
|
|
253
|
+
description: "Watch and rebuild on any code change (development mode)"
|
|
254
|
+
}).task({
|
|
255
|
+
handler (context) {
|
|
256
|
+
watch(createConfigurations({
|
|
257
|
+
minification: context.minification,
|
|
258
|
+
sourceMaps: context.sourceMaps,
|
|
259
|
+
standalone: false
|
|
260
|
+
}));
|
|
261
|
+
}
|
|
236
262
|
});
|
|
237
263
|
};
|
|
238
264
|
|
|
265
|
+
const build = async (configurations)=>{
|
|
266
|
+
process.env.NODE_ENV ??= "production";
|
|
267
|
+
const output = [];
|
|
268
|
+
for (const config of configurations){
|
|
269
|
+
const initialTime = Date.now();
|
|
270
|
+
const bundle = await rollup({
|
|
271
|
+
...config,
|
|
272
|
+
onLog
|
|
273
|
+
});
|
|
274
|
+
if (config.output) {
|
|
275
|
+
const outputEntries = Array.isArray(config.output) ? config.output : [
|
|
276
|
+
config.output
|
|
277
|
+
];
|
|
278
|
+
const promises = [];
|
|
279
|
+
for (const outputEntry of outputEntries){
|
|
280
|
+
const outputFilename = outputEntry.file ?? outputEntry.dir;
|
|
281
|
+
if (!outputFilename) {
|
|
282
|
+
throw new Error("Misconfigured file entry point. Make sure to define an `import`, `require`, or `default` field.");
|
|
283
|
+
}
|
|
284
|
+
promises.push(new Promise((resolve, reject)=>{
|
|
285
|
+
bundle.write(outputEntry).then(()=>{
|
|
286
|
+
resolve({
|
|
287
|
+
elapsedTime: Date.now() - initialTime,
|
|
288
|
+
filename: outputFilename
|
|
289
|
+
});
|
|
290
|
+
}).catch((reason)=>{
|
|
291
|
+
reject(reason);
|
|
292
|
+
});
|
|
293
|
+
}));
|
|
294
|
+
}
|
|
295
|
+
output.push(...await Promise.all(promises));
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return output;
|
|
299
|
+
};
|
|
300
|
+
|
|
239
301
|
const createBuildCommand = (program)=>{
|
|
240
302
|
return createCommand(program, {
|
|
241
303
|
name: "build",
|
|
@@ -295,67 +357,6 @@ const formatSize = (bytes)=>{
|
|
|
295
357
|
return kiloBytes < 1 ? `${bytes} B` : `${kiloBytes.toFixed(2)} kB`;
|
|
296
358
|
};
|
|
297
359
|
|
|
298
|
-
const watch = (configurations)=>{
|
|
299
|
-
process.env.NODE_ENV ??= "development";
|
|
300
|
-
const watcher = watch$1(configurations.map((config)=>({
|
|
301
|
-
...config,
|
|
302
|
-
onLog
|
|
303
|
-
})));
|
|
304
|
-
let startDuration;
|
|
305
|
-
console.clear();
|
|
306
|
-
watcher.on("event", async (event)=>{
|
|
307
|
-
switch(event.code){
|
|
308
|
-
case "START":
|
|
309
|
-
{
|
|
310
|
-
startDuration = Date.now();
|
|
311
|
-
clearLog(`Build in progress...`, {
|
|
312
|
-
type: "information"
|
|
313
|
-
});
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
case "BUNDLE_END":
|
|
317
|
-
await event.result.close();
|
|
318
|
-
break;
|
|
319
|
-
case "END":
|
|
320
|
-
{
|
|
321
|
-
const duration = Date.now() - startDuration;
|
|
322
|
-
clearLog(`Build done in ${duration}ms (at ${new Date().toLocaleTimeString()})`, {
|
|
323
|
-
type: "success"
|
|
324
|
-
});
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
case "ERROR":
|
|
328
|
-
{
|
|
329
|
-
const { error } = event;
|
|
330
|
-
clearLog(`${String(error)}`, {
|
|
331
|
-
type: "error"
|
|
332
|
-
});
|
|
333
|
-
console.error("\n", error);
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
};
|
|
339
|
-
const clearLog = (...input)=>{
|
|
340
|
-
console.clear();
|
|
341
|
-
helpers.message(...input);
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
const createWatchCommand = (program)=>{
|
|
345
|
-
return createCommand(program, {
|
|
346
|
-
name: "watch",
|
|
347
|
-
description: "Watch and rebuild on any code change (development mode)"
|
|
348
|
-
}).task({
|
|
349
|
-
handler (context) {
|
|
350
|
-
watch(createConfigurations({
|
|
351
|
-
minification: context.minification,
|
|
352
|
-
sourceMaps: context.sourceMaps,
|
|
353
|
-
standalone: false
|
|
354
|
-
}));
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
};
|
|
358
|
-
|
|
359
360
|
const createProgram = (...commandBuilders)=>{
|
|
360
361
|
const program = termost("The zero-configuration transpiler and bundler for the web");
|
|
361
362
|
for (const commandBuilder of commandBuilders){
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quickbundle",
|
|
3
|
-
"version": "0.0.0-next-
|
|
3
|
+
"version": "0.0.0-next-63542e6",
|
|
4
4
|
"description": "The zero-configuration transpiler and bundler for the web",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Ayoub Adib",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"typescript": "
|
|
43
|
+
"typescript": "^4.7.0 || ^5.0.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependenciesMeta": {
|
|
46
46
|
"typescript": {
|