lmk123 / blog

个人技术博客,博文写在 Issues 里。
https://github.com/lmk123/blog/issues
623 stars 35 forks source link

开发 NPM 包时可能不需要将代码打包进一个文件里 #123

Open lmk123 opened 1 year ago

lmk123 commented 1 year ago

我目前正在写很多个 NPM 包。我使用 es module 写了源码,然后用 Rollup 将它们打包在一个文件里,并同时提供 CommonJS 和 es module 的格式。

但最近我开始意识到,我似乎不需要这样做。

我发现,将所有代码打包在同一个文件里的话,很难“优化”。

举个例子,浏览器扩展程序的代码有两种运行环境:内容脚本只能使用一部分 Chrome API,而扩展程序内的其它页面(背景页、弹出页页等)可以使用所有 Chrome API,这种情况下,我需要单独给内容脚本加一个 entry:

// index.js 导出全部
import { runInBackground, runInContent } from 'my-module'

// content-only.js 仅导出只能在内容脚本环境运行的代码
import { runInContent } from 'my-module/content-only'

这样用 Rollup 打包的话就有一个问题,那就是 runInContent 的代码同时出现在了 index.js 和 content-only.js 的 bundle 里。这可能没什么大不了的,但我觉得最理想的方式应该是由 index.js 引入 content-only.js:

// content-only.js
export function runInContent() {}

// index.js
export { runInContent } from './content-only'
export function runInBackground () {}

如果要用 Rollup 做到这一点,那就需要改一些配置,但是我又想到——如果不把代码打包成一个文件的话,不就天然支持这种形式吗?

这么一想,我发现这样做有很多好处:

关于 Webpack 的 sideEffects Webpack 的 sideEffects 的原理似乎是拆分 import,举个例子: ```js // 当我们引用了模块里的某个方法时 import { runInBackground } from 'my-module' // Webpack 会分析 runInBackground 的来源,最终只引入定义了这个函数的文件,比如 import { runInBackground } from 'my-module/lib/background.js' ``` 这样的话就不用导入整个 'my-module',只会导入 'my-module/lib/background.js'。但是如果我们将 my-module 整个打包成一个文件,那么这个优化就不起作用了,因为 my-module 并没有被拆分成多个文件,runInBackground 就在 bundle 里。 找到了一篇比较好的解释 https://stackoverflow.com/a/69866774

坏处就是用户在消费我的 NPM 包的时候需要做一些配置,但我觉得这样利大于弊:

我担心将 NPM 包打包成一个文件可能有一些好处,但我谷歌了一下 do we need bundle npm package code,推荐的结果都觉得 NPM 包(再次强调,特指 NPM 包)不需要打包成同一个文件:

我准备试试。