Project Icon

bunchee

简化JS/TS库打包流程的零配置工具

bunchee是一个零配置的JavaScript和TypeScript库打包工具。它基于Rollup和SWC构建,允许开发者专注于代码编写,同时轻松生成CommonJS和ESModule格式的包。bunchee使用package.json中的标准exports配置作为唯一依据,通过入口文件约定匹配exports并构建包。此工具支持多种运行时环境、可执行文件构建、服务器组件,还提供实验性的共享模块功能。

bunchee

零配置的 JS/TS 包构建工具。

bunchee

bunchee 是一个零配置的构建工具,可以轻松地打包 JS/TS 库。它基于 Rollup 和 SWC ⚡️ 构建,让你专注于编写代码,同时生成多个捆绑包(CommonJS 或 ESModule)。它使用 package.json 中的标准导出配置作为唯一的真实来源,并使用入口文件约定来匹配你的导出并将它们构建成捆绑包。

快速开始

安装

npm install --save-dev bunchee

如果你使用 TypeScript

npm install --save-dev bunchee typescript

配置

创建你的库入口文件和 package.json。

cd ./my-lib
mkdir src && touch ./src/index.ts

准备

# 使用 bunchee 准备 package.json 配置
npm exec bunchee --prepare
# "如果你使用其他包管理器如 pnpm"
# pnpm bunchee --prepare

# "或者使用 npx"
# npx bunchee@latest --prepare

或者你可以查看以下案例来配置你的 package.json。

JavaScript

然后使用 package.json 中的 exports 字段 来配置不同的条件,并利用与其他打包工具(如 webpack)相同的功能。exports 字段允许你定义多个条件。

{
  "files": ["dist"],
  "exports": {
    "import": "./dist/es/index.mjs",
    "require": "./dist/cjs/index.js"
  },
  "scripts": {
    "build": "bunchee"
  }
}
TypeScript

如果你正在构建一个 TypeScript 库,将类型与主入口文件分开,并在 package.json 中指定类型路径。当你在 TypeScript 和现代模块解析(高于 node16)中使用 .mjs.cjs 扩展名时,TypeScript 将需要特定的类型声明文件,如 .d.mts.d.cts 来匹配扩展名。bunchee 可以自动生成它们以匹配条件和扩展名的类型。一个例子是在 package.json 中这样配置你的导出:

{
  "files": ["dist"],
  "exports": {
    "import": {
      "types": "./dist/es/index.d.mts",
      "default": "./dist/es/index.mjs"
    },
    "require": {
      "types": "./dist/cjs/index.d.ts",
      "default": "./dist/cjs/index.js"
    }
  },
  "scripts": {
    "build": "bunchee"
  }
}
混合(CJS & ESM)模块解析与 TypeScript 如果你使用 TypeScript 和 Node 10 以及 Node 16 模块解析,你可以在 package.json 中使用 `types` 字段来指定类型路径。然后 `bunchee` 将生成与主入口文件相同扩展名的类型文件。
{
  "files": ["dist"],
  "main": "./dist/cjs/index.js",
  "module": "./dist/es/index.mjs",
  "types": "./dist/cjs/index.d.ts",
  "exports": {
    "import": {
      "types": "./dist/es/index.d.ts",
      "default": "./dist/es/index.js"
    },
    "require": {
      "types": "./dist/cjs/index.d.cts",
      "default": "./dist/cjs/index.cjs"
    }
  },
  "scripts": {
    "build": "bunchee"
  }
}

构建

然后 src 文件夹中的文件将被视为入口文件,并与 package.json 中的导出名称相匹配。例如: src/index.ts 将匹配导出名称 "." 或唯一的主导出。

现在只需运行 npm run build(或者如果你使用这些包管理器,则运行 pnpm build / yarn build),bunchee 将找到入口文件并构建它们。 输出格式将基于导出条件和文件扩展名。举个例子:

  • 根据导出条件,require 是 CommonJS,import 是 ESM。
  • 不考虑导出条件,.js 是 CommonJS,.mjs 是 ESM。然后对于像 "node" 这样的导出条件,你可以用你的扩展名选择格式。

[!NOTE] 所有的 dependenciespeerDependencies 将自动标记为外部依赖,不会包含在捆绑包中。如果你想将它们包含在捆绑包中,可以使用 --no-external 选项。

使用

文件约定

虽然 exports 字段正在成为 node.js 中导出的标准,bunchee 也支持在一个命令中构建多个导出。

提供与 package.json 中 exports 字段导出名称匹配的入口文件名([name].[ext])。例如:

  • <cwd>/src/index.ts 将匹配 "." 导出名称,或者如果只有一个主导出。
  • <cwd>/src/lite.ts 将匹配 "./lite" 导出名称。

