使用rollup打包自己的npm包

524 阅读6分钟

之前我写了篇文章使用npm发布自己的第一个包,目前存在两个问题,先看一下我们的包上传到 npm 上是怎样的结构:

可以看到上传到 npm 的包和我们的本地目录结构是一样的,这也并不奇怪,因为我使用的就是最简单的npm init -y生成的配置文件,并没有做什么额外的配置项,所以自然是我本地代码是什么样的,上传到 npm 上就是什么样,这样看起来是没有什么问题,但仔细观察就会发现有这么几个问题:

  1. .vscode文件也上传到 npm 上了,我们其实不希望将vscode的配置文件上传上去,这并没有什么用。此外很多时候我们的代码内可能不是全部内容都上传到 npm 上的,我们只需要和包有关的代码上传到 npm 上。
  2. 目前上传的代码是未经压缩的,是源码直出的,可以看到目前包的总体积在 864B, 这在包小的时候没什么问题,但是如果日后代码逐渐增多,包的体积也会递增,这势必会增加实际项目的大小,而这些额外增加的大小,本来是可以通过压缩代码来实现的。而且我们实际上也不需要在 npm 上查看它的源码,毕竟 npm 不是源代码管理工具,它注重的是使用。

所以针对上述两个问题,本文将通过增加 npm 的一系列配置以及引入rollup来打包我们的包解决上述问题,下面开始正文:

使用 .npmignore忽略 .vscode 文件夹

  • 在项目的根目录下创建一个 .npmignore 文件。
  • 在文件中添加以下内容以屏蔽 .vscode 文件夹
.vscode

然后我们重新发布测试下,查看结果:

此时我们就看到上传到 npm 上的包就不含.vscode了,而且包的体积也减少了近 100B

补充说明

如果使用 git来管理代码,那么npm 默认会使用 .gitignore 文件。在 .gitignore 中添加即可。如果有了.gitignore,.npmignore 文件会覆盖 .gitignore 的行为。

下面解决第二个问题,不过在开始之前,我们需要先知道 rollup是什么?

rollup 是什么

Rollup 是一个用于 JavaScript 的模块打包工具,它将小的代码片段编译成更大、更复杂的代码,例如库或应用程序。它使用 JavaScript 的 ES6 版本中包含的新标准化代码模块格式,而不是以前的 CommonJS 和 AMD 等特殊解决方案。ES 模块允许你自由无缝地组合你最喜欢的库中最有用的个别函数。这在未来将在所有场景原生支持,但 Rollup 让你今天就可以开始这样做。

这是官方文档对 rollup 的概括,简单总结一下:

rollup 是使用ES模块(es moudle)语法打包JavaScript模块的工具,所谓的JavaScript模块打包工具,意思就是将使用 ES 模块(使用 exportd 导出和 import 导入)编写的代码编译成其它模块类型的代码(比如UMD 或 CommonJS 格式),以使得你的代码可以在各种不同的 JavaScript 环境运行。

举例来说,就拿我们的fengdu-utils包来说,它是使用 ES 模块写的,很明显它不能直接在浏览器里使用,没有办法通过 script 引入,它只能在工程化的项目内使用。

此外 rollup 还可以在编译的过程中,使用一系列插件来对源代码进一步处理,就比如说压缩代码,而这也是我们主要想使用的,话不多说我们直接开始实践。

rollup 安装

rollup安装为开发依赖

npm i rollup -D

创建rollup配置文件rollup.config.js,这里我们需要通过input来指定打包的入口文件,以及output指定输出的文件,我希望最后打包的文件放到dist目录下:

export default {
  input: 'index.js',
  output: {
    file: 'dist/index.js'
  }
}

我们配置一个 scripts 命令来快速运行 rollup 打包命令

"scripts": {
+    "build": "rollup -c"
  }

这样我们就可以直接通过npm run build来执行rollup打包了,运行后发现报错:

> rollup -c


src/index.js → dist/index.js...
(node:5593) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///Users/wanko/project/fengdu-utils/rollup.config.js is not specified and it doesn't parse as CommonJS.
Reparsing as ES module because module syntax was detected. This incurs a performance overhead.
To eliminate this warning, add "type": "module" to /Users/wanko/project/fengdu-utils/package.json.
(Use `node --trace-warnings ...` to show where the warning was created)
[!] RollupError: Could not resolve entry module "src/index.js".

这是因为 Rollup 的配置文件被检测为 ESM 模块(通过 export defaultimport 语法),而Node.js 默认将文件解析为 CommonJS 模块,所以我们需要在package.json中添加 "type": "module",明确声明项目使用 ESM 模块格式:

{
  "type": "module"
}

如果不想使用 ESM,可以将 Rollup 配置文件改为 CommonJS 格式,使用 module.exportsrequire

module.exports =  {
  input: 'index.js',
  output: {
    file: 'dist/index.js'
  }
}

此时再打包可以看到打包后dist目录输出的index.js文件:

我们可以看到打包后的代码,其实就是将 ES6 转为了 ES5,然后将原来不同模块的代码组合到了一个文件中,代码都是原样不变,连注释都在。

很明显这样还是不能减少包的体积,想要减少包体积,我们还需要使用rollup的压缩插件terser,它可以对打包后的文件进行压缩,包括移除 console,移除注释, 从而减少文件体积。专于生产环境的代码优化。

安装压缩插件

npm install rollup-plugin-terser -D

我们再执行 rollup 打包命令,查看 dist

可以看到压缩后就只剩下几行代码,那么我们只需要上传这个文件到 npm 上就可以极大的减少我们的包体积,具体怎么做,请继续往下看。

指定 npm 要上传的文件

我们需要在package.json中做两件事情:

  1. 增加files字段,files 字段为一个数组,设置后 npm 将只会上传指定目录或文件夹下的文件到 npm。
  2. 修改main字段,因为我们只上传了dist目录到 npm,原来的设置的根目录下index.js为入口文件就不再对了,需要改为dist/index.js

完整 package.json配置

{
  "name": "fengdu-utils",
  "version": "1.0.3",
  "main": "dist/index.js",
  "files": [
    "dist"
  ],
  "scripts": {
    "build": "rollup -c"
  },
  "type": "module",
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "@rollup/plugin-terser": "^0.4.4",
    "rollup": "^4.29.1"
  }
}

发布到 npm 上后我们查看 npm 的包结构:

可以看到只有dist目录被上传了,最后打包后的文件体积只有327B,比之前小了一半还多。

总结

通过使用rollup来打包 npm 包,不仅使得 npm 的包结构精简,减少了冗余代码的上传,还减少了包的体积。

如果学会了就赶快去行动吧。