bunchee 6.3.0 → 6.3.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/README.md +233 -209
- package/dist/bin/cli.js +11 -7
- package/dist/index.js +37 -22
- package/package.json +14 -13
package/README.md
CHANGED
|
@@ -14,8 +14,11 @@
|
|
|
14
14
|
</a>
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
**bunchee** is a zero-configuration bundler designed to streamline package building by adhering to the `exports` field in your **package.json**. Powered by Rollup and SWC ⚡️, it generates output based on your config, supporting both CommonJS and ESModules.
|
|
20
|
+
|
|
21
|
+
By using the standard `exports` configuration as the single source of truth, **bunchee** automatically aligns entry file conventions with your exports, ensuring seamless and efficient builds.
|
|
19
22
|
|
|
20
23
|
## Quick Start
|
|
21
24
|
|
|
@@ -36,14 +39,14 @@ mkdir src && touch ./src/index.ts && touch package.json
|
|
|
36
39
|
|
|
37
40
|
Add the exports in `package.json`.
|
|
38
41
|
|
|
39
|
-
```
|
|
42
|
+
```json5
|
|
40
43
|
{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
44
|
+
name: 'coffee',
|
|
45
|
+
type: 'module',
|
|
46
|
+
main: './dist/index.js',
|
|
47
|
+
scripts: {
|
|
48
|
+
build: 'bunchee',
|
|
49
|
+
},
|
|
47
50
|
}
|
|
48
51
|
```
|
|
49
52
|
|
|
@@ -53,192 +56,118 @@ Add the exports in `package.json`.
|
|
|
53
56
|
npm run build
|
|
54
57
|
```
|
|
55
58
|
|
|
56
|
-
|
|
57
|
-
Simply like Node.js module resolution, each export name will match the file in `src/` directory.
|
|
58
|
-
|
|
59
|
-
For example:
|
|
60
|
-
|
|
61
|
-
- `src/index.ts` will match the exports name `"."` or the only main export.
|
|
62
|
-
- `src/lite.ts` will match the exports name `"./lite"`.
|
|
63
|
-
- `src/react/index.ts` will match the exports name `"./react"`.
|
|
64
|
-
|
|
65
|
-
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.
|
|
66
|
-
The output format will based on the exports condition and also the file extension. Given an example:
|
|
67
|
-
|
|
68
|
-
- It's CommonJS for `require` and ESM for `import` based on the exports condition.
|
|
69
|
-
- 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.
|
|
70
|
-
|
|
71
|
-
> [!NOTE]
|
|
72
|
-
> All the `dependencies` and `peerDependencies` will be marked as external automatically and not included in the bundle. If you want to include them in the bundle, you can use the `--no-external` option.
|
|
73
|
-
|
|
74
|
-
#### Prepare Package
|
|
75
|
-
|
|
76
|
-
```sh
|
|
77
|
-
# Use bunchee to prepare package.json configuration
|
|
78
|
-
npm exec bunchee prepare
|
|
79
|
-
# "If you're using other package manager such as pnpm"
|
|
80
|
-
# pnpm bunchee prepare
|
|
59
|
+
## Usage
|
|
81
60
|
|
|
82
|
-
|
|
83
|
-
# npx bunchee@latest prepare
|
|
84
|
-
```
|
|
61
|
+
### Entry Files
|
|
85
62
|
|
|
86
|
-
|
|
63
|
+
Then files in `src` folders will be treated as entry files and match the export names in package.json.
|
|
64
|
+
Simply like Node.js module resolution, each export name will match the file in `src/` directory.
|
|
87
65
|
|
|
88
|
-
|
|
89
|
-
<summary>JavaScript ESModule</summary>
|
|
66
|
+
Here's a example of entry files and exports configuration:
|
|
90
67
|
|
|
91
|
-
|
|
68
|
+
| **File** | **Exports Name** |
|
|
69
|
+
| -------------------- | ---------------------- |
|
|
70
|
+
| `src/index.ts` | `"."` (default export) |
|
|
71
|
+
| `src/lite.ts` | `"./lite"` |
|
|
72
|
+
| `src/react/index.ts` | `"./react"` |
|
|
92
73
|
|
|
93
|
-
```
|
|
74
|
+
```json5
|
|
94
75
|
{
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
".": "./dist/es/index.js",
|
|
99
|
-
"./react": "./dist/es/react.js"
|
|
76
|
+
name: 'coffee',
|
|
77
|
+
scripts: {
|
|
78
|
+
build: 'bunchee',
|
|
100
79
|
},
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
</details>
|
|
108
|
-
|
|
109
|
-
<details>
|
|
110
|
-
<summary>TypeScript</summary>
|
|
111
|
-
|
|
112
|
-
If you're build a TypeScript library, separate the types from the main entry file and specify the types path in package.json. Types exports need to stay on the top of each export with `types` condition, and you can use `default` condition for the JS bundle file.
|
|
113
|
-
|
|
114
|
-
```json
|
|
115
|
-
{
|
|
116
|
-
"files": ["dist"],
|
|
117
|
-
"type": "module",
|
|
118
|
-
"main": "./dist/index.js",
|
|
119
|
-
"exports": {
|
|
120
|
-
".": {
|
|
121
|
-
"types": "./dist/index.d.ts",
|
|
122
|
-
"default": "./dist/index.js"
|
|
80
|
+
type: 'module',
|
|
81
|
+
exports: {
|
|
82
|
+
// entry: ./src/index.ts
|
|
83
|
+
'.': {
|
|
84
|
+
import: './dist/index.js',
|
|
85
|
+
require: './dist/index.cjs',
|
|
123
86
|
},
|
|
124
|
-
"./react": {
|
|
125
|
-
"types": "./dist/react/index.d.ts",
|
|
126
|
-
"default": "./dist/react/index.js"
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
"scripts": {
|
|
130
|
-
"build": "bunchee"
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
</details>
|
|
136
87
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
If you're using TypeScript with Node 10 and Node 16 module resolution, you can use the `types` field in package.json to specify the types path. Then `bunchee` will generate the types file with the same extension as the main entry file.
|
|
88
|
+
// entry: ./src/lite.ts
|
|
89
|
+
'./lite': './dist/lite.js',
|
|
140
90
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
```json
|
|
144
|
-
{
|
|
145
|
-
"files": ["dist"],
|
|
146
|
-
"type": "module",
|
|
147
|
-
"main": "./dist/index.js",
|
|
148
|
-
"module": "./dist/index.js",
|
|
149
|
-
"types": "./dist/index.d.ts",
|
|
150
|
-
"exports": {
|
|
151
|
-
"import": {
|
|
152
|
-
"types": "./dist/index.d.ts",
|
|
153
|
-
"default": "./dist/index.js"
|
|
154
|
-
},
|
|
155
|
-
"require": {
|
|
156
|
-
"types": "./dist/index.d.cts",
|
|
157
|
-
"default": "./dist/index.cjs"
|
|
158
|
-
}
|
|
91
|
+
// entry: ./src/react/index.ts
|
|
92
|
+
'./react': './dist/react.js',
|
|
159
93
|
},
|
|
160
|
-
"scripts": {
|
|
161
|
-
"build": "bunchee"
|
|
162
|
-
}
|
|
163
94
|
}
|
|
164
95
|
```
|
|
165
96
|
|
|
166
|
-
|
|
97
|
+
### Output Formats
|
|
167
98
|
|
|
168
|
-
|
|
99
|
+
**bunchee** detects the format of each entry-point based on export condition type or the file extension. It supports the following output formats:
|
|
169
100
|
|
|
170
|
-
`
|
|
101
|
+
| `package.json` Field | Output format |
|
|
102
|
+
| -------------------- | -------------------------------- |
|
|
103
|
+
| `main` | Default |
|
|
104
|
+
| `types` | TypeScript declaration |
|
|
105
|
+
| `exports` | Default |
|
|
106
|
+
| `exports.require` | CommonJS |
|
|
107
|
+
| `exports.import` | Default |
|
|
108
|
+
| `exports.types` | TypeScript declaration of export |
|
|
109
|
+
| `bin` | Default |
|
|
110
|
+
| `bin.<name>` | Default |
|
|
171
111
|
|
|
172
|
-
|
|
173
|
-
- if the entry files are matched with the exports paths.
|
|
112
|
+
The **Default** output format is determined by the file extension:
|
|
174
113
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
114
|
+
| File Extension | Output format |
|
|
115
|
+
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
116
|
+
| `.js` | Determined by `package.json#type`, CommonJS by default |
|
|
117
|
+
| `.cjs` | [CommonJS](https://nodejs.org/api/packages.html#:~:text=Files%20ending%20with%20.cjs%20are%20always%20loaded%20as%20CommonJS%20regardless%20of%20the%20nearest%20parent%20package.json) |
|
|
118
|
+
| `.mjs` | [ECMAScript Modules](https://nodejs.org/api/modules.html#the-mjs-extension) |
|
|
179
119
|
|
|
180
|
-
|
|
120
|
+
### External Dependencies
|
|
181
121
|
|
|
182
|
-
|
|
122
|
+
The `dependencies` and `peerDependencies` will be marked as externalized and wont be included in the bundle. If you want to include them in the bundle, you can use the `--no-external` option. Or you can import the `devDependencies` in your source code to bundle them.
|
|
183
123
|
|
|
184
|
-
|
|
124
|
+
```json5
|
|
125
|
+
{
|
|
126
|
+
// Externalized
|
|
127
|
+
dependencies: {
|
|
128
|
+
/* ... */
|
|
129
|
+
},
|
|
130
|
+
peerDependencies: {
|
|
131
|
+
/* ... */
|
|
132
|
+
},
|
|
185
133
|
|
|
186
|
-
|
|
134
|
+
// Bundled
|
|
135
|
+
devDependencies: {
|
|
136
|
+
/* ... */
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
```
|
|
187
140
|
|
|
188
|
-
|
|
189
|
-
- `<cwd>/src/lite.ts` will match `"./lite"` export name.
|
|
141
|
+
### Multiple Runtime
|
|
190
142
|
|
|
191
|
-
|
|
192
|
-
Briefly, the entry files from `src/` folder will do matching with `exports` conditions from `package.json` and build them into bundles.
|
|
143
|
+
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.
|
|
193
144
|
|
|
194
|
-
|
|
145
|
+
For instance:
|
|
195
146
|
|
|
196
|
-
```
|
|
147
|
+
```json5
|
|
197
148
|
{
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
149
|
+
exports: {
|
|
150
|
+
'react-server': './dist/react-server.mjs',
|
|
151
|
+
'edge-light': './dist/edge-light.mjs',
|
|
152
|
+
import: './dist/index.mjs',
|
|
201
153
|
},
|
|
202
|
-
"type": "module",
|
|
203
|
-
"exports": {
|
|
204
|
-
"./lite": "./dist/lite.js",
|
|
205
|
-
".": {
|
|
206
|
-
"import": "./dist/index.js",
|
|
207
|
-
"require": "./dist/index.cjs"
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
154
|
}
|
|
211
155
|
```
|
|
212
156
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
```
|
|
216
|
-
- my-lib/
|
|
217
|
-
|- src/
|
|
218
|
-
|- lite.ts
|
|
219
|
-
|- index.ts
|
|
220
|
-
|- package.json
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
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.
|
|
224
|
-
|
|
225
|
-
### Multiple Runtime
|
|
226
|
-
|
|
227
|
-
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.
|
|
157
|
+
### Path Alias
|
|
228
158
|
|
|
229
|
-
|
|
159
|
+
`bunchee` supports both TypeScript `paths` config and Node.js [`imports field`](https://nodejs.org/api/packages.html#subpath-imports) in `package.json` for path aliasing. It will resolve the path alias to the correct file path. If you're using modern TypeScript versions, you can also directly configure the `imports` field in `package.json` and it will work as a charm.
|
|
230
160
|
|
|
231
|
-
```
|
|
161
|
+
```json5
|
|
162
|
+
// package.json
|
|
232
163
|
{
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
"import": "./dist/index.mjs"
|
|
237
|
-
}
|
|
164
|
+
imports: {
|
|
165
|
+
'#util': './src/utils.ts',
|
|
166
|
+
},
|
|
238
167
|
}
|
|
239
168
|
```
|
|
240
169
|
|
|
241
|
-
###
|
|
170
|
+
### Binary CLI
|
|
242
171
|
|
|
243
172
|
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.
|
|
244
173
|
|
|
@@ -252,45 +181,49 @@ For example:
|
|
|
252
181
|
|
|
253
182
|
This will match the `bin` field in package.json as:
|
|
254
183
|
|
|
255
|
-
```
|
|
184
|
+
```json5
|
|
256
185
|
{
|
|
257
|
-
|
|
186
|
+
bin: './dist/bin.js',
|
|
258
187
|
}
|
|
259
188
|
```
|
|
260
189
|
|
|
261
|
-
|
|
190
|
+
If you have multiple binaries, you can create multiple files under the `bin` directory. Check the below example for more details.
|
|
191
|
+
|
|
192
|
+
<details>
|
|
193
|
+
<summary>Multiple Binaries</summary>
|
|
194
|
+
|
|
195
|
+
For named executable files, you can create multiple files under the `bin` directory.
|
|
262
196
|
|
|
263
197
|
```bash
|
|
264
198
|
|- src/
|
|
265
199
|
|- bin/
|
|
266
|
-
|
|
267
|
-
|- bar.ts
|
|
200
|
+
|
|
268
201
|
```
|
|
269
202
|
|
|
270
203
|
This will match the `bin` field in package.json as:
|
|
271
204
|
|
|
272
|
-
```
|
|
205
|
+
```json5
|
|
273
206
|
{
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
207
|
+
bin: {
|
|
208
|
+
foo: './dist/bin/a.js',
|
|
209
|
+
bar: './dist/bin/b.js',
|
|
210
|
+
},
|
|
278
211
|
}
|
|
279
212
|
```
|
|
280
213
|
|
|
214
|
+
</details>
|
|
215
|
+
|
|
281
216
|
> Note: For multiple `bin` files, the filename should match the key name in the `bin` field.
|
|
282
217
|
|
|
283
218
|
### Server Components
|
|
284
219
|
|
|
285
|
-
|
|
286
|
-
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.
|
|
287
|
-
|
|
288
|
-
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.
|
|
289
|
-
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.
|
|
220
|
+
**bunchee** supports building React Server Components and Server Actions with directives like `"use client"` or `"use server"`. It generates separate chunks for the server or client boundaries. When integrated to framework like Next.js, it can correctly handles the boundaries with the split chunks.
|
|
290
221
|
|
|
291
222
|
### Shared Modules
|
|
292
223
|
|
|
293
|
-
|
|
224
|
+
Sometimes, you may want to share a chunk across multiple bundles without promoting it to separate entries or exports, such as single instance of React context module, shared utils, etc. In these cases, **shared modules** will help you achieve the goal. Files or directories **prefixed with an underscore** (`_<name>.<ext>` or `_<name>/**`) will be treated as **shared modules**.
|
|
225
|
+
|
|
226
|
+
These conventions are kept private and are not going to be treat as shared modules or entry points. For example, test or mock files like `_foo/a.test.ts` will be ignored and not included as shared modules.
|
|
294
227
|
|
|
295
228
|
<details>
|
|
296
229
|
<summary>Shared Utils Example</summary>
|
|
@@ -351,38 +284,23 @@ This convention keeps shared modules private while enabling efficient bundling a
|
|
|
351
284
|
|
|
352
285
|
#### CLI Options
|
|
353
286
|
|
|
354
|
-
`bunchee` CLI provides few options to create different bundles or generating types.
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
- Format (`-f <format>`): Set output format (default: `'esm'`).
|
|
358
|
-
- 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.
|
|
359
|
-
- Target (`--target <target>`): Set ECMAScript target (default: `'es2015'`).
|
|
360
|
-
- Runtime (`--runtime <runtime>`): Set build runtime (default: `'browser'`).
|
|
361
|
-
- Environment (`--env <env,>`): Define environment variables. (default: `[]`, separate by comma)
|
|
362
|
-
- Working Directory (`--cwd <cwd>`): Set current working directory where containing `package.json`.
|
|
363
|
-
- Minify (`-m`): Compress output.
|
|
364
|
-
- Watch (`-w`): Watch for source file changes.
|
|
365
|
-
- No Clean(`--no-clean`): Do not clean the dist folder before building. (default: `false`)
|
|
366
|
-
- TSConfig (`--tsconfig <path>`): Specify the path to the TypeScript configuration file. (default: `tsconfig.json`)
|
|
367
|
-
- Bundle Types (`--dts-bundle`): Bundle type declaration files. (default: `false`)
|
|
287
|
+
`bunchee` CLI provides few options to create different bundles or generating types. Call `bunchee --help` to see the help information in the terminal.
|
|
288
|
+
|
|
289
|
+
Here are the available options for the CLI:
|
|
368
290
|
|
|
369
291
|
```sh
|
|
370
292
|
cd <project-root-dir>
|
|
371
293
|
|
|
372
|
-
#
|
|
294
|
+
# Build based on the package.json configuration
|
|
295
|
+
bunchee --runtime node -o ./dist/bundle.js
|
|
296
|
+
bunchee -f esm -o --target es2022 ./dist/bundle.esm.js
|
|
373
297
|
|
|
374
|
-
|
|
375
|
-
bunchee ./src/
|
|
376
|
-
|
|
377
|
-
# build node.js library, or change target to es2019
|
|
378
|
-
bunchee ./src/index.js --runtime node --target es2019
|
|
298
|
+
# Specify the input source file
|
|
299
|
+
bunchee ./src/foo.ts -o ./dist/foo.js
|
|
379
300
|
```
|
|
380
301
|
|
|
381
302
|
#### Specifying extra external dependencies
|
|
382
303
|
|
|
383
|
-
By default, `bunchee` will mark all the `dependencies` and `peerDependencies` as externals so you don't need to pass them as CLI args.
|
|
384
|
-
But if there's any dependency that used but not in the dependency list and you want to mark as external, you can use the `--external` option to specify them.
|
|
385
|
-
|
|
386
304
|
```sh
|
|
387
305
|
bunchee --external=dep1,dep2,dep3
|
|
388
306
|
```
|
|
@@ -399,6 +317,112 @@ bunchee --no-external
|
|
|
399
317
|
|
|
400
318
|
This will include all dependencies within your output bundle.
|
|
401
319
|
|
|
320
|
+
#### Prepare Package
|
|
321
|
+
|
|
322
|
+
```sh
|
|
323
|
+
# Use bunchee to prepare package.json configuration
|
|
324
|
+
npm exec bunchee prepare
|
|
325
|
+
# "If you're using other package manager such as pnpm"
|
|
326
|
+
# pnpm bunchee prepare
|
|
327
|
+
|
|
328
|
+
# "Or use with npx"
|
|
329
|
+
# npx bunchee@latest prepare
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Or you can checkout the following cases to configure your package.json.
|
|
333
|
+
|
|
334
|
+
<details>
|
|
335
|
+
<summary>JavaScript ESModule</summary>
|
|
336
|
+
|
|
337
|
+
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.
|
|
338
|
+
|
|
339
|
+
```json5
|
|
340
|
+
{
|
|
341
|
+
files: ['dist'],
|
|
342
|
+
type: 'module',
|
|
343
|
+
exports: {
|
|
344
|
+
'.': './dist/es/index.js',
|
|
345
|
+
'./react': './dist/es/react.js',
|
|
346
|
+
},
|
|
347
|
+
scripts: {
|
|
348
|
+
build: 'bunchee',
|
|
349
|
+
},
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
</details>
|
|
354
|
+
|
|
355
|
+
<details>
|
|
356
|
+
<summary>TypeScript</summary>
|
|
357
|
+
|
|
358
|
+
If you're build a TypeScript library, separate the types from the main entry file and specify the types path in package.json. Types exports need to stay on the top of each export with `types` condition, and you can use `default` condition for the JS bundle file.
|
|
359
|
+
|
|
360
|
+
```json5
|
|
361
|
+
{
|
|
362
|
+
files: ['dist'],
|
|
363
|
+
type: 'module',
|
|
364
|
+
main: './dist/index.js',
|
|
365
|
+
exports: {
|
|
366
|
+
'.': {
|
|
367
|
+
types: './dist/index.d.ts',
|
|
368
|
+
default: './dist/index.js',
|
|
369
|
+
},
|
|
370
|
+
'./react': {
|
|
371
|
+
types: './dist/react/index.d.ts',
|
|
372
|
+
default: './dist/react/index.js',
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
scripts: {
|
|
376
|
+
build: 'bunchee',
|
|
377
|
+
},
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
</details>
|
|
382
|
+
|
|
383
|
+
<details>
|
|
384
|
+
<summary>Hybrid (CJS & ESM) Module Resolution with TypeScript</summary>
|
|
385
|
+
If you're using TypeScript with Node 10 and Node 16 module resolution, you can use the `types` field in package.json to specify the types path. Then `bunchee` will generate the types file with the same extension as the main entry file.
|
|
386
|
+
|
|
387
|
+
_NOTE_: When you're using `.mjs` or `.cjs` extensions with TypeScript and modern module resolution (above node16), TypeScript will require specific type declaration files like `.d.mts` or `.d.cts` to match the extension. `bunchee` can automatically generate them to match the types to match the condition and extensions.
|
|
388
|
+
|
|
389
|
+
```json5
|
|
390
|
+
{
|
|
391
|
+
files: ['dist'],
|
|
392
|
+
type: 'module',
|
|
393
|
+
main: './dist/index.js',
|
|
394
|
+
module: './dist/index.js',
|
|
395
|
+
types: './dist/index.d.ts',
|
|
396
|
+
exports: {
|
|
397
|
+
import: {
|
|
398
|
+
types: './dist/index.d.ts',
|
|
399
|
+
default: './dist/index.js',
|
|
400
|
+
},
|
|
401
|
+
require: {
|
|
402
|
+
types: './dist/index.d.cts',
|
|
403
|
+
default: './dist/index.cjs',
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
scripts: {
|
|
407
|
+
build: 'bunchee',
|
|
408
|
+
},
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
</details>
|
|
413
|
+
|
|
414
|
+
#### Lint Package
|
|
415
|
+
|
|
416
|
+
`lint` command will check the package.json configuration is valid or not, it can valid few things like:
|
|
417
|
+
|
|
418
|
+
- if the entry files are matched with the exports conditions.
|
|
419
|
+
- if the entry files are matched with the exports paths.
|
|
420
|
+
|
|
421
|
+
```sh
|
|
422
|
+
# Use bunchee to lint if the package.json configuration is valid
|
|
423
|
+
npm exec bunchee lint
|
|
424
|
+
```
|
|
425
|
+
|
|
402
426
|
### Environment Variables
|
|
403
427
|
|
|
404
428
|
To pass environment variables to your bundled code, use the --env option followed by a comma-separated list of environment variable names:
|
|
@@ -424,12 +448,12 @@ This will match the export name `"react-server"` and `"edge-light"` then use the
|
|
|
424
448
|
|
|
425
449
|
`process.env.NODE_ENV` is injected by default if present that you don't need to manually inject yourself. If you need to separate the development build and production build, `bunchee` provides different export conditions for development and production mode with `development` and `production` export conditions.
|
|
426
450
|
|
|
427
|
-
```
|
|
451
|
+
```json5
|
|
428
452
|
{
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
}
|
|
453
|
+
exports: {
|
|
454
|
+
development: './dist/index.development.js',
|
|
455
|
+
production: './dist/index.production.js',
|
|
456
|
+
},
|
|
433
457
|
}
|
|
434
458
|
```
|
|
435
459
|
|
|
@@ -512,14 +536,14 @@ To target a range of browsers, you can use the `browserslist` field in `package.
|
|
|
512
536
|
|
|
513
537
|
For example:
|
|
514
538
|
|
|
515
|
-
```
|
|
539
|
+
```json5
|
|
516
540
|
{
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
]
|
|
541
|
+
browserslist: [
|
|
542
|
+
'last 1 version',
|
|
543
|
+
'> 1%',
|
|
544
|
+
'maintained node versions',
|
|
545
|
+
'not dead',
|
|
546
|
+
],
|
|
523
547
|
}
|
|
524
548
|
```
|
|
525
549
|
|
package/dist/bin/cli.js
CHANGED
|
@@ -69,9 +69,13 @@ const tsExtensions = new Set([
|
|
|
69
69
|
]);
|
|
70
70
|
const DEFAULT_TS_CONFIG = {
|
|
71
71
|
compilerOptions: {
|
|
72
|
+
target: 'ES2022',
|
|
72
73
|
module: 'ESNext',
|
|
73
74
|
moduleResolution: 'bundler'
|
|
74
|
-
}
|
|
75
|
+
},
|
|
76
|
+
include: [
|
|
77
|
+
'src'
|
|
78
|
+
]
|
|
75
79
|
};
|
|
76
80
|
const BINARY_TAG = '$binary';
|
|
77
81
|
const PRIVATE_GLOB_PATTERN = '**/_*/**';
|
|
@@ -642,7 +646,7 @@ function lint$1(pkg) {
|
|
|
642
646
|
}
|
|
643
647
|
}
|
|
644
648
|
|
|
645
|
-
var version = "6.3.
|
|
649
|
+
var version = "6.3.1";
|
|
646
650
|
|
|
647
651
|
async function writeDefaultTsconfig(tsConfigPath) {
|
|
648
652
|
await fs.promises.writeFile(tsConfigPath, JSON.stringify(DEFAULT_TS_CONFIG, null, 2), 'utf-8');
|
|
@@ -1198,11 +1202,11 @@ async function run(args) {
|
|
|
1198
1202
|
cwd,
|
|
1199
1203
|
target,
|
|
1200
1204
|
runtime,
|
|
1201
|
-
external: args.external === null ? null : ((_args_external = args.external) == null ?
|
|
1205
|
+
external: args.external === null ? null : ((_args_external = args.external) == null ? undefined : _args_external.split(',')) || [],
|
|
1202
1206
|
watch: !!watch,
|
|
1203
1207
|
minify: !!minify,
|
|
1204
1208
|
sourcemap: sourcemap === false ? false : true,
|
|
1205
|
-
env: (env == null ?
|
|
1209
|
+
env: (env == null ? undefined : env.split(',')) || [],
|
|
1206
1210
|
clean,
|
|
1207
1211
|
tsconfig
|
|
1208
1212
|
};
|
|
@@ -1256,7 +1260,7 @@ async function run(args) {
|
|
|
1256
1260
|
if (assetJobs.length === 0) {
|
|
1257
1261
|
logger.warn('The "src" directory does not contain any entry files. ' + 'For proper usage, please refer to the following link: ' + 'https://github.com/huozhi/bunchee#usage');
|
|
1258
1262
|
}
|
|
1259
|
-
const outputState = initialBuildContext == null ?
|
|
1263
|
+
const outputState = initialBuildContext == null ? undefined : initialBuildContext.pluginContext.outputState;
|
|
1260
1264
|
if (outputState) {
|
|
1261
1265
|
logOutputState(outputState.getSizeStats());
|
|
1262
1266
|
}
|
|
@@ -1268,7 +1272,7 @@ async function run(args) {
|
|
|
1268
1272
|
onBuildEnd
|
|
1269
1273
|
};
|
|
1270
1274
|
if (watch) {
|
|
1271
|
-
logger.log(`Watching project
|
|
1275
|
+
logger.log(`Watching changes in the project directory...`);
|
|
1272
1276
|
}
|
|
1273
1277
|
try {
|
|
1274
1278
|
await index_js.bundle(cliEntry, bundleConfig);
|
|
@@ -1279,7 +1283,7 @@ async function run(args) {
|
|
|
1279
1283
|
error: err
|
|
1280
1284
|
};
|
|
1281
1285
|
}
|
|
1282
|
-
if ((buildError == null ?
|
|
1286
|
+
if ((buildError == null ? undefined : buildError.digest) === 'bunchee:not-existed') {
|
|
1283
1287
|
help();
|
|
1284
1288
|
} else {
|
|
1285
1289
|
if (watch) {
|
package/dist/index.js
CHANGED
|
@@ -249,9 +249,13 @@ const tsExtensions = new Set([
|
|
|
249
249
|
]);
|
|
250
250
|
const DEFAULT_TS_CONFIG = {
|
|
251
251
|
compilerOptions: {
|
|
252
|
+
target: 'ES2022',
|
|
252
253
|
module: 'ESNext',
|
|
253
254
|
moduleResolution: 'bundler'
|
|
254
|
-
}
|
|
255
|
+
},
|
|
256
|
+
include: [
|
|
257
|
+
'src'
|
|
258
|
+
]
|
|
255
259
|
};
|
|
256
260
|
const BINARY_TAG = '$binary';
|
|
257
261
|
const PRIVATE_GLOB_PATTERN = '**/_*/**';
|
|
@@ -1003,7 +1007,7 @@ function createOutputState({ entries }) {
|
|
|
1003
1007
|
};
|
|
1004
1008
|
}
|
|
1005
1009
|
|
|
1006
|
-
const
|
|
1010
|
+
const createMemoize = (fn, cacheKey, cacheArg)=>{
|
|
1007
1011
|
const cache = cacheArg || new Map();
|
|
1008
1012
|
return (...args)=>{
|
|
1009
1013
|
const key = cacheKey ? typeof cacheKey === 'function' ? cacheKey(...args) : cacheKey : JSON.stringify({
|
|
@@ -1020,8 +1024,9 @@ const memoize = (fn, cacheKey, cacheArg)=>{
|
|
|
1020
1024
|
};
|
|
1021
1025
|
const memoizeByKey = (fn)=>{
|
|
1022
1026
|
const cache = new Map();
|
|
1023
|
-
return (cacheKey)=>
|
|
1027
|
+
return (cacheKey)=>createMemoize(fn, cacheKey, cache);
|
|
1024
1028
|
};
|
|
1029
|
+
const memoize = (fn)=>createMemoize(fn);
|
|
1025
1030
|
|
|
1026
1031
|
let hasLoggedTsWarning = false;
|
|
1027
1032
|
function resolveTypescript(cwd) {
|
|
@@ -1049,11 +1054,14 @@ function resolveTypescript(cwd) {
|
|
|
1049
1054
|
}
|
|
1050
1055
|
return ts;
|
|
1051
1056
|
}
|
|
1052
|
-
|
|
1053
|
-
let tsCompilerOptions = {};
|
|
1057
|
+
const resolveTsConfigPath = memoize((cwd, tsconfigFileName = 'tsconfig.json')=>{
|
|
1054
1058
|
let tsConfigPath;
|
|
1055
|
-
tsConfigPath = path.resolve(cwd,
|
|
1056
|
-
|
|
1059
|
+
tsConfigPath = path.resolve(cwd, tsconfigFileName);
|
|
1060
|
+
return fileExists(tsConfigPath) ? tsConfigPath : undefined;
|
|
1061
|
+
});
|
|
1062
|
+
function resolveTsConfigHandler(cwd, tsConfigPath) {
|
|
1063
|
+
let tsCompilerOptions = {};
|
|
1064
|
+
if (tsConfigPath) {
|
|
1057
1065
|
// Use the original ts handler to avoid memory leak
|
|
1058
1066
|
const ts = resolveTypescript(cwd);
|
|
1059
1067
|
const basePath = tsConfigPath ? path.dirname(tsConfigPath) : cwd;
|
|
@@ -1067,7 +1075,7 @@ function resolveTsConfigHandler(cwd, tsconfig = 'tsconfig.json') {
|
|
|
1067
1075
|
tsConfigPath
|
|
1068
1076
|
};
|
|
1069
1077
|
}
|
|
1070
|
-
const resolveTsConfig =
|
|
1078
|
+
const resolveTsConfig = memoize(resolveTsConfigHandler);
|
|
1071
1079
|
async function convertCompilerOptions(cwd, json) {
|
|
1072
1080
|
// Use the original ts handler to avoid memory leak
|
|
1073
1081
|
const ts = resolveTypescript(cwd);
|
|
@@ -1345,7 +1353,7 @@ function aliasEntries({ entry: sourceFilePath, conditionNames, entries, format,
|
|
|
1345
1353
|
if (dts) {
|
|
1346
1354
|
var _exportMapEntries_find;
|
|
1347
1355
|
// Find the type with format condition first
|
|
1348
|
-
matchedBundlePath = (_exportMapEntries_find = exportMapEntries.find(findTypesFileCallback)) == null ?
|
|
1356
|
+
matchedBundlePath = (_exportMapEntries_find = exportMapEntries.find(findTypesFileCallback)) == null ? undefined : _exportMapEntries_find.bundlePath;
|
|
1349
1357
|
// If theres no format specific types such as import.types or require.types,
|
|
1350
1358
|
// fallback to the general types file.
|
|
1351
1359
|
if (!matchedBundlePath) {
|
|
@@ -1355,13 +1363,13 @@ function aliasEntries({ entry: sourceFilePath, conditionNames, entries, format,
|
|
|
1355
1363
|
...item,
|
|
1356
1364
|
format: undefined
|
|
1357
1365
|
});
|
|
1358
|
-
})) == null ?
|
|
1366
|
+
})) == null ? undefined : _exportMapEntries_find1.bundlePath;
|
|
1359
1367
|
}
|
|
1360
1368
|
} else {
|
|
1361
1369
|
var _exportMapEntries_find2;
|
|
1362
1370
|
matchedBundlePath = (_exportMapEntries_find2 = exportMapEntries.find((item)=>{
|
|
1363
1371
|
return findJsBundlePathCallback(item, specialCondition);
|
|
1364
|
-
})) == null ?
|
|
1372
|
+
})) == null ? undefined : _exportMapEntries_find2.bundlePath;
|
|
1365
1373
|
}
|
|
1366
1374
|
if (matchedBundlePath) {
|
|
1367
1375
|
if (!sourceToRelativeBundleMap.has(exportCondition.source)) sourceToRelativeBundleMap.set(exportCondition.source, matchedBundlePath);
|
|
@@ -1519,7 +1527,7 @@ async function buildInputConfig(entry, bundleConfig, exportCondition, buildConte
|
|
|
1519
1527
|
const sizePlugin = pluginContext.outputState.plugin(cwd);
|
|
1520
1528
|
// common plugins for both dts and ts assets that need to be processed
|
|
1521
1529
|
// If it's a .d.ts file under non-ESM package or .d.cts file, use cjs types alias.
|
|
1522
|
-
const aliasFormat = dts ? ((_bundleConfig_file = bundleConfig.file) == null ?
|
|
1530
|
+
const aliasFormat = dts ? ((_bundleConfig_file = bundleConfig.file) == null ? undefined : _bundleConfig_file.endsWith('.d.cts')) || ((_bundleConfig_file1 = bundleConfig.file) == null ? undefined : _bundleConfig_file1.endsWith('.d.ts')) && !isESModulePackage(pkg.type) ? 'cjs' : 'esm' : bundleConfig.format;
|
|
1523
1531
|
const currentConditionNames = Object.keys(exportCondition.export)[0];
|
|
1524
1532
|
const aliasPlugin = aliasEntries({
|
|
1525
1533
|
entry,
|
|
@@ -1685,7 +1693,7 @@ async function buildOutputConfigs(bundleConfig, exportCondition, buildContext, d
|
|
|
1685
1693
|
const { format } = bundleConfig;
|
|
1686
1694
|
const { entries, pkg, cwd, tsOptions: { tsCompilerOptions }, pluginContext } = buildContext;
|
|
1687
1695
|
// Add esm mark and interop helper if esm export is detected
|
|
1688
|
-
const useEsModuleMark = tsCompilerOptions == null ?
|
|
1696
|
+
const useEsModuleMark = tsCompilerOptions == null ? undefined : tsCompilerOptions.esModuleInterop;
|
|
1689
1697
|
const absoluteOutputFile = path.resolve(cwd, bundleConfig.file);
|
|
1690
1698
|
const isEsmPkg = isESModulePackage(pkg.type);
|
|
1691
1699
|
const name = filePathWithoutExtension(absoluteOutputFile);
|
|
@@ -1893,11 +1901,12 @@ async function bundle(cliEntryPath, { cwd: _cwd, ...options } = {}) {
|
|
|
1893
1901
|
// Original input file path, client path might change later
|
|
1894
1902
|
const inputFile = cliEntryPath;
|
|
1895
1903
|
const isFromCli = Boolean(cliEntryPath);
|
|
1896
|
-
|
|
1897
|
-
let
|
|
1904
|
+
const tsConfigPath = resolveTsConfigPath(cwd, options.tsconfig);
|
|
1905
|
+
let tsConfig = resolveTsConfig(cwd, tsConfigPath);
|
|
1906
|
+
let hasTsConfig = Boolean(tsConfig == null ? undefined : tsConfig.tsConfigPath);
|
|
1898
1907
|
const defaultTsOptions = {
|
|
1899
|
-
tsConfigPath: tsConfig == null ?
|
|
1900
|
-
tsCompilerOptions: (tsConfig == null ?
|
|
1908
|
+
tsConfigPath: tsConfig == null ? undefined : tsConfig.tsConfigPath,
|
|
1909
|
+
tsCompilerOptions: (tsConfig == null ? undefined : tsConfig.tsCompilerOptions) || {}
|
|
1901
1910
|
};
|
|
1902
1911
|
// Handle single entry file
|
|
1903
1912
|
if (!isMultiEntries) {
|
|
@@ -1947,10 +1956,16 @@ async function bundle(cliEntryPath, { cwd: _cwd, ...options } = {}) {
|
|
|
1947
1956
|
}
|
|
1948
1957
|
const entries = await collectEntriesFromParsedExports(cwd, parsedExportsInfo, pkg, inputFile);
|
|
1949
1958
|
const hasTypeScriptFiles = Object.values(entries).some((entry)=>isTypescriptFile(entry.source));
|
|
1959
|
+
// If there's no tsconfig, create one.
|
|
1950
1960
|
if (hasTypeScriptFiles && !hasTsConfig) {
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1961
|
+
// Check if tsconfig.json exists in the project first.
|
|
1962
|
+
// If not, create one with default settings.
|
|
1963
|
+
// Otherwise, use the existing one.
|
|
1964
|
+
const defaultTsConfigPath = path.resolve(cwd, 'tsconfig.json');
|
|
1965
|
+
if (!fileExists(defaultTsConfigPath)) {
|
|
1966
|
+
await writeDefaultTsconfig(defaultTsConfigPath);
|
|
1967
|
+
}
|
|
1968
|
+
defaultTsOptions.tsConfigPath = defaultTsConfigPath;
|
|
1954
1969
|
hasTsConfig = true;
|
|
1955
1970
|
}
|
|
1956
1971
|
let browserslistConfig;
|
|
@@ -1972,14 +1987,14 @@ async function bundle(cliEntryPath, { cwd: _cwd, ...options } = {}) {
|
|
|
1972
1987
|
moduleDirectiveLayerMap: new Map()
|
|
1973
1988
|
}
|
|
1974
1989
|
};
|
|
1975
|
-
(_options__callbacks = options._callbacks) == null ?
|
|
1990
|
+
(_options__callbacks = options._callbacks) == null ? undefined : (_options__callbacks_onBuildStart = _options__callbacks.onBuildStart) == null ? undefined : _options__callbacks_onBuildStart.call(_options__callbacks, buildContext);
|
|
1976
1991
|
const generateTypes = hasTsConfig && options.dts !== false;
|
|
1977
1992
|
const rollupJobsOptions = {
|
|
1978
1993
|
isFromCli,
|
|
1979
1994
|
generateTypes
|
|
1980
1995
|
};
|
|
1981
1996
|
const assetJobs = await createAssetRollupJobs(options, buildContext, rollupJobsOptions);
|
|
1982
|
-
(_options__callbacks1 = options._callbacks) == null ?
|
|
1997
|
+
(_options__callbacks1 = options._callbacks) == null ? undefined : (_options__callbacks_onBuildEnd = _options__callbacks1.onBuildEnd) == null ? undefined : _options__callbacks_onBuildEnd.call(_options__callbacks1, assetJobs);
|
|
1983
1998
|
}
|
|
1984
1999
|
|
|
1985
2000
|
exports.bundle = bundle;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bunchee",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.1",
|
|
4
4
|
"description": "zero config bundler for js/ts/jsx libraries",
|
|
5
5
|
"bin": "./dist/bin/cli.js",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
],
|
|
25
25
|
"prettier": {
|
|
26
26
|
"semi": false,
|
|
27
|
-
"singleQuote": true
|
|
27
|
+
"singleQuote": true,
|
|
28
|
+
"trailingComma": "all"
|
|
28
29
|
},
|
|
29
30
|
"engines": {
|
|
30
31
|
"node": ">= 18.0.0"
|
|
@@ -36,25 +37,25 @@
|
|
|
36
37
|
},
|
|
37
38
|
"license": "MIT",
|
|
38
39
|
"dependencies": {
|
|
39
|
-
"@rollup/plugin-commonjs": "^28.0.
|
|
40
|
+
"@rollup/plugin-commonjs": "^28.0.2",
|
|
40
41
|
"@rollup/plugin-json": "^6.1.0",
|
|
41
|
-
"@rollup/plugin-node-resolve": "^
|
|
42
|
-
"@rollup/plugin-replace": "^6.0.
|
|
42
|
+
"@rollup/plugin-node-resolve": "^16.0.0",
|
|
43
|
+
"@rollup/plugin-replace": "^6.0.2",
|
|
43
44
|
"@rollup/plugin-wasm": "^6.2.2",
|
|
44
45
|
"@rollup/pluginutils": "^5.1.3",
|
|
45
|
-
"@swc/core": "^1.
|
|
46
|
+
"@swc/core": "^1.10.7",
|
|
46
47
|
"@swc/helpers": "^0.5.11",
|
|
47
48
|
"clean-css": "^5.3.3",
|
|
48
49
|
"glob": "^11.0.0",
|
|
49
|
-
"magic-string": "^0.30.
|
|
50
|
+
"magic-string": "^0.30.17",
|
|
50
51
|
"ora": "^8.0.1",
|
|
51
52
|
"picomatch": "^4.0.2",
|
|
52
53
|
"pretty-bytes": "^5.6.0",
|
|
53
|
-
"rollup": "^4.
|
|
54
|
+
"rollup": "^4.30.1",
|
|
54
55
|
"rollup-plugin-dts": "^6.1.1",
|
|
55
56
|
"rollup-plugin-swc3": "^0.11.1",
|
|
56
57
|
"rollup-preserve-directives": "^1.1.3",
|
|
57
|
-
"tslib": "^2.
|
|
58
|
+
"tslib": "^2.8.1",
|
|
58
59
|
"yargs": "^17.7.2"
|
|
59
60
|
},
|
|
60
61
|
"peerDependencies": {
|
|
@@ -71,8 +72,8 @@
|
|
|
71
72
|
"devDependencies": {
|
|
72
73
|
"@huozhi/testing-package": "1.0.0",
|
|
73
74
|
"@swc-node/register": "^1.10.9",
|
|
74
|
-
"@swc/jest": "^0.2.
|
|
75
|
-
"@swc/types": "^0.1.
|
|
75
|
+
"@swc/jest": "^0.2.37",
|
|
76
|
+
"@swc/types": "^0.1.17",
|
|
76
77
|
"@types/clean-css": "^4.2.11",
|
|
77
78
|
"@types/jest": "29.0.0",
|
|
78
79
|
"@types/node": "^22.9.3",
|
|
@@ -82,11 +83,11 @@
|
|
|
82
83
|
"bunchee": "link:./",
|
|
83
84
|
"cross-env": "^7.0.3",
|
|
84
85
|
"husky": "^9.0.11",
|
|
85
|
-
"jest": "29.0
|
|
86
|
+
"jest": "29.7.0",
|
|
86
87
|
"lint-staged": "^15.2.2",
|
|
87
88
|
"next": "^15.0.4",
|
|
88
89
|
"picocolors": "^1.0.0",
|
|
89
|
-
"prettier": "
|
|
90
|
+
"prettier": "2.8.8",
|
|
90
91
|
"react": "^19.0.0",
|
|
91
92
|
"react-dom": "^19.0.0",
|
|
92
93
|
"typescript": "^5.7.2"
|