构建脚本可以只是 bunchee,无需为每个导出配置任何输入源。当然,你仍然可以根据需要指定其他参数。 简而言之,src/ 文件夹中的入口文件将与 package.json 中的 exports 条件进行匹配,并将它们构建成捆绑包。

假设你有默认导出包 "." 和子路径导出 "./lite",在 package.json 中列出了不同的导出条件

{
  "name": "example",
  "scripts": {
    "build": "bunchee"
  },
  "exports": {
    "./lite": "./dist/lite.js",
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  }
}

然后你需要在项目根目录添加两个入口文件 index.tslite.ts 来匹配导出名称 ".""./lite",bunchee 将这些入口文件与导出名称关联,然后将它们用作输入源和输出路径信息。

- my-lib/
  |- src/
    |- lite.ts
    |- index.ts
  |- package.json

它还会在具有导出路径名称的目录下查找 index.<ext> 文件。例如,如果你在导出字段中有 "./lite": "./dist/lite.js",那么它也会查找 ./lite/index.js 作为入口文件。

多运行时

对于像 react-nativereact-serveredge-light 这样的特殊平台的导出条件,它们可能有不同的导出或不同的代码条件。在这种情况下,如果你想将它们构建为不同的代码捆绑包,bunchee 提供了一个覆盖输入源文件约定。

例如:

{
  "exports": {
    "react-server": "./dist/react-server.mjs",
    "edge-light": "./dist/edge-light.mjs",
    "import": "./dist/index.mjs"
  }
}

可执行文件

要使用 package.json 中的 bin 字段构建可执行文件,bunchee 要求你在 src 目录下创建 bin 目录。源文件匹配将与入口文件约定相同。

例如:

|- src/
  |- bin/
    |- index.ts

这将匹配 package.json 中的 bin 字段为:

{
  "bin": "./dist/bin.js"
}

对于多个可执行文件,你可以在 bin 目录下创建多个文件。

|- src/
  |- bin/
    |- foo.ts
    |- bar.ts

这将匹配 package.json 中的 bin 字段为:

{
  "bin": {
    "foo": "./dist/bin/a.js",
    "bar": "./dist/bin/b.js"
  }
}

注意:对于多个 bin 文件,文件名应与 bin 字段中的键名匹配。

服务器组件

bunchee 支持构建服务器组件和服务器操作,使用库指令如 "use client""use server"。它将为客户端和服务器生成相应的块,正确划分客户端和服务器边界。 然后当库集成到应用程序(如 Next.js)中时,应用程序打包工具可以正确转换客户端组件和服务器操作,最大化利用优势。

如果你在入口文件中使用 "use client""use server",那么它将被保留在顶部,该入口的 dist 文件将成为客户端组件。 如果你在作为入口依赖项的文件中使用 "use client""use server",那么包含指令的文件将被拆分成单独的块,并将指令提升到该块的顶部。

共享模块(实验性)

总有一些情况,你需要在捆绑包之间共享代码,但它们不必是单独的入口或导出。你希望将它们捆绑到一个共享块中,然后在不同的捆绑包中使用它们。你可以使用共享模块约定 [name].[layer]-runtime.[ext] 来创建共享模块捆绑包。

共享工具示例
// src/util.shared-runtime.js
export function sharedUtil() {
  /* ... */
}

然后你可以在不同的入口文件中使用它们:

// src/index.js
import { sharedUtil } from './util.shared-runtime'
// src/lite.js
import { sharedUtil } from './util.shared-runtime'

bunchee 将把共享模块捆绑到一个单独的中,该层与文件名约定匹配,在上面的例子中是 "shared",并且该捆绑包将被不同的入口捆绑包引用。

对于多个运行时捆绑包,比如同时有 defaultreact-server。它们可能有需要共享并在不同运行时捆绑包之间保持只有一个实例的模块。你可以使用共享模块约定为不同的运行时捆绑包创建共享模块捆绑包。

共享运行时模块示例
'use client'
// src/app-context.shared-runtime.js
export const AppContext = React.createContext(null)

然后你可以在不同的入口文件中使用它们:

// src/index.js
import { AppContext } from './app-context.shared-runtime'
// src/index.react-server.js
import { AppContext } from './app-context.shared-runtime'

app-context.shared-runtime 将被捆绑到一个单独的块中,只有一个实例,并在不同的运行时捆绑包之间共享。

CLI

CLI 选项

