在多个前端团队分布全国各地的公司中,如何将项目中的公共组件构建成一个 npm 包并发布呢?本文将分享一种使用 Rollup 构建工具实现这一目标的思路。
首先,我们需要解决构建适配问题。由于应用构建可能使用 webpack、vite 等工具,并包含 tailwindcss、svgr 等功能,Rollup 也需要支持这些特性,以确保构建出的模块与应用行为一致。
我的方案是让开发者提供一个 input 的 glob 选项,然后将这个 input 中的所有文件分别打包成独立的 npm 包。预期的打包效果如下图所示:
实现这一目标,我们需要解决以下几个关键问题:
- 文件结构:如何将分享的模块文件打包到不同的文件结构中(便于发布)
- 描述文件生成:为每个模块生成 package.json 等相关文件
- 导入路径重定向:处理代码中需要重定向的导入路径
文件结构
Rollup 的 input 选项可以影响打包后的目录结构。为了定制化组件的输出目录结构,我们需要修改 input 选项。这里采用了一种将文件路径映射为模块名称的算法,例如:
- src/components/actions.tsx -> @app-xxx/components-actions
- src/pages/form/components/a/index.tsx -> @app-xxx/form-components-a
同时,我们还需要设置 output.enentryFileNames 为 [name]/index.js,这样 src/components/actions.tsx 文件就会被打包到 @app-xxx/components-actions/index.js
描述文件生成
生成 package.json 需要获取当前模块即将发布的版本号和依赖项。
- 获取模块当前版本号可以使用 npm view 命令
- 计算即将发布的版本号可以使用 semver npm 库进行递增
依赖项的生成
- 生成 external match:使用当前应用的 package.json 文件中的 dependencies、peerDependencies 和分享模块列表,组成一个字符串数组,构建正则表达式来匹配导入路径
- 使用导入路径进行匹配:Rollup 在每个模块构建后会生成一个 output 对象,该对象中的 imports 数组可用于匹配正则
导入路径重定向
如果不进行处理,打包后的代码可能会出现如下情况:
为解决这个问题,我采用了一个简单直接的方法:使用正则表达式替换文件内容
总结与展望
- 最终,我实现了一个 Rollup 插件来处理上述过程,仓库地址。
- 除了提取项目中的公共组件,我们还需要让其他团队成员能够查看 npm 仓库中的组件,最好能实现预览效果。
- 为此,我使用 Storybook 结合上述功能开发了一个组件分享平台。该平台利用 Storybook 的 CSF 概念作为组件分享单元,提供一个网页版,列出所有应用分享的组件及其预览效果。由于这部分内容较多,后续有机会再详细分享。
通过这种方式,我们不仅实现了公共组件的提取和发布,还为团队协作提供了更好的可视化工具,提高了开发效率和代码复用率。