bunchee 4.0.1 → 4.1.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/README.md CHANGED
@@ -16,28 +16,24 @@
16
16
 
17
17
  Bunchee makes bundling your library into one file effortless, with zero configuration required. It is built on top of Rollup and SWC ⚡️, allowing you to focus on writing code and generating multiple module types (CommonJS, ESModules) simultaneously.
18
18
 
19
- ## Installation
19
+ ## Quick Start
20
+
21
+ ### Installation
20
22
 
21
23
  ```sh
22
24
  npm install --save-dev bunchee
23
25
  ```
24
26
 
25
- ## Usage
26
-
27
- Create your library
27
+ ### Configuration
28
28
 
29
+ Create your library entry file and package.json.
29
30
  ```sh
30
31
  cd ./my-lib && mkdir src
31
32
  touch ./src/index.ts
32
33
  touch package.json
33
34
  ```
34
35
 
35
- Configure module exports
36
-
37
- [exports sugar in Node.js](https://nodejs.org/api/packages.html#exports-sugar)
38
-
39
- You can use the `exports` field to support different conditions and leverage the same functionality as other bundlers, such as webpack. The exports field allows you to define multiple conditions.
40
-
36
+ Then use use the [exports field in package.json](https://nodejs.org/api/packages.html#exports-sugar) to configure different conditions and leverage the same functionality as other bundlers, such as webpack. The exports field allows you to define multiple conditions.
41
37
  ```json
42
38
  {
43
39
  "exports": {
@@ -50,85 +46,29 @@ You can use the `exports` field to support different conditions and leverage the
50
46
  }
51
47
  ```
52
48
 
53
- Using pure ESM package?
54
-
49
+ If you want to use ESM package, change the `type` field in package.json to `module`, `bunchee` will change the output format to ESM.
55
50
  ```json
56
51
  {
57
52
  "type": "module",
58
- "main": "./dist/index.mjs",
53
+ "exports": {
54
+ "import": "dist/index.mjs",
55
+ "require": "dist/index.cjs"
56
+ },
59
57
  "scripts": {
60
58
  "build": "bunchee"
61
59
  }
62
60
  }
63
61
  ```
64
62
 
65
- Then just run `npm run build`, or `pnpm build` / `yarn build` if you're using these package managers. The output format will based on the exports condition and also the file extension. Given an example:
63
+ Now just run `npm run build` (or `pnpm build` / `yarn build`) if you're using these package managers, `bunchee` will find the entry files and build them.
64
+ The output format will based on the exports condition and also the file extension. Given an example:
66
65
 
67
66
  - It's CommonJS for `require` and ESM for `import` based on the exports condition.
68
67
  - It's CommonJS for `.js` and ESM for `.mjs` based on the extension regardless the exports condition. Then for export condition like "node" you could choose the format with your extension.
69
68
 
70
- ## Configuration
71
-
72
- `bunchee` CLI provides few options to create different bundles or generating types.
73
-
74
- ### CLI Options
75
-
76
- - Output (`-o <file>`): Specify output filename.
77
- - Format (`-f <format>`): Set output format (default: `'esm'`).
78
- - External (`--external <dep,>`): Specifying extra external dependencies, by default it is the list of `dependencies` and `peerDependencies` from `package.json`. Values are separate by comma.
79
- - Target (`--target <target>`): Set ECMAScript target (default: `'es2015'`).
80
- - Runtime (`--runtime <runtime>`): Set build runtime (default: `'browser'`).
81
- - Environment (`--env <env,>`): Define environment variables. (default: `NODE_ENV`, separate by comma)
82
- - Working Directory (`--cwd <cwd>`): Set current working directory where containing `package.json`.
83
- - Types (`--dts`): Generate TypeScript declaration files along with assets.
84
- - Minify (`-m`): Compress output.
85
- - Watch (`-w`): Watch for source file changes.
86
-
87
- ### Basic Example
88
-
89
- ```sh
90
- cd <project-root-dir>
91
-
92
- # specifying input, output and format
93
-
94
- bunchee ./src/index.js -f cjs -o ./dist/bundle.js
95
- bunchee ./src/index.js -f esm -o ./dist/bundle.esm.js
96
-
97
- # build node.js library, or change target to es2019
98
- bunchee ./src/index.js --runtime node --target es2019
99
- ```
100
-
101
- #### Specifying extra external dependencies
102
-
103
- If you want to mark specific dependencies as external and not include them in the bundle, use the `--external` option followed by a comma-separated list of dependency names:
104
-
105
- ```sh
106
- bunchee --external=dependency1,dependency2,dependency3
107
- ```
108
-
109
- Replace `dependency1`, `dependency2`, and `dependency3` with the names of the dependencies you want to exclude from the bundle.
110
-
111
- #### Bundling everything without external dependencies
112
-
113
- To bundle your library without external dependencies, use the `--no-external` option:
114
-
115
- ```sh
116
- bunchee --no-external
117
- ```
118
-
119
- This will include all dependencies within your output bundle.
120
-
121
- ### Environment Variables
122
-
123
- To pass environment variables to your bundled code, use the --env option followed by a comma-separated list of environment variable names:
124
-
125
- ```bash
126
- bunchee --env=ENV1,ENV2,ENV3
127
- ```
128
-
129
- Replace `ENV1`, `ENV2`, and `ENV3` with the names of the environment variables you want to include in your bundled code. These environment variables will be inlined during the bundling process.
69
+ ## Usage
130
70
 
131
- ### Entry Files Convention
71
+ ### File Conventions
132
72
 
133
73
  While `exports` field is becoming the standard of exporting in node.js, bunchee also supports to build multiple exports all in one command.
134
74
 
@@ -169,7 +109,7 @@ Then you need to add two entry files `index.ts` and `lite.ts` in project root di
169
109
 
170
110
  It will also look up for `index.<ext>` file under the directory having the name of the export path. For example, if you have `"./lite": "./dist/lite.js"` in exports field, then it will look up for `./lite/index.js` as the entry file as well.
171
111
 
172
- ### Use Exports Conventions
112
+ ### Multiple Runtime
173
113
 
174
114
  For exports condition like `react-native`, `react-server` and `edge-light` as they're special platforms, they could have different exports or different code conditions. In this case bunchee provides an override input source file convention if you want to build them as different code bundle.
175
115
 
@@ -185,25 +125,8 @@ For instance:
185
125
  }
186
126
  ```
187
127
 
188
- You can use `index.<export-type>.<ext>` to override the input source file for specific export name. Or using `<export-path>/index.<export-type>.<ext>` also works. Such as:
189
-
190
- ```
191
- |- src/
192
- |- index/.ts
193
- |- index.react-server.ts
194
- |- index.edge-light.ts
195
- ```
196
-
197
- This will match the export name `"react-server"` and `"edge-light"` then use the corresponding input source file to build the bundle.
198
-
199
- #### Package lint
200
-
201
- `bunchee` has support for checking the package bundles are matched with package exports configuration.
202
-
203
-
204
128
  ### Executables
205
129
 
206
-
207
130
  To build executable files with the `bin` field in package.json, `bunchee` requires you to create the `bin` directory under `src` directory. The source file matching will be same as the entry files convention.
208
131
 
209
132
  For example:
@@ -244,6 +167,87 @@ This will match the `bin` field in package.json as:
244
167
 
245
168
  > Note: For multiple `bin` files, the filename should match the key name in the `bin` field.
246
169
 
170
+
171
+ ### Server Components
172
+
173
+ `bunchee` supports to build server components and server actions with library directives like `"use client"` or `"use server"`. It will generate the corresponding chunks for client and server that scope the client and server boundaries properly.
174
+ Then when the library is integrated to an app such as Next.js, app bundler can transform the client components and server actions correctly and maximum the benefits.
175
+
176
+ If you're using `"use client"` or `"use server"` in entry file, then it will be preserved on top and the dist file of that entry will become a client component.
177
+ If you're using `"use client"` or `"use server"` in a file that used as a dependency for an entry, then that file containing directives be split into a separate chunk and hoist the directives to the top of the chunk.
178
+
179
+ ### CLI
180
+
181
+ #### CLI Options
182
+
183
+ `bunchee` CLI provides few options to create different bundles or generating types.
184
+
185
+ - Output (`-o <file>`): Specify output filename.
186
+ - Format (`-f <format>`): Set output format (default: `'esm'`).
187
+ - External (`--external <dep,>`): Specifying extra external dependencies, by default it is the list of `dependencies` and `peerDependencies` from `package.json`. Values are separate by comma.
188
+ - Target (`--target <target>`): Set ECMAScript target (default: `'es2015'`).
189
+ - Runtime (`--runtime <runtime>`): Set build runtime (default: `'browser'`).
190
+ - Environment (`--env <env,>`): Define environment variables. (default: `NODE_ENV`, separate by comma)
191
+ - Working Directory (`--cwd <cwd>`): Set current working directory where containing `package.json`.
192
+ - Types (`--dts`): Generate TypeScript declaration files along with assets.
193
+ - Minify (`-m`): Compress output.
194
+ - Watch (`-w`): Watch for source file changes.
195
+
196
+ ```sh
197
+ cd <project-root-dir>
198
+
199
+ # specifying input, output and format
200
+
201
+ bunchee ./src/index.js -f cjs -o ./dist/bundle.js
202
+ bunchee ./src/index.js -f esm -o ./dist/bundle.esm.js
203
+
204
+ # build node.js library, or change target to es2019
205
+ bunchee ./src/index.js --runtime node --target es2019
206
+ ```
207
+
208
+ #### Specifying extra external dependencies
209
+
210
+ If you want to mark specific dependencies as external and not include them in the bundle, use the `--external` option followed by a comma-separated list of dependency names:
211
+
212
+ ```sh
213
+ bunchee --external=dependency1,dependency2,dependency3
214
+ ```
215
+
216
+ Replace `dependency1`, `dependency2`, and `dependency3` with the names of the dependencies you want to exclude from the bundle.
217
+
218
+ #### Bundling everything without external dependencies
219
+
220
+ To bundle your library without external dependencies, use the `--no-external` option:
221
+
222
+ ```sh
223
+ bunchee --no-external
224
+ ```
225
+
226
+ This will include all dependencies within your output bundle.
227
+
228
+ ### Environment Variables
229
+
230
+ To pass environment variables to your bundled code, use the --env option followed by a comma-separated list of environment variable names:
231
+
232
+ ```bash
233
+ bunchee --env=ENV1,ENV2,ENV3
234
+ ```
235
+
236
+ Replace `ENV1`, `ENV2`, and `ENV3` with the names of the environment variables you want to include in your bundled code. These environment variables will be inlined during the bundling process.
237
+
238
+
239
+ You can use `index.<export-type>.<ext>` to override the input source file for specific export name. Or using `<export-path>/index.<export-type>.<ext>` also works. Such as:
240
+
241
+ ```
242
+ |- src/
243
+ |- index/.ts
244
+ |- index.react-server.ts
245
+ |- index.edge-light.ts
246
+ ```
247
+
248
+ This will match the export name `"react-server"` and `"edge-light"` then use the corresponding input source file to build the bundle.
249
+
250
+
247
251
  ### Wildcard Exports
248
252
 
249
253
  Bunchee implements the Node.js feature of using the asterisk `*` as a wildcard to match the exportable entry files.
@@ -389,6 +393,11 @@ Bunchee offers a convenient watch mode for rebuilding your library whenever chan
389
393
 
390
394
  If you specify `target` option in `tsconfig.json`, then you don't have to pass it again through CLI.
391
395
 
396
+ #### Package lint
397
+
398
+ `bunchee` has support for checking the package bundles are matched with package exports configuration.
399
+
400
+
392
401
  ### License
393
402
 
394
403
  MIT
package/dist/bin/cli.js CHANGED
@@ -54,7 +54,7 @@ async function fileExists(filePath) {
54
54
  }
55
55
  }
56
56
 
57
- var version = "4.0.1";
57
+ var version = "4.1.0";
58
58
 
59
59
  const helpMessage = `
60
60
  Usage: bunchee [options]
package/dist/index.js CHANGED
@@ -193,15 +193,40 @@ function rawContent({ exclude }) {
193
193
  '**/*.txt'
194
194
  ], exclude);
