目录划分
开发组件库与开发项目的目录划分区别是很大的,我们再组件库开发时通常会把项目氛围源代码包,输出包、还有使用案例宝等等,这里不同的组件库的规划方式不同,带来的结果也不同。
开发环境构建
依赖安装
npm i webpack webpack-cli webpack-dev-server -D
npm i html-webpack-plugin -D
安装搭建Vue项目所需要的依赖包
npm i vue -D // 这里必须-D 安装, 因为项目构建时不能加入vue的源代码
npm i vue-loader -D
npm i vue-template-compiler -D
在webpack.dev.js总加入兼容vue框架的配置
const {VueLoaderPlugin} = require('vue-loader')
//....
module: {
rules: [
{
test: '/\.vue$/',
use: {
loader: 'vue-loader'
}
}
]
},
plugins: [
new VueLoaderPlugin(),
...
]
预处理器
npm i sass sass-loader -D
npm i style-loader css-loader -D
在webpack.dev.js中加入scss文件的loader配置信息
{
test: /\.scss$/,
use: [
{loader: 'style-loader'},
{loader: 'css-loader'},
{loader: 'sass-loader'}
]
}
关于css与js分离
为什么将css设计在js外部
由于项目是适用webpack打包构建工具进行构建项目的,其css的提取工具并不能将自由度完全交给开发者来进行构建,所以开发者无法随意的定义CSS生成文件的输出目录,文件名称以及构建过程等内容,所以通常我们把CSS样式单独设计出来,后期使用专门的CSS打包构建工具单独构建CSS这样可以更灵活的定义全局的样式系统
调试阶段的注意事项
在调试阶段,所有样式都只能使用index.scss进行加载,并且调试阶段采用的并不是构建之后的文件结构进行加载,所以调试阶段使用example项目仅仅是项目内部调试使用,后续还需要进行pack操作发布再进行调用
src/index 中模块编排代码
const {version, name} = require('../package.json')
// 将 ../packages/index.js中导出的模块合并汇总
import * as Components from '../packages'
// 将../package.js中的模块单独导出
export * from '../packages'
// 通过install函数自动注册每一个组件
const install = (app) => {
Object.keys(Componets).forEach(key => {
app.use(Components[key])
})
}
// 导出组件库整体对象
export default {
install,
version,
name
}
目前已经成功的将组件库的基本结构定义出来并在实际项目中使用,但我们之前一直在开发环境操作,demo项目中导入的也是src中源代码的内容。这种方式的组件库并不能满足真正的技术团队中跨项目分享组件的能力,我们最后也想ElementUI一样去构建组件库的安装包,所以需要对当前定义的生产环境配置。
生产环境的构建目的与应用开发的区别
生产环境的构建目的是输出一份不限于任何项目结构的静态组件资源,该资源支持全量和按需导入的方式提供给开发者们使用,这样开发者便无需将我们的组件库代码加载到其项目的src目录下,实现对项目的扩展同事又能提供灵活的运用方式。
组件库构建详解
打包构建项目配置
webpack.prod.js
const path = require('path')
const {VueLoaderPlugin} = require('vue-loader')
module.exports = {
mode: 'production',
devtool: 'source-map',
entry: {
index: './src/index.js',
button: './packages/button',
asside: './packages/aside',
main: './packages/main',
header: './packages/header',
container: './packages/container'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'lib'),
library: {
name: 'TdUi',
type: 'umd'
},
clean: true
},
module: {
rules: [
{
test: /\.vue$/,
use: {loader: 'vue-loader'}
}
]
},
externals: ['vue'],
plugins: [new VueLoaderPlugin()]
}
package.json 加入命令
"build": "webpack --config webpack.prod.js --progress --color"
构建JS与构建CSS分离及其原因
在构建项目的过程中,我们发现所有的样式文件都不是在组件库内部代码引入的,所以构建项目后生成的组件库代码并没有css样式,这是因为为了极致的精简组件库,我们希望每一个歹毒的组件都会对应自己的单独样式,这样我们再构建组件库的时候功能代码和样式代码使用两种方式单独构建才能让组件库更加灵活的主观选择。
所以我们通常会在组件库项目中使用webpack之外的脚手架进行样式构建 比如gulp
使用gulp构建css及其原因
gulp是一套基于stream的构建系统,他由于配置简单,速度快 深受很多开发者的追捧,尤其是在webpack没有流行的时代,gulp相当于是当时打包构建工具的王者。在webpack出现后,gulp仍然因为其自身的特色在研发层面被大量使用。
之所以使用gulp来构建css样式是因为 webpack是一个JavaScript为核心的构建工具,所以在构建时虽然可以通过插件提取css但是必须基于JavaScript文件作为入口,所以这种操作是很受限制的,在构建UI框架的过程中使用gulp可以大大降低维护样式的成本。
安装依赖
npm i gulp gulp-cli -D
npm i gulp-sass gulp-sass-glob -D
npm i sass node-sass -D
npm i gulp-postcss postcss cssnano autoprefixer -D
配置
创建.browserslistrc文件并初始化内容 确保css可以补全兼容性前缀
> 0.25%
last 2 versions
创建gulpfile.js
const {src, dest, series} = require('gulp')
var sass = require('gulp-sass')(require('sass'))
var sassGlob = require('gulp-sass-glob')
var postcss = require('gulp-postcss')
var autoprefixer = require('autoprefixer')
var cssnano = require('cssnano')
function scss () {
var plugins = [
autoprefixer(),
cssnano()
]
return src('src/styles/*.scss')
.pipe(sassGlob())
.pipe(sass())
.pipe(postcss(plugins))
.pipe(dest('lib/styles'))
}
exports.default = series(scss)
package.json添加构建命令
"build:stype": "gulp",
peerDependencies的作用
当项目构建步骤完成后,需要在项目的package.json中追加一些配置,这里最重要的配置就是peerDependencies
由于我们开发的框架是基于Vue框架运行的UI组件库,所以在安装组件库时必须确保已经安装了vue框架,为了确保开发者可以明确知道我们的UI库是依赖Vue框架的,这里我们可以通过peerDependencies指定的vue的依赖包,指定后该项目弱作为依赖被其他开发者安装,开发者在安装时控制台会提示该项目必须依赖其他安装包,
所以接下来package.json中配置的peerDependencies属性代码如下
{
"peerDependencies": {
"vue": "^3.2.31"
}
}
本地发布
在本地打包前,我们需要继续修改package.json文件在其中加入如下内容(不要将注释放在package中)
{
"main": "lib/index.js",
"files": ["lib", "src", "packages", "example"]
}
设置后可以通过版本控制工具将版本提升一下再打包
npm version patch -m "构建本地测试包"
npm pack
按需引入
借助babel-plugin-component 我们可以只引入需要的组件,已达到减小项目体积的目的。
首先安装babel-plugin-component
npm i babel-plugin-component -D
然后将.babelrc修改为
{
"presets": [["es2015", {"modules": false}]],
"plugins": [
[
"component"
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
在项目的babel.config.js文件中加入如下配置
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
[
"component",
{
"libraryName": "tdui",
"styleLibraryName": "styles"
}
]
]
}
UI组件文档的设计要求
UI组件的文档设计风格已经越来越统一化,所有的UI文档大多遵循统一排版和菜单模式,每个菜单项对应一个固定的组件,该组件的说明需要包含组件的效果案例,组件的代码案例,组件的参数说明和组件的事件说明,还有在线调试功能。无论使用任何框架的生态,目前的文档创建规则大体都是这样的,我们可以参考ElementUI
UI组件文档的常用编写方式介绍
编写帮助文档最极简的方式就是直接使用MarkDown语法编写项目的readme.md说明文件,这种方式效率高,开发速度快,不过复杂功能的UI组件无法直接在MD文件中使用所以会导致文档不生动,提高学习门槛。
还有其他方式就是通过网页制作的方式直接通过我们的UI组件库创建一个新项目,通过编程的方式编写组件库的开发文档,这种方式可以非常生动的描绘组件库的文档,不过开发过程复杂,没有任何可复用的编码,所以性价比极低。
最后又很多开发者将文档需求整理后制作了一些前端快速构建文档项目的框架,这种框架即保留了markdown的高效率,又增加了编程式文档带来的生动效果,所以深受广大开发者的喜爱。
文档库常用工具
vuepress
官方文档http://caibaojian.com/vuepress/guide
优点是定制效果非常好,可以实现任何你想实现的文档效果,学习成本低,门槛低。
缺点是有些框架内部的坑,只能编写Vue框架的文档
storybook 文档工具
官方文档https://storybook.js.org
优点是支持很多主流的前端框架用来构建文档系统,自由度高功能及其强大
缺点是文档服务器为国际站,并没有中文版,阅读门槛高,访问要求网络链路好