首页
Preview

还在用 rollup 打包库?试试 unbuild 吧

Rollup

Rollup 是一款 JavaScript 模块打包器,它可以将一些零散的 JavaScript 模块打包成一个或多个具有高度优化的 bundle。

与其他打包器如 webpack 和 Parcel 不同,Rollup 更适用于构建 JavaScript 库或组件,因为它能够生成一个纯净的、可重用的模块化代码。

Rollup 采用 ES6 模块和 Tree-shaking 技术,可以消除未使用的代码,从而减小 bundle 的大小。这使得它生成的 bundle 更小、更快、更易于维护和优化,特别适合于在浏览器环境中使用。

Rollup 的配置简单、易于使用,支持多种插件和自定义插件,可以满足各种需求。如果你想构建一个高效、可维护、可重用的 JavaScript 库或组件,那么 Rollup 是一个不错的选择。

Usage

使用 Rollup 打包库也非常简单

install

npm i rollup -D

config

创建 Rollup 配置文件 rollup.config.js

// rollup.config.js
export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'umd'
  }
}

build

npx rollup --config rollup.config.js

此配置将 src/index.js 打包为一个 UMD 格式的 bundle,并输出到 dist/bundle.js

要使用插件,请在配置文件中导入插件并将其添加到 plugins 中。例如,要使用 Babel 插件将 ES6 代码转换为 ES5 代码:

npm i rollup-plugin-babel -D
// rollup.config.js
import babel from 'rollup-plugin-babel';

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'umd'
  },
  plugins: [
    babel({
      exclude: 'node_modules/**'
    })
  ]
}

这将在打包时使用 Babel 插件来转换你的代码。

Features

Rollup 有非常多的优秀的特性

Tree-Shaking

Tree-Shaking 是一种去除 JavaScript 代码中未使用部分的技术,可以减小 bundle 的大小

// math.js
export function square(x) {
  return x * x;
}

// 打包后,这段代码不会出现在 bundle 中
export function cube(x) {
  return x * x * x;
}

// index.js
import { square } from './math.js';

console.log(square(4));

在这个示例中,math.js 导出了两个函数 squarecube,而 index.js 只使用了 square 函数。如果使用 Rollup 和 Tree-Shaking 技术打包这些文件,那么输出的 bundle 将只包含 square 函数和其依赖的代码,而 cube 函数和其依赖的代码将被移除。

Multiple outputs

Rollup 也可以生成多种输出格式,包括 CommonJS、AMD、ES6 模块和 UMD。在 Rollup 配置文件的 output 属性中指定 format 选项即可。例如,要生成一个 CommonJS 格式的输出文件和一个 ES6 模块格式的输出文件,可以这样配置:

// rollup.config.js
export default {
  input: 'src/index.js',
  output: [
    {
      file: 'dist/bundle.cjs.js',
      format: 'cjs'
    },
    {
      file: 'dist/bundle.esm.js',
      format: 'es'
    }
  ]
}

这将生成一个 CommonJS 格式的输出文件 dist/bundle.cjs.js 和一个 ES6 模块格式的输出文件 dist/bundle.esm.js。同时也可以使用其他格式,如 AMD 和 UMD。注意,当使用 UMD 格式时,需要指定 name 选项来指定全局变量的名称。例如:

// rollup.config.js
export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.umd.js',
    format: 'umd',
    name: 'MyLibrary'
  }
}

这将生成一个 UMD 格式的输出文件 dist/bundle.umd.js,并将全局变量命名为 MyLibrary,使得它可以在浏览器和 Node.js 等环境中使用。

Code Splitting

在 Rollup 中,可以使用动态导入语法来实现原生的代码分割。动态导入语法与常规导入语法类似,只是将 import 关键字替换为 import() 函数。

// rollup.config.js
export default {
  input: "src/index.js",
  output: {
    dir: "dist",
  },
}
// src/foo.js
export default 1;
// src/index.js
export default function () {
  // 分割 foo.js
  import("./foo.js").then(({ default: foo }) => console.log(foo));
}

show-lazy.gif

最终打包,./foo.js 会被单独的分割开

Powerful plugins

Rollup 的插件系统非常灵活,可以满足各种需求。Rollup 的插件分为两种类型:转换插件和输出插件。转换插件用于处理源代码,例如将 ES6 代码转换为 ES5 代码、将 CSS 文件转换为 JavaScript 代码等。输出插件用于生成输出文件,例如将 JavaScript 代码写入文件、将代码发送到服务器等。

Rollup 的插件生态非常丰富,有许多优秀的插件可供使用。以下是一些常用的 Rollup 插件:

  • @rollup/plugin-node-resolve:用于解析 Node.js 模块导入语法和第三方模块的依赖关系。使用这个插件可以方便地将 Node.js 模块和第三方模块打包到你的 bundle 中。
  • @rollup/plugin-commonjs:用于将 CommonJS 模块转换为 ES6 模块。使用这个插件可以方便地将 CommonJS 模块打包到你的 bundle 中。
  • rollup-plugin-babel:用于将 ES6+ 代码转换为 ES5 代码。使用这个插件可以方便地在 Rollup 中使用 Babel。
  • rollup-plugin-terser:用于压缩 JavaScript 代码。使用这个插件可以减小输出文件的大小,提高页面加载速度。
  • rollup-plugin-sass:用于将 Sass 文件转换为 CSS 文件。使用这个插件可以方便地在 Rollup 中使用 Sass。
  • rollup-plugin-postcss:用于将 CSS 文件转换为 JavaScript 代码。使用这个插件可以方便地在 Rollup 中使用 PostCSS。
  • rollup-plugin-image:用于将图片转换为 JavaScript 代码。使用这个插件可以方便地在 Rollup 中使用图片。
  • rollup-plugin-json:用于将 JSON 文件转换为 JavaScript 代码。使用这个插件可以方便地在 Rollup 中使用 JSON。