195
195
  return {
196
- name: "string",
196
+ name: 'string',
197
197
  transform (code, id) {
198
198
  if (filter(id)) {
199
199
  return {
200
- code: `export default ${JSON.stringify(code)}`,
201
- map: undefined
200
+ code: `const data = ${JSON.stringify(code)};\nexport default data;`,
201
+ map: null
202
+ };
203
+ }
204
+ return null;
205
+ }
206
+ };
207
+ }
208
+
209
+ function prependDirectives() {
210
+ return {
211
+ name: 'prependDirective',
212
+ transform: {
213
+ order: 'post',
214
+ handler (code, id) {
215
+ var _moduleInfo_meta;
216
+ const moduleInfo = this.getModuleInfo(id);
217
+ if (moduleInfo == null ? void 0 : (_moduleInfo_meta = moduleInfo.meta) == null ? void 0 : _moduleInfo_meta.preserveDirectives) {
218
+ const firstDirective = moduleInfo.meta.preserveDirectives.directives[0];
219
+ if (firstDirective) {
220
+ const directive = firstDirective.value;
221
+ const directiveCode = `'${directive}';`;
222
+ return directiveCode + '\n' + code;
223
+ }
224
+ }
225
+ return {
226
+ code,
227
+ map: null
202
228
  };
203
229
  }
204
- return undefined;
205
230
  }
206
231
  };
207
232
  }
