搭建工程不打算采用create-react-app脚手架来搭建,因为脚手架封装好了很多东西,而有些东西对于组件库并不适用,用来搭建组件库过于臃肿,因此我不打算借助任何脚手架来搭建工程。
首先,先创建一个工程文件夹pony-react-ui,在该文件夹下执行如下命令:
npminit//生成package.jsontsc--init//生成tsconfig.json然后,按照如下目录结构初始化工程:
pony-react-ui├──src├──assets├──components├──Button├──Button.tsx└──index.ts└──Dialog├──Dialog.tsx└──index.ts├──styles├──_button.scss├──_dialog.scss├──_mixins.scss├──_variables.scss└──pony.scss└──index.ts//打包的入口文件,引入pony.scss,抛出每一个组件├──index.js//主文件入口,package.json中main字段指定的文件├──package.json├──tsconfig.json//指定了用来编译这个项目的根文件和编译选项├──webpack.config.js└──README.md编写一个Button组件Button组件应该满足一下需求:
Button.tsx
export*from'./Button';这样,一个示例组件就基本完成了,有同学肯定会有这么一个疑问,为什么在Button.tsx中没有引入它的样式文件_button.scss,而是在使用时引入全局样式或者单独引入_button.scss呢?
//单独引入组件样式import{Button}from'pony-react-ui';import'pony-react-ui/lib/styles/button.scss';//全局引入组件样式,打包时抽离出来的样式import'pony-react-ui/lib/styles/index.scss';这跟样式的权重有关,通过import引入的样式权重会低于JSX中className定义的样式,因此才可以在组件外部修改内部的样式。
举个实例:
import{Button}from'pony-react-ui';import'pony-react-ui/lib/styles/button.scss';importstylesfrom'./index.module.scss';constDemo=()=>(
├──styles├──_button.scss├──_dialog.scss├──_mixins.scss├──_variables.scss└──pony.scss我在style文件下存放所有的样式文件,与_button.scss、_dialog.scss类型的样式文件属于组件的样式文件,_mixins.scss用于存放mixin指令,提高样式逻辑复用
//_mixins.scss@mixincolors($text,$border,$background){color:$text;background-color:$background;border-color:$border;}//设置按钮大小@mixinbutton-size($padding-x,$height,$font-size){height:$height;padding:0$padding-x;font-size:$font-size;line-height:($height-2);}比如,在_button.scss中使用
$values:#ff0000,#00ff00,#0000ff;.primary{@includecolors($values...);}node-sass会将其编译成
.primary{color:#ff0000;background-color:#00ff00;border-color:#0000ff;}_variables.scss用于存放一些样式常量,比如定义不同尺寸按钮的字体大小:
$button-font-size:14px!default;$button-xl-font-size:16px!default;$button-lg-font-size:16px!default;$button-sm-font-size:12px!default;pony.scss会引入所有的样式文件,_mixins.scss、_variables.scss这类工具类样式文件需要置前引入,因为后面的组件样式文件可能依赖它们
@import'variables';@import'mixins';@import'button';@import'dialog';...在对样式文件构建处理时,我没有使用cssmodules去避免样式重名,而是使用BEM规范书写样式规避这一问题。为什么我要这么做呢?
rules:[{test:/\.(sa|sc|c)ss$/,use:[loader:'css-loader',options:{modules:false//禁止cssmodules}]}]因为使用cssmodules导致无法从组件外部修改组件内部样式。通常,从外部修改组件样式一般会这样写:
.btn{:global{//下次修改Button组件构建后,生成的hash不一定为sadf6756.pony-button-promary-sadf6756{color:#da2227;}}}构建打包入口文件src/index.ts为webpack构建入口文件
import'./styles/pony.scss';export*from'./components/Button';export*from'./components/Dialog';这里会引入全局样式文件,在构建时MiniCssExtractPlugin会对样式进行抽离压缩,然后分离输出JS脚本和CSS脚本
在构建之前,我们必须明确组件库的使用场景。现在常见会通过esmodule以及CommonJS引入,有些场景下会直接使用