以上插件只是 Rollup 插件生态中的一部分,还有许多其他优秀的插件可供选择。在使用插件时,需要注意不要过度依赖插件,以免增加 bundle 的大小和构建时间。同时,也需要选择适合自己项目的插件,以免出现兼容性和性能问题。

总体而言,Rollup 是非常棒的库打包工具


unbuild

unbuild 也是 js 库打包工具,相比 rollup 有更好的开发体验 🥰

Usage

unbuild 的使用就更简单了

install

npm i unbuild -D

demo

创建 src/index.ts:

export const log = (...args) => { console.log(...args) }

更新 package.json:

{
  "type": "module",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "main": "./dist/index.cjs",
  "types": "./dist/index.d.ts",
  "files": [
    "dist"
  ]
}

build

npx unbuild

打包完成了

当然它也支持配置文件 👉 unbuild/configuration,但大多数情况下你是不需要的

Features

Optimized bundler

unbuild 基于Rollup,集成了 Rollup 生态中非常优秀的插件,开箱即用的支持 typescript,并允许生成commonjsesmodule 格式和类型声明。

这意味着不需要你手动一个个安装插件,配置,调试后才可以进行库开发。

简单查看源码也可以发现内置了很多插件。

13b9f660aeb4417f90ffedf0fe109ba8_tplv-k3u1fbpfcp-watermark.png

这些插件直接用社区第三方的,也有自己魔改的 (在 src/builder/plugins 中)。

值得一提的是,这里用了 esbuild 来转换 js 代码,比原生 Rollup 还要快。

a1813c1cad594bc2b6e2431b8a13c00e_tplv-k3u1fbpfcp-watermark.png

Automated config

unbuild 可以自动智能从 package.json 中推断出打包的入口和配置。这意味着大多数情况下,我们甚至不需要配置文件就可以进行正确地打包。

简单查看源码也可以发现,解析预设时未发现预设会回滚到自动预设

897d305d4ce14a1c8ced989a00bd6672_tplv-k3u1fbpfcp-watermark.png

fcd04a5a541b42a386afd643921736a2_tplv-k3u1fbpfcp-watermark.png

autoPreset 会递归扫描 src 源码目录获取所有源文件路径,同时结合 package.json 推断出 Entries 入口。

c5bcd66c880c4fa880d9169586ec7018_tplv-k3u1fbpfcp-watermark.png

其中 inferEntries 中最有意思的是对 package.jsonbin 的处理 👇

4ca897b0c99b4ce49594079009cb569d_tplv-k3u1fbpfcp-watermark.png

有了这个,如果我们开发 cli,就不需要单独配置,很 nice 🥰

Bundleless build

集成了 mkdist ,一个轻量的文件转换器。有点像 webpackloader,用来给文件进行预处理的。

而且 mkdist 可以保持原有目录文件的结构,也支持 vuesfc 组件,还能 copy 静态文件。

值得一提的是,我为 copy 静态文件部分提过 pr,用流来跑 copy,支持大型文件,速度很快。

具体可见 👉 perf: copy raw files with stream by markthree · Pull Request #70 · unjs/mkdist

当然携带大型文件到 npm 库中是不推荐的。

Passive watcher

stub 插桩,是我最喜欢的功能。

传统的打包工具,在开发环境采用监听模式时,每改动一次源码就需要打包一次。

例如下边用 Rollup,你会发现每次我保存源文件,都得重新打包一次。

8ecbea4f3f30439a8ebd5a273ecfb7ce_tplv-k3u1fbpfcp-watermark.gif

这在小项目开发当然无所谓,但是当我们进行 monorepo 开发时就完蛋了。

可能我们简单改其中一行代码,就会触发多个包一起打包,人直接麻了 🤕

而在 unbuild 中,我们可以使用插桩 👇

npx unbuild --stub

cd480db38fed4506bd6028cf29ae35bf_tplv-k3u1fbpfcp-watermark.gif

你会发现我们的进程断开了,然后生成了带有 jitibundle

这时我们其实就可以直接使用开发环境的代码了,因为 jiti 可以动态的执行 js 或者 ts 源码,不需要监听模式 🥰

这也意味着我们在写 monorepo 时,只需要运行一次 stub 即可,不会触发重新打包。

Untype Generator

集成了 untyped,可以通过 markdown 和配置对象生成类型。

Secure builds

自动检查各种构建问题,例如潜在的丢失未使用的依赖项。

cli 输出还包括了大小和导出,以进行快速检查。

尾声

后边我可能会介绍如何正确打包库,也欢迎关注 👇

或者关注我的开箱即用的 node 库模板 👉 node-lib-starter

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
markthree
保持简单

评论(0)

添加评论