@@ -660,6 +685,7 @@ async function buildInputConfig(entry, pkg, options, cwd, { tsConfigPath, tsComp
660
685
  exclude: /node_modules/
661
686
  }),
662
687
  preserveDirectives__default.default(),
688
+ prependDirectives(),
663
689
  replace__default.default({
664
690
  values: getBuildEnv(options.env || []),
665
691
  preventAssignment: true
@@ -727,6 +753,22 @@ function hasEsmExport(exportPaths, tsCompilerOptions) {
727
753
  }
728
754
  return Boolean(hasEsm || (tsCompilerOptions == null ? void 0 : tsCompilerOptions.esModuleInterop));
729
755
  }
756
+ const splitChunks = (id, ctx)=>{
757
+ const moduleInfo = ctx.getModuleInfo(id);
758
+ const moduleMeta = moduleInfo == null ? void 0 : moduleInfo.meta;
759
+ if (!moduleInfo || !moduleMeta) {
760
+ return;
761
+ }
762
+ const directives = (moduleMeta.preserveDirectives || {
763
+ directives: []
764
+ }).directives.map((d)=>d.replace(/^use /, '')).filter((d)=>d !== 'strict');
765
+ const moduleLayer = directives[0];
766
+ if (moduleLayer && !moduleMeta.isEntry) {
767
+ const chunkName = path__default.default.basename(id, path__default.default.extname(id));
768
+ return `${chunkName}-${moduleLayer}`;
769
+ }
770
+ return;
771
+ };
730
772
  function buildOutputConfigs(pkg, exportPaths, options, exportCondition, cwd, { tsCompilerOptions }, dts) {
731
773
  const { format } = options;
732
774
  // Add esm mark and interop helper if esm export is detected
@@ -737,16 +779,14 @@ function buildOutputConfigs(pkg, exportPaths, options, exportCondition, cwd, { t
737
779
  const name = filenameWithoutExtension(file);
738
780
  // TODO: simplify dts file name detection
739
781
  const dtsFile = file ? file : exportCondition.export['types'] ? path.resolve(cwd, exportCondition.export['types']) : path.resolve(dtsDir, (exportCondition.name === '.' ? 'index' : exportCondition.name) + '.d.ts');
740
- // If there's dts file, use `output.file`
741
- const dtsPathConfig = dtsFile ? {
742
- file: dtsFile
743
- } : {
744
- dir: dtsDir
782
+ const dtsPathConfig = {
783
+ dir: dtsFile ? path.dirname(dtsFile) : dtsDir
745
784
  };
785
+ const outputFile = dtsFile || file;
746
786
  return {
747
787
  name: pkg.name || name,
748
788
  ...dts ? dtsPathConfig : {
749
- file: file
789
+ dir: path.dirname(outputFile)
750
790
  },
751
791
  format,
752
792
  exports: 'named',
@@ -754,7 +794,10 @@ function buildOutputConfigs(pkg, exportPaths, options, exportCondition, cwd, { t
754
794
  interop: 'auto',
755
795
  freeze: false,
756
796
  strict: false,
757
- sourcemap: options.sourcemap
797
+ sourcemap: options.sourcemap,
798
+ manualChunks: splitChunks,
799
+ chunkFileNames: '[name]-[hash].js',
800
+ entryFileNames: path.basename(outputFile)
758
801
  };
759
802
  }
760
803
  // build configs for each entry from package exports
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunchee",
3
- "version": "4.0.1",
3
+ "version": "4.1.0",
4
4
  "description": "zero config bundler for js/ts/jsx libraries",
5
5
  "bin": "./dist/bin/cli.js",
6
6
  "main": "./dist/index.js",
@@ -8,6 +8,7 @@
8
8
  "scripts": {
9
9
  "test": "jest --env node",
10
10
  "test:update": "TEST_UPDATE_SNAPSHOT=1 pnpm test",
11
+ "test:post": "POST_BUILD=1 pnpm jest test/compile.test.ts test/integration.test.ts",
11
12
  "clean": "rm -rf ./dist",
12
13
  "typecheck": "tsc --noEmit",
13
14
  "prepublishOnly": "pnpm clean && pnpm build && chmod +x ./dist/bin/cli.js && pnpm test",
@@ -59,7 +60,7 @@
59
60
  "rollup": "^4.6.1",
60
61
  "rollup-plugin-dts": "^6.1.0",
61
62
  "rollup-plugin-swc3": "^0.11.0",
62
- "rollup-preserve-directives": "^1.0.1",
63
+ "rollup-preserve-directives": "^1.1.0",
63
64
  "tslib": "^2.6.2"
64
65
  },
65
66
  "peerDependencies": {