bunchee CLI 提供了几个选项来创建不同的捆绑包或生成类型。

  • 输出(-o <文件>):指定输出文件名。
  • 格式(-f <格式>):设置输出格式(默认:'esm')。
  • 外部依赖(--external <依赖,>):指定额外的外部依赖,默认为package.json中的dependenciespeerDependencies列表。值以逗号分隔。
  • 目标(--target <目标>):设置ECMAScript目标(默认:'es2015')。
  • 运行时(--runtime <运行时>):设置构建运行时(默认:'browser')。
  • 环境(--env <环境变量,>):定义环境变量。(默认:NODE_ENV,以逗号分隔)
  • 工作目录(--cwd <工作目录>):设置包含package.json的当前工作目录。
  • 压缩(-m):压缩输出。
  • 监视(-w):监视源文件变化。
  • 不清理(--no-clean):构建前不清理dist文件夹。(默认:false
  • TypeScript配置(--tsconfig <路径>):指定TypeScript配置文件的路径。(默认:tsconfig.json
cd <项目根目录>

# 指定输入、输出和格式

bunchee ./src/index.js -f cjs -o ./dist/bundle.js
bunchee ./src/index.js -f esm -o ./dist/bundle.esm.js

# 构建Node.js库,或将目标更改为es2019
bunchee ./src/index.js --runtime node --target es2019

指定额外的外部依赖

默认情况下,bunchee会将所有dependenciespeerDependencies标记为外部依赖,因此您无需将它们作为CLI参数传递。 但如果有任何使用但不在依赖列表中的依赖,并且您想将其标记为外部依赖,可以使用--external选项来指定它们。

bunchee --external=dep1,dep2,dep3

dep1dep2dep3替换为您想要从捆绑包中排除的依赖项名称。

捆绑所有内容而不包含外部依赖

要捆绑您的库而不包含外部依赖,请使用--no-external选项:

bunchee --no-external

这将在输出捆绑包中包含所有依赖项。

环境变量

要将环境变量传递给捆绑的代码,请使用--env选项,后跟以逗号分隔的环境变量名称列表:

bunchee --env=ENV1,ENV2,ENV3

ENV1ENV2ENV3替换为您想要包含在捆绑代码中的环境变量名称。这些环境变量将在捆绑过程中被内联。

您可以使用index.<导出类型>.<扩展名>来覆盖特定导出名称的输入源文件。或者使用<导出路径>/index.<导出类型>.<扩展名>也可以。例如:

|- src/
  |- index/.ts
  |- index.react-server.ts
  |- index.edge-light.ts

这将匹配导出名称"react-server""edge-light",然后使用相应的输入源文件来构建捆绑包。

自动开发和生产模式

如果存在process.env.NODE_ENV,默认会注入,您无需手动注入。如果需要分离开发构建和生产构建,bunchee为开发和生产模式提供了不同的导出条件,分别为developmentproduction导出条件。

{
  "exports": {
    "development": "./dist/index.development.js",
    "production": "./dist/index.production.js"
  }
}

然后您可以使用bunchee自动构建开发捆绑包和生产捆绑包。

CSS

bunchee对纯CSS文件导入提供基本支持。它将被捆绑到js捆绑包中,并在浏览器加载捆绑包时将样式标签插入文档头部。

/* src/style.css */
.foo {
  color: orange;
}
// src/index.tsx
import './style.css'

export const Foo = () => <div className="foo">foo</div>

文本文件

如果您只想将文件作为字符串内容导入,可以将扩展名命名为.txt.data,它将被捆绑为字符串内容。

例如:

src/index.ts

import data from './data.txt'

export default data

src/data.txt

hello world

输出

export default "hello world"

Node.js API

import path from 'path'
import { bundle, type BundleConfig } from 'bunchee'

// 这些选项的定义可以在帮助信息中找到
await bundle(path.resolve('./src/index.ts'), {
  dts: false, // 布尔值
  watch: false, // 布尔值
  minify: false, // 布尔值
  sourcemap: false, // 布尔值
  external: [], // 字符串数组
  format: 'esm', // 'esm' | 'cjs'
  target: 'es2015', // ES语法目标
  runtime: 'nodejs', // 'browser' | 'nodejs'
  cwd: process.cwd(), // 字符串
  clean: true, // 布尔值
  tsconfig: 'tsconfig.json', // 字符串
})

监视模式

Bunchee提供了一个方便的监视模式,可以在源文件发生更改时重新构建您的库。要启用此功能,请使用-w--watch

target

如果您在tsconfig.json中指定了target选项,则无需再通过CLI传递它。

包检查

bunchee支持检查包捆绑是否与包导出配置匹配。

许可证

MIT

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

稿定AI

稿定设计 是一个多功能的在线设计和创意平台,提供广泛的设计工具和资源,以满足不同用户的需求。从专业的图形设计师到普通用户,无论是进行图片处理、智能抠图、H5页面制作还是视频剪辑,稿定设计都能提供简单、高效的解决方案。该平台以其用户友好的界面和强大的功能集合,帮助用户轻松实现创意设计。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号