使用dumi搭建React 组件库并发布包
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用dumi搭建React 组件库并发布包相关的知识,希望对你有一定的参考价值。
参考技术A 前情:原先在github找个别人写好的组件库研究搭建的webpack配置,结果很多问题,经过一天的修修改改才能install、build及link。研究了一天后了解到dumi,为组件开发场景而生的文档工具。具体的搭建可以查看下文的链接,就不献丑了。dumi 文档: https://d.umijs.org/zh-CN
首先使用npm run build完成构建打包
再在组件库目录下执行:npm link
最后在本地的其他项目下执行:npm link [组件库的packagejs的name]
场景描述:现有项目 my-app 及 组件库 dumi-ui(package文件里的name:dumi-ui)
注意:设置了淘宝镜像会影响登录,如果登录不成功可以试一下
dumi组件库打包总结
最近在做页面抽成组件然后发布,期间也是遇到了很多问题和坑,现在顺便分享一下。
dumi为组件开发场景而生的文档工具,这里注重分享打包的过程,
father
dumi使用father打包,father文档
1 使用rollup打包的时候报错。
father提供了几种打包的方式,umd, cjs, esm。
也支持使用rollup或者babel来打包成cjs/esm。
一开始选择的是rollup来打包。
出现的问题:
- rollup只支持esmodule,不支持commonjs,如果你的组件库引用了类似于lodash的库,lodash是commonjs的,就会报错。这时候可以配置extraExternals。
- 比如我的组件库使用了lodash.debounce和lodash的throttle方法,
export default
cjs: type: 'rollup' ,
esm:
type: 'rollup',
,
cssModules: true,
extraExternals: [
'lodash.debounce',
'lodash.throttle',
],
- extraExternals表示为rollup模式配置额外的external。这样debounce的代码不会被打包进index.js,而是换成了
var debounce = require('lodash.debounce');
var throttle = require('lodash.throttle');
直接require。
2 peerDependencies和dependencies
一文搞懂peerDependencies
假设denpendencies是这样的
dependencies:
"ahooks": "^2.10.12",
"antd": "^4.19.3",
"crypto-js": "^4.1.1",
"react": "^16.12.0",
这时候外部引用的时候,不管版本是否一致,都会打包两份react,两份antd。
而使用了peerDependencies之后
peerDependencies:
"ahooks": "^2.10.12",
"antd": ">=4.19.3",
"crypto-js": "^4.1.1",
"react": ">=16.12.0",
,
dependencies:
"ahooks": "^2.10.12",
"antd": ">=4.19.3",
"crypto-js": "^4.1.1",
"react": ">=16.12.0",
比如当外部的react版本是17的,就满足条件,那么组件库不会多打包一份react代码,而是直接使用外部引用项目的react。
- 这里i还有一个注意的点,配置了peerDependencies之后,不能配置webpack的resolve.modules去指定第三方库的位置
3 组件库配置antd样式前缀问题
因为是从页面抽离成组件,所以一开始是有配置antd样式前缀的,但是打包成组件库之后便无法使用样式前缀了。
- 原因:组件库依赖的antd,并不会在打包的时候直接将代码打包到输出产物。
- 简单理解就是,antd的代码,是在外部引用组件库的时候,比较antd版本的区别,
- 如果符合,那么组件库使用的antd就是项目的antd。而项目的antd我们无法控制他使用跟组件库一样的样式前缀。
- 如果不符合,那么组件库会多打包出一份antd的代码,而这个antd同样是没有webpack来帮我们修改样式文件的前缀的。
- 上面两种情况就会导致组件库手动修改的antd前缀修改,如自己定义的.ant-xxx的.ant会被修改前缀,但是引用的css/less文件的前缀还是.ant
使用babel打包代码
- 使用rollup打包后的代码,全部都输出到一个文件,这也是rollup的特色。
- 但是组件库的方式不适合使用rollup打包,不利于按需引入。
- 引入一个组件,会导致全部都被引入,打包体积大大增加。比如一个组件依赖了一些大一点的库,但是我引入了其他的一个组件,也会导致没引入的组件和他依赖的库都被打包了。
- 使用rollup打包后的体积:
test就是引入组件的页面,vendors~test…是组件库依赖的第三方文件,其中就包括没有引用的组件的依赖也被打包了。
改造,使用babel打包代码。参考antd的代码结构。
cjs: type: 'babel', lazy: true ,
esm:
type: 'babel',
//importLibToEs: true,
,
cjs打包后的代码在lib,esm打包后的代码在es。
package.json配置
"main": "lib/index.js",
"module": "es/index.js",
main字段,会在外部项目引入组件库的时候,当打包的时候就会找到lib/index.js文件,就是cjs的方式。
module字段,会在外部项目引入组件库的时候,当本地启动的时候,就会找到es/index.js文件。
使用了babel之后,打包后的代码结构如
不会将所有代码打包到一个文件去了。
为了配合babel-plugin-imports插件实现按需引入,我们的文件命名和目录结构选择跟antd类似的即可。
babel打包遇到路径别名问题。
babel形式的打包,如果遇到了’@/xx’,他不会解析@,这时候就需要另一个插件来帮忙了。
babel-plugin-module-resolver
extraBabelPlugins: [
[
'import',
libraryName: 'antd',
//libraryDirectory: 'es',
style: true,
,
],
[
require.resolve('babel-plugin-module-resolver'),
root: ['./'],
alias:
'@': './es',
,
,
],
],
他会将@转换成es的相对路径,但是对于cjs来说,文件夹是lib,所以这样配也有问题,暂时没有找到好的解决办法,所以将只能将别名一一改掉,如果只需要打包一种形式的,就可以使用该插件,如只打包esm。
改进后效果:
跟上面的例子一样,正常引入一个组件。然后在.babelrc.js文件中配置bable-plugin-imports,npm上有他的很多配置。
他可以帮助我们转化代码实现按需引入,比如上面的import button,到打包后就转成require(‘antd/lib/button’)。
这时候我们配置
module.exports =
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": [
[
"import",
"libraryName": "antd",
"style": true
],
// 配置我们的组件库按需引入
[
"import",
"libraryName": "xxxx",
"libraryDirectory": "lib",
//"camel2DashComponentName": false,
// "customName": (name, file) =>
// name = name[0].toLowerCase() + name.slice(1)
// return `xxxx/$name`;
//
,
"xxxx"
]
]
然后,正常打包,
再对比使用rollup打包的组件库
左边是rollup,右边是babel打包加按需加载的效果。
可以看到,test是引用了组件的页面,
- 在rollup下,所有的包括组件库依赖的第三方依赖也会被打包进来。
- 在babel打包+babel-plugin-import插件的帮助下,只打包进了引用的组件。
如果没有使用babel-plugin-import
打包后的代码也是全量引入。
以上是关于使用dumi搭建React 组件库并发布包的主要内容,如果未能解决你的问题,请参考以下文章