{"id":13791852,"url":"https://github.com/huozhi/bunchee","last_synced_at":"2025-04-29T18:32:10.284Z","repository":{"id":37029533,"uuid":"154026156","full_name":"huozhi/bunchee","owner":"huozhi","description":"Zero config bundler for npm packages","archived":false,"fork":false,"pushed_at":"2025-04-20T07:57:48.000Z","size":2760,"stargazers_count":1188,"open_issues_count":20,"forks_count":32,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-20T08:41:26.267Z","etag":null,"topics":["bundler","commonjs","esmodule","javascript","jsx","minify","react","rsc","server-components","typescript"],"latest_commit_sha":null,"homepage":"https://bunchee-it.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/huozhi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-21T16:00:08.000Z","updated_at":"2025-04-20T07:57:49.000Z","dependencies_parsed_at":"2023-11-08T05:52:33.153Z","dependency_job_id":"8187b258-8dba-4bd0-a52c-118040ae58cc","html_url":"https://github.com/huozhi/bunchee","commit_stats":{"total_commits":700,"total_committers":22,"mean_commits":"31.818181818181817","dds":0.1071428571428571,"last_synced_commit":"916bb50adc0646e47b3bf6ca47aeb88d1aa02618"},"previous_names":[],"tags_count":174,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huozhi%2Fbunchee","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huozhi%2Fbunchee/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huozhi%2Fbunchee/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huozhi%2Fbunchee/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/huozhi","download_url":"https://codeload.github.com/huozhi/bunchee/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250738759,"owners_count":21479242,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bundler","commonjs","esmodule","javascript","jsx","minify","react","rsc","server-components","typescript"],"created_at":"2024-08-03T22:01:05.191Z","updated_at":"2025-04-29T18:32:10.265Z","avatar_url":"https://github.com/huozhi.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","typescript"],"sub_categories":[],"readme":"# bunchee\n\n\u003e Zero-config bundler for JS/TS packages.\n\n![bunchee](https://repository-images.githubusercontent.com/154026156/5d132698-0ff5-4644-a4fd-d9570e6229bc)\n\n\u003cp align=\"left\"\u003e\n  \u003ca href=\"https://npm.im/bunchee\"\u003e\n    \u003cimg src=\"https://badgen.net/npm/v/bunchee\"\u003e\n  \u003c/a\u003e\n\n  \u003ca href=\"https://github.com/huozhi/bunchee/actions?workflow=CI\"\u003e\n    \u003cimg src=\"https://github.com/huozhi/bunchee/workflows/CI/badge.svg\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n**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.\n\nBy 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.\n\n## Quick Start\n\n### Installation\n\n```sh\nnpm install --save-dev bunchee typescript\n```\n\n### Configuration\n\nCreate entry files of your library and `package.json`.\n\n```sh\ncd ./coffee\nmkdir src \u0026\u0026 touch ./src/index.ts \u0026\u0026 touch package.json\n```\n\nAdd the exports in `package.json`.\n\n```json5\n{\n  \"name\": \"coffee\",\n  \"type\": \"module\",\n  \"main\": \"./dist/index.js\",\n  \"scripts\": {\n    \"build\": \"bunchee\"\n  }\n}\n```\n\n#### Build\n\n```sh\nnpm run build\n```\n\n## Usage\n\n### Entry Files\n\nThen files in `src` folders will be treated as entry files and match the export names in package.json.\nSimply like Node.js module resolution, each export name will match the file in `src/` directory.\n\nHere's a example of entry files and exports configuration:\n\n| **File**             | **Exports Name**       |\n| -------------------- | ---------------------- |\n| `src/index.ts`       | `\".\"` (default export) |\n| `src/lite.ts`        | `\"./lite\"`             |\n| `src/react/index.ts` | `\"./react\"`            |\n\n```json5\n{\n  \"name\": \"coffee\",\n  \"scripts\": {\n    \"build: \"bunchee\",\n  },\n  \"type\": \"module\",\n  \"exports\": {\n    // entry: ./src/index.ts\n    \".\": {\n      \"import\": \"./dist/index.js\",\n      \"require\": \"./dist/index.cjs\",\n    },\n\n    // entry: ./src/lite.ts\n    \"./lite\": \"./dist/lite.js\",\n\n    // entry: ./src/react/index.ts\n    \"./react\": \"./dist/react.js\",\n  },\n}\n```\n\n### Output Formats\n\n**bunchee** detects the format of each entry-point based on export condition type or the file extension. It supports the following output formats:\n\n| `package.json` Field | Output format                    |\n| -------------------- | -------------------------------- |\n| `main`               | Default                          |\n| `types`              | TypeScript declaration           |\n| `exports`            | Default                          |\n| `exports.require`    | CommonJS                         |\n| `exports.import`     | Default                          |\n| `exports.types`      | TypeScript declaration of export |\n| `bin`                | Default                          |\n| `bin.\u003cname\u003e`         | Default                          |\n\nThe **Default** output format is determined by the file extension:\n\n| File Extension | Output format                                                                                                                                                                           |\n| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `.js`          | Determined by `package.json#type`, CommonJS by default                                                                                                                                  |\n| `.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) |\n| `.mjs`         | [ECMAScript Modules](https://nodejs.org/api/modules.html#the-mjs-extension)                                                                                                             |\n\n### External Dependencies\n\nThe `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.\n\n```json5\n{\n  // Externalized\n  \"dependencies\": {\n    /* ... */\n  },\n  \"peerDependencies\": {\n    /* ... */\n  },\n\n  // Bundled\n  \"devDependencies\": {\n    /* ... */\n  },\n}\n```\n\n### Multiple Runtime\n\nFor 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.\n\nFor instance:\n\n```json5\n{\n  \"exports\": {\n    \"react-server\": \"./dist/react-server.mjs\",\n    \"edge-light\": \"./dist/edge-light.mjs\",\n    \"import\": \"./dist/index.mjs\",\n  },\n}\n```\n\n### Path Alias\n\n`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.\n\n```json5\n// package.json\n{\n  \"imports\": {\n    \"#util\": \"./src/utils.ts\",\n  },\n}\n```\n\n### Binary CLI\n\nTo 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.\n\nFor example:\n\n```bash\n|- src/\n  |- bin/\n    |- index.ts\n```\n\nThis will match the `bin` field in package.json as:\n\n```json5\n{\n  \"bin\": \"./dist/bin.js\",\n}\n```\n\nIf you have multiple binaries, you can create multiple files under the `bin` directory. Check the below example for more details.\n\n\u003cdetails\u003e\n  \u003csummary\u003eMultiple Binaries\u003c/summary\u003e\n\nFor named executable files, you can create multiple files under the `bin` directory.\n\n```bash\n|- src/\n  |- bin/\n\n```\n\nThis will match the `bin` field in package.json as:\n\n```json5\n{\n  \"bin\": {\n    \"foo\": \"./dist/bin/a.js\",\n    \"bar\": \"./dist/bin/b.js\",\n  },\n}\n```\n\n\u003c/details\u003e\n\n\u003e Note: For multiple `bin` files, the filename should match the key name in the `bin` field.\n\n### Server Components\n\n**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.\n\n### Shared Modules\n\nSometimes, 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** (`_\u003cname\u003e.\u003cext\u003e` or `_\u003cname\u003e/**`) will be treated as **shared modules**.\n\nThese 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.\n\n\u003cdetails\u003e\n  \u003csummary\u003eShared Utils Example\u003c/summary\u003e\n\n```js\n// src/_util.js\nexport function sharedUtil() {\n  /* ... */\n}\n```\n\nYou can then use them in different entry files:\n\n```js\n// src/index.js\nimport { sharedUtil } from './_util'\n```\n\n```js\n// src/lite.js\nimport { sharedUtil } from './_util'\n```\n\n`bunchee` will bundle the shared module into a separate chunk, keeping it private and ensuring it's referenced by multiple entry bundles.\n\n\u003c/details\u003e\n\nFor scenarios involving multiple runtime bundles, such as `default` and `react-server`, modules that need to be shared and remain as a single instance across different runtime bundles can also follow this convention. The leading underscore (`_`) ensures that these modules are private to your application while facilitating reuse.\n\n\u003cdetails\u003e\n  \u003csummary\u003eShared Runtime Module Example\u003c/summary\u003e\n\n```js\n'use client'\n// src/_app-context.js\nexport const AppContext = React.createContext(null)\n```\n\nThese modules can be imported in various runtime entry files:\n\n```js\n// src/index.js\nimport { AppContext } from './_app-context'\n```\n\n```js\n// src/index.react-server.js\nimport { AppContext } from './_app-context'\n```\n\nThe `_app-context` module will be bundled into a shared chunk that exists as a single instance across different runtime bundles.\n\n\u003c/details\u003e\n\nThis convention keeps shared modules private while enabling efficient bundling and reuse across your codebase.\n\n### CLI\n\n#### Options\n\n`bunchee` CLI provides few options to create different bundles or generating types. Call `bunchee --help` to see the help information in the terminal.\n\nHere are the available options for the CLI:\n\n```sh\ncd \u003cproject-root-dir\u003e\n\n# Build based on the package.json configuration\nbunchee --runtime node -o ./dist/bundle.js\nbunchee -f esm -o --target es2022 ./dist/bundle.esm.js\n\n# Specify the input source file\nbunchee ./src/foo.ts -o ./dist/foo.js\n```\n\n#### Specifying extra external dependencies\n\n```sh\nbunchee --external=dep1,dep2,dep3\n```\n\nReplace `dep1`, `dep2`, and `dep3` with the names of the dependencies you want to exclude from the bundle.\n\n#### Bundling everything without external dependencies\n\nTo bundle your library without external dependencies, use the `--no-external` option:\n\n```sh\nbunchee --no-external\n```\n\nThis will include all dependencies within your output bundle.\n\n#### Build Successful Command\n\nA command to be executed after a build is successful can be specified using the `--success` option, which is useful for development watching mode:\n\n```sh\nbunchee --watch --success \"node ./dist/index.js\"\n```\n\n#### Prepare Package\n\n```sh\n# Use bunchee to prepare package.json configuration\nnpm exec bunchee prepare\n# \"If you're using other package manager such as pnpm\"\n# pnpm bunchee prepare\n\n# \"Or use with npx\"\n# npx bunchee@latest prepare\n```\n\nOr you can checkout the following cases to configure your package.json.\n\n\u003cdetails\u003e\n  \u003csummary\u003eJavaScript ESModule\u003c/summary\u003e\n\nThen 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.\n\n```json5\n{\n  \"files\": [\"dist\"],\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": \"./dist/es/index.js\",\n    \"./react\": \"./dist/es/react.js\",\n  },\n  \"scripts\": {\n    \"build\": \"bunchee\",\n  },\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eTypeScript\u003c/summary\u003e\n\nIf you're building 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.\n\n```json5\n{\n  \"files\": [\"dist\"],\n  \"type\": \"module\",\n  \"main\": \"./dist/index.js\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\",\n    },\n    \"./react\": {\n      \"types\": \"./dist/react/index.d.ts\",\n      \"default\": \"./dist/react/index.js\",\n    },\n  },\n  \"scripts\": {\n    \"build\": \"bunchee\",\n  },\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eHybrid (CJS \u0026 ESM) Module Resolution with TypeScript\u003c/summary\u003e\nIf 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.\n\n_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.\n\n```json5\n{\n  \"files\": [\"dist\"],\n  \"type\": \"module\",\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"exports\": {\n    \"import\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\",\n    },\n    \"require\": {\n      \"types\": \"./dist/index.d.cts\",\n      \"default\": \"./dist/index.cjs\",\n    },\n  },\n  \"scripts\": {\n    \"build\": \"bunchee\",\n  },\n}\n```\n\n\u003c/details\u003e\n\n#### Lint Package\n\n`lint` command will check the package.json configuration is valid or not, it can valid few things like:\n\n- if the entry files are matched with the exports conditions.\n- if the entry files are matched with the exports paths.\n\n```sh\n# Use bunchee to lint if the package.json configuration is valid\nnpm exec bunchee lint\n```\n\n### Environment Variables\n\nTo pass environment variables to your bundled code, use the --env option followed by a comma-separated list of environment variable names:\n\n```bash\nbunchee --env=ENV1,ENV2,ENV3\n```\n\nReplace `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.\n\nYou can use `index.\u003cexport-type\u003e.\u003cext\u003e` to override the input source file for specific export name. Or using `\u003cexport-path\u003e/index.\u003cexport-type\u003e.\u003cext\u003e` also works. Such as:\n\n```\n|- src/\n  |- index/.ts\n  |- index.react-server.ts\n  |- index.edge-light.ts\n```\n\nThis will match the export name `\"react-server\"` and `\"edge-light\"` then use the corresponding input source file to build the bundle.\n\n#### Auto Development and Production Mode\n\n`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.\n\n```json5\n{\n  \"exports\": {\n    \"development\": './dist/index.development.js',\n    \"production\": './dist/index.production.js',\n  },\n}\n```\n\nThen you can use `bunchee` to build the development bundle and production bundle automatically.\n\n### CSS\n\n`bunchee` has basic CSS support for pure CSS file imports. It will be bundled into js bundle and insert the style tag into the document head when the bundle is loaded by browser.\n\n```css\n/* src/style.css */\n.foo {\n  color: orange;\n}\n```\n\n```tsx\n// src/index.tsx\nimport './style.css'\n\nexport const Foo = () =\u003e \u003cdiv className=\"foo\"\u003efoo\u003c/div\u003e\n```\n\n### Text Files\n\nIf you just want to import a file as string content, you can name the extension as `.txt` or `.data` and it will be bundled as string content.\n\nFor example:\n\nsrc/index.ts\n\n```js\nimport data from './data.txt'\n\nexport default data\n```\n\nsrc/data.txt\n\n```txt\nhello world\n```\n\noutput\n\n```js\nexport default 'hello world'\n```\n\n### Node.js API\n\n```ts\nimport path from 'path'\nimport { bundle, type BundleConfig } from 'bunchee'\n\n// The definition of these options can be found in help information\nawait bundle(path.resolve('./src/index.ts'), {\n  dts: false, // Boolean\n  watch: false, // Boolean\n  minify: false, // Boolean\n  sourcemap: false, // Boolean\n  external: [], // string[]\n  format: 'esm', // 'esm' | 'cjs'\n  target: 'es2015', // ES syntax target\n  runtime: 'nodejs', // 'browser' | 'nodejs'\n  cwd: process.cwd(), // string\n  clean: true, // boolean\n  tsconfig: 'tsconfig.json', // string\n})\n```\n\n#### Watch Mode\n\nBunchee offers a convenient watch mode for rebuilding your library whenever changes are made to the source files. To enable this feature, use either `-w` or `--watch`.\n\n#### `target`\n\nIf you specify `target` option in `tsconfig.json`, then you don't have to pass it again through CLI.\nTo target a range of browsers, you can use the `browserslist` field in `package.json`, bunchee will use it to determine the target browsers for the output bundle.\n\nFor example:\n\n```json5\n{\n  \"browserslist\": [\n    \"last 1 version\",\n    \"\u003e 1%\",\n    \"maintained node versions\",\n    \"not dead\",\n  ],\n}\n```\n\n#### Package lint\n\n`bunchee` has support for checking the package bundles are matched with package exports configuration.\n\n### License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhuozhi%2Fbunchee","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhuozhi%2Fbunchee","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhuozhi%2Fbunchee/lists"}