@@ -10,9 +10,9 @@ date: 2024-11-14 11:45
10
10
- [ 打包 es 和 lib 以及样式] ( https://github.com/json-q/rc-library-templete/commit/c9d8a53c26d1189cd05939f57d07b07bfd2c1642 )
11
11
- [ 初始化 storybook 测试打包产物和打包 umd 产物] ( https://github.com/json-q/rc-library-templete/commit/1af4b5316ee2da0ed4febc69e28c19e166d6b5c9 )
12
12
13
- # 安装组件开发依赖
13
+ ## 安装组件开发依赖
14
14
15
- ## react 和 react-dom 依赖集成
15
+ ### react 和 react-dom 依赖集成
16
16
17
17
- ` package.json ` 文件的 peerDependencies 写入 react react-dom
18
18
@@ -35,15 +35,15 @@ date: 2024-11-14 11:45
35
35
pnpm i @types/react @types/react-dom -D
36
36
```
37
37
38
- ## clsx
38
+ ### clsx
39
39
40
40
安装 ` clsx ` 作为样式开发的库,其它用到了再安装即可
41
41
42
42
``` bash
43
43
pnpm i clsx -D
44
44
```
45
45
46
- # 编写 less 样式
46
+ ## 编写 less 样式
47
47
48
48
- 在 ` componets/src ` 下新建 ` style ` 文件夹
49
49
- 新建 ` index.less ` 作为入口文件
@@ -95,7 +95,7 @@ pnpm i clsx -D
95
95
96
96
写这么多是为了在后续编译 less 样式时能看出明显的效果。
97
97
98
- # 编写测试组件 Button
98
+ ## 编写测试组件 Button
99
99
100
100
代码我就不列出来了,大家可以自行编写,或者去仓库看也可以,就是一个简单的示例组件,编写完成后,目录结构如下
101
101
@@ -111,14 +111,14 @@ export type { ButtonProps } from "./button/interface";
111
111
export { default as Button } from " ./button" ;
112
112
```
113
113
114
- # 打包编译
114
+ ## 打包编译
115
115
116
116
- 导出类型声明文件
117
117
- 导出 umd esmodule commonjs 3 种形式产物供使用者引入;
118
118
- 支持样式文件 css 引入,而非只有 less,减少使用者的接入成本;
119
119
- 支持按需加载。
120
120
121
- ## 导出类型声明文件
121
+ ### 导出类型声明文件
122
122
123
123
` tsconfig.json ` 上一节已经写好了,直接使用 tsc 编译即可。
124
124
@@ -134,11 +134,11 @@ export { default as Button } from "./button";
134
134
135
135
其实大部分 npm 包需要做的都是编译,打包基本用不到。
136
136
137
- ## 导出 commonjs 代码
137
+ ### 导出 commonjs 代码
138
138
139
139
打包这个工作,` rollup ` 也可以,不过我们是编译,不是打成 bundler,而且还要处理 css,` rollup ` 就不是很容易处理了。如果是直接打 bundler 的话,` rollup ` 更简单,而且 ` webpack ` 在这方面也很在行。
140
140
141
- ### babel 相关配置
141
+ #### babel 相关配置
142
142
143
143
安装 babel 及其相关依赖,这一部分解释性的话术引用自下方的参考文章。
144
144
@@ -185,7 +185,7 @@ IE 11
185
185
not IE 10
186
186
```
187
187
188
- #### polyfill 相关思考
188
+ ##### polyfill 相关思考
189
189
190
190
很遗憾的是,` @babel/runtime-corejs3 ` 无法在按需引入的基础上根据目标浏览器支持程度再次减少 polyfill 的引入。
191
191
@@ -213,7 +213,7 @@ module.exports = {
213
213
};
214
214
```
215
215
216
- ### gulp 任务编排
216
+ #### gulp 任务编排
217
217
218
218
安装 gulp 相关依赖
219
219
@@ -282,9 +282,9 @@ pnpm i rimraf -D -w
282
282
283
283
![ image] ( https://jsonq.top/cdn-static/2025/02/25/1740465672018-rqpzh6mq.png )
284
284
285
- ## 导出 ESM 代码
285
+ ### 导出 ESM 代码
286
286
287
- ### 修改 babel 配置
287
+ #### 修改 babel 配置
288
288
289
289
为了让 ES Module 更好的支持 [ Tree Shaking] ( https://webpack.docschina.org/guides/tree-shaking/ ) ,需要对 babel 配置做一些改动
290
290
@@ -305,7 +305,7 @@ module.exports = {
305
305
};
306
306
```
307
307
308
- ### gulp 新增 esm 构建任务
308
+ #### gulp 新增 esm 构建任务
309
309
310
310
esm 和 cjs 都走 babel 编译,流程基本一致,可以将编译方法抽离出去,两个任务共用
311
311
@@ -351,12 +351,12 @@ const build = gulp.parallel(gulp.series(compileCJS, compileESM));
351
351
352
352
![ image] ( https://jsonq.top/cdn-static/2025/02/25/1740465672207-ut65dlpr.png )
353
353
354
- ## Less 样式处理
354
+ ### Less 样式处理
355
355
356
356
- 了解流行组件库的样式为什么会是那样的结构
357
357
- 模仿流行组件库的样式结构进行编译,实现样式的按需加载
358
358
359
- ### 为什么是 less?而非 sass 或 css in js?
359
+ #### 为什么是 less?而非 sass 或 css in js?
360
360
361
361
- 个人更对 less 熟悉一些,所以是 less 而不是 sass
362
362
- 对于 cssinjs,个人不喜欢
@@ -365,7 +365,7 @@ const build = gulp.parallel(gulp.series(compileCJS, compileESM));
365
365
- 此处就稍微吐槽一下 ` antd5 ` ,cssinjs 性能做得真的很有问题,组件文档打开速度相对于 v4 来说不知道慢了多少倍(加载时大量的 style 标签动态插入),issue 里也经常有人反映性能问题。
366
366
- 虽说有些零运行时的 cssinjs,但是那些随机类名个人看着也确实不舒服。
367
367
368
- ### 了解流行组件库的样式打包构成
368
+ #### 了解流行组件库的样式打包构成
369
369
370
370
这里就举例国内采用同样技术的组件库:[ antd 4.x] ( https://github.com/ant-design/ant-design/tree/4.x-stable ) 、[ arco design] ( https://github.com/arco-design/arco-design ) 、[ tdesign] ( https://github.com/Tencent/tdesign-react ) ,可以参考一下他们的打包后的结构目录
371
371
@@ -381,7 +381,7 @@ const build = gulp.parallel(gulp.series(compileCJS, compileESM));
381
381
- 拆分成多种类型的入口文件,还可以让用户做** 按需导入** ,
382
382
- 由于要灵活配置,所以开发的组件内部是不能直接导入样式的(不然的话就是写死样式,就不存在多个样式类型的引入方式),样式导入交给用户去做
383
383
384
- ### 拷贝 less 文件至打包目录
384
+ #### 拷贝 less 文件至打包目录
385
385
386
386
将上述的 less 打包结构理解之后,就可以按照这种结构开始打包样式了。
387
387
@@ -405,7 +405,7 @@ const build = gulp.parallel(gulp.series(compileCJS, compileESM), copyLess);
405
405
406
406
![ image] ( https://jsonq.top/cdn-static/2025/02/25/1740465672606-2bccrdfz.png )
407
407
408
- ### less 编译成 css
408
+ #### less 编译成 css
409
409
410
410
安装相关依赖,` gulp-less ` 将 less 编译成 css,` gulp-autoprefixer ` 添加 css 前缀,由于之前设置了 ` .browserslistrc ` ,` gulp-autoprefixer ` 会自动识别兼容的版本去添加前缀
411
411
@@ -439,7 +439,7 @@ const build = gulp.parallel(gulp.series(compileCJS, compileESM), copyLess, less2
439
439
440
440
这里没有对 css 进行压缩,esm 和 lib 会被用户以 npm 方式使用,用户打包时,自然会对 css 进行压缩。
441
441
442
- #### 为什么只对 ` index.less ` 进行编译?
442
+ ##### 为什么只对 ` index.less ` 进行编译?
443
443
444
444
- 每个组件的样式都需要一个合并起来的入口文件,这个文件里引入了该组件所需的所有 less 样式,方便开发者导入。
445
445
- 如果每个 less 都进行编译,那 ` index.less ` 编译出来的就是该组件所有的 css,然后其余的拆分组件也会再编译对应的 css,相当于重复编译了
@@ -468,7 +468,7 @@ const build = gulp.parallel(gulp.series(compileCJS, compileESM), copyLess, less2
468
468
- ` gulp-less ` 在编译 ` index.less ` 时,由于有引入顺序,相当于把 ` var.less ` 和 ` component.less ` 做了合并,这种是完全没问题的,可以正常编译。
469
469
- ` gulp-less ` 编译完 ` index.less ` ,再去编译 ` component.less ` ,发现内部有一个未知的 less 变量,因为此时 ` gulp-less ` 不通过 ` index.less ` 这个桥梁走,而是直接编译 ` component.less ` ,那自然会报错。
470
470
471
- ### 生成 css.js
471
+ #### 生成 css.js
472
472
473
473
生成 css.js 让不安装 less 插件的用户也可以正常使用。
474
474
@@ -541,7 +541,7 @@ function cssInjection(content) {
541
541
542
542
> 其实这一部分很多可以优化的地方,做的更细致一点,大家在看懂之后可以自行尝试优化,比如 ` token.css ` 并不存在(` token.less ` 未被编译),可以去掉,再比如可以把 less 变量编译 cssvar,` css.js ` 可以再额外引入 css 变量,就可以做到动态换肤功能。
543
543
544
- ### 按需加载
544
+ #### 按需加载
545
545
546
546
实际上只要结构上写出来,按需加载的核心就已经完成了。
547
547
@@ -562,7 +562,7 @@ cssinjs 的库都不需要这个,因为 cssinjs 只有 js,天然支持 `tree
562
562
563
563
** 以上内容作为一次 [ commit] ( https://github.com/json-q/rc-library-templete/commit/c9d8a53c26d1189cd05939f57d07b07bfd2c1642 ) 暂存一下**
564
564
565
- ### 整理 package.json 的入口以及导出模块的方式和指向
565
+ #### 整理 package.json 的入口以及导出模块的方式和指向
566
566
567
567
``` json
568
568
{
@@ -597,7 +597,7 @@ cssinjs 的库都不需要这个,因为 cssinjs 只有 js,天然支持 `tree
597
597
598
598
而后边又添加了 ` ./es/*": "./es/* ` 等的指向,是因为我在使用按需加载的过程中发现插件无法从 ` ./es ` 中读取文件,找不到文件路径,而且编辑器无法给出路径提示(看样子确实是没有指定到文件下),所以才有了这一系列的指向,大家可以去掉之后自行尝试一下。
599
599
600
- ### 新增组件实时编译能力
600
+ #### 新增组件实时编译能力
601
601
602
602
本地使用组件库时,当修改了组件想要看到最新效果,就只能重新 ` pnpm build ` 打包,这显然很不方便,好在 ` gulp ` 提供了相关的实时编译支持。
603
603
@@ -625,7 +625,7 @@ exports.watch = watchFiles;
625
625
626
626
> 这个实时编译不太好用,编译方是没问题的,使用方经常无法及时得到响应。
627
627
628
- # 安装 storybook 验证打包成果
628
+ ## 安装 storybook 验证打包成果
629
629
630
630
上一章节我们把 monorepo 的基本文件结构搭建好了,storybook 是直接处于根目录下的子包,此时在该目录下执行初始化命令,暂时不要选择 ` Next ` ,因为 SSR 环境下目前不确定是否会发生意外情况
631
631
@@ -641,15 +641,15 @@ pnpm add rclt-components --workspace
641
641
642
642
storybook 分两个运行界面,一个是 vite + react 默认的模板页面,就是 ` src ` 下的文件,这个也可以作为自己的组件库文档进行开发。一个是根据 ` *.storeis.(tsx|...) ` 生成的 storybook 文档。
643
643
644
- ## 测试组件可用性
644
+ ### 测试组件可用性
645
645
646
646
在 ` App.tsx ` 中导入组件
647
647
648
648
![ image] ( https://jsonq.top/cdn-static/2025/02/25/1740465673340-xbx2ifpr.png )
649
649
650
650
运行 ` pnpm dev ` ,打开即可看到一个很丑的按钮 button,因为没有样式,接下来我们做样式的按需导入
651
651
652
- ## 测试样式的按需加载
652
+ ### 测试样式的按需加载
653
653
654
654
安装 ` vite-plugin-imp `
655
655
@@ -692,7 +692,7 @@ export default defineConfig({
692
692
693
693
> 这么看来在项目结构搭建时可以把 ` storybook` 作为根目录作为项目共享的配置,这样可以直接在 ` components` 文件夹下写 story 文档,结构上更方便查看
694
694
695
- ## 编写文档
695
+ ### 编写文档
696
696
697
697
storybook 的约定文件格式可以在 ` main .ts ` 中看到,我们把它进行稍加修改
698
698
@@ -758,13 +758,13 @@ export const ButtonSize: Story = {
758
758
759
759
样式的按需加载也被 storybook 文档享受到了,不需要单独导入 css。
760
760
761
- # 打包 umd 格式的组件 bundler
761
+ ## 打包 umd 格式的组件 bundler
762
762
763
763
umd 可以直接在浏览器环境使用,各大组件库基本都提供有 umd 格式的组件产物。
764
764
765
765
这里使用的是 webpack 打包 umd,没有选择 rollup,大家根据喜好选择即可,这个比较简单。
766
766
767
- ## webpack 打包 bulder
767
+ ### webpack 打包 bundler
768
768
769
769
安装 webpack 相关依赖和打包用到的 loader:
770
770
@@ -893,7 +893,7 @@ module.exports = merge(prodConfig, commonConfig);
893
893
894
894

895
895
896
- ### 细节优化
896
+ #### 细节优化
897
897
898
898
- webpackbar 打包进度条
899
899
- case-sensitive-paths-webpack-plugin 文件大小写敏感检测(不同平台的路径兼容)
@@ -915,7 +915,7 @@ module.exports = {
915
915
};
916
916
` ` `
917
917
918
- ## 打包 css
918
+ ### 打包 css
919
919
920
920
` webpack` 就算安装 ` less- loader` ,想打包出 css,也是完全没用的,因为 less 样式是完全独立的,组件内部不引入样式,` webpack` 在打包时,完全找不到使用的 less,自然就打包不出来。
921
921
@@ -970,7 +970,7 @@ function less2css() {
970
970
971
971
> 其实 webpack 打包 dist 这块不用拆分出 ` dev` 和 ` prod` 两个文件,可以将配置项作为一个函数,通过传参判断构建的产物类型,作为构建脚本执行会更合适。
972
972
973
- ## 测试 dist
973
+ ### 测试 dist
974
974
975
975
新建一个 ` test- dist .html ` ,引入 react、react-dom、babel 的 umd 链接
976
976
@@ -1011,6 +1011,6 @@ function less2css() {
1011
1011
1012
1012
组件库的打包到此结束!同时期待阅读这篇文章的你有更深入的优化
1013
1013
1014
- # 参考
1014
+ ## 参考
1015
1015
1016
1016
[React 组件库搭建指南(三):编译打包](https://github.com/worldzhao/blog/issues/5)
0 commit comments