引言
因为业务须要,近期团队要搞一套本人的 UI
组件库,框架方面还是 Vue
。而业界曾经有比拟成熟的一些UI
库了,比方 ElementUI
、AntDesign
、Vant
等。
联合框架 Vue
,咱们抉择在ElementUI
根底上进行革新。但 造轮子
绝非易事,首先须要先去理解它整个但构建流程、目录设计等。
本文通过剖析 ElementUI
残缺的构建流程,最初给出搭建一个齐备的组件库须要做的一些工作,心愿对于想理解 ElementUI
源码或者也有搭建 UI
组件库需要的你,能够提供一些帮忙!
咱们先来看下 ElementUI
的源码的目录构造。
目录构造解析
- github:寄存了
Element UI
奉献指南、issue
和PR
模板 - build:寄存了打包相干的配置文件
- examples:组件相干示例 demo
- packages:组件源码
- src:寄存入口文件和一些工具辅助函数
- test:单元测试相干文件,这也是一个优良的开源我的项目必备的
- types:类型申明文件
说完文件目录,剩下还有几个文件(常见的 .babelrc
、.eslintc
这里就不开展阐明了),在业务代码中是不常见的:
- .travis.yml:继续集成 (CI) 的配置文件
- CHANGELOG:更新日志,这里
Element UI
提供了四种不同语言的,也是很贴心了 - components.json:表明了组件的文件门路,不便
webpack
打包时获取组件的文件门路。 - FAQ.md:
ElementUI
开发者对常见问题的解答。 - LICENSE:开源许可证,
Element UI
应用的是MIT
协定 - Makefile:
Makefile
是一个实用于C/C++
的工具,在领有make
环境的目录下,如果存在一个Makefile
文件。那么输出make
命令将会执行Makefile
文件中的某个指标命令。
深刻理解构建流程前,咱们先来看下 ElementUI
源码的几个比拟次要的文件目录,这对于前面钻研ElementUI
的残缺流程是有帮忙的。
package.json
通常咱们去看一个大型项目都是从 package.json
文件开始看起的,这外面蕴含了我的项目的版本、入口、脚本、依赖等要害信息。
我这里拿出了几个关键字段,一一的去剖析、解释他的含意。
main
我的项目的入口文件
import Element from 'element-ui'
时候引入的就是main
中的文件
lib/element-ui.common.js
是 commonjs
标准,而 lib/index.js
是umd
标准,这个我在前面的打包模块会具体阐明。
files
指定 npm publish
发包时须要蕴含的文件 / 目录。
typings
TypeScript
入口文件。
home
我的项目的线上地址
unpkg
当你把一个包公布到 npm
上时,它同时应该也能够在 unpkg
上获取到。也就是说,你的代码既可能在 NodeJs
环境也可能在 浏览器环境
执行。为此你须要用 umd
格局打包,lib/index.js
是 umd
标准,由 webpack.conf.js
生成。
style
申明款式入口文件,这里是lib/theme-chalk/index.css
,前面也会具体阐明。
scripts
开发、测试、生产构建,打包、部署,测试用例等相干脚本。scripts
算是 package.json
中最重要的局部了,上面我会一一对其中的重要指令进行阐明。
bootstrap
"bootstrap": "yarn || npm i"
装置依赖,官网举荐优先选用 yarn
(吐槽一句:我刚开始没看明确,想着bootstrap
不是之前用过的那个 ui 库吗 ????,起初看了下,原来 bootstrap
翻译过去是 疏导程序
的意思,这样看看也就大略了解了 ????)
build:file
该指令次要用来自动化生成一些文件。
"build:file": "node build/bin/iconInit.js & node build/bin/build-entry.js & node build/bin/i18n.js & node build/bin/version.js"
这条指令较长,咱们拆开来看:
build/bin/iconInit.js
解析 icon.scss
,把所有的icon
的名字放在 icon.json
外面 最初挂在 Vue
原型上的 $icon
上。
最初通过遍历icon.json
,失去了官网的这种成果:
build/bin/build-entry.js
依据 components.json
文件,生成 src/index.js
文件,外围就是 json-templater/string
插件的应用。
咱们先来看下 src/index.js
文件,他对应的是我的项目的入口文件,最下面有这样一句:
/* Automatically generated by './build/bin/build-entry.js' */
也就是 src/index.js
文件是由 build/bin/build-entry.js
脚本主动构建的。咱们来看下源码:
// 依据 components.json 生成 src/index.js 文件
// 引入所有组件的依赖关系
var Components = require("../../components.json");
var fs = require("fs");
// https://www.npmjs.com/package/json-templater 能够让 string 与变量联合 输入一些内容
var render = require("json-templater/string");
// https://github.com/SamVerschueren/uppercamelcase 转化为驼峰 foo-bar >> FooBar
var uppercamelcase = require("uppercamelcase");
var path = require("path");
// os.EOL 属性是一个常量,返回以后操作系统的换行符(Windows 零碎是 \r\n,其余零碎是 \n)var endOfLine = require("os").EOL;
// 生成文件的名字和门路
var OUTPUT_PATH = path.join(__dirname, "../../src/index.js");
var IMPORT_TEMPLATE =
"import {{name}} from'../packages/{{package}}/index.js';";
var INSTALL_COMPONENT_TEMPLATE = "{{name}}";
// var MAIN_TEMPLATE = `/* Automatically generated by './build/bin/build-entry.js' */
// ...
// 获取所有组件的名字,寄存在数组中
var ComponentNames = Object.keys(Components);
var includeComponentTemplate = [];
var installTemplate = [];
var listTemplate = [];
ComponentNames.forEach((name) => {var componentName = uppercamelcase(name);
includeComponentTemplate.push(
render(IMPORT_TEMPLATE, {
name: componentName,
package: name,
})
);
if (
[
"Loading",
"MessageBox",
"Notification",
"Message",
"InfiniteScroll",
].indexOf(componentName) === -1
) {
installTemplate.push(
render(INSTALL_COMPONENT_TEMPLATE, {
name: componentName,
component: name,
})
);
}
if (componentName !== "Loading") listTemplate.push(` ${componentName}`);
});
var template = render(MAIN_TEMPLATE, {include: includeComponentTemplate.join(endOfLine),
install: installTemplate.join("," + endOfLine),
version: process.env.VERSION || require("../../package.json").version,
list: listTemplate.join("," + endOfLine),
});
// 后果输入到 src/index.js 中
fs.writeFileSync(OUTPUT_PATH, template);
console.log("[build entry] DONE:", OUTPUT_PATH);
其实就是下面说的,依据 components.json
,生成src/index.js
文件。
build/bin/i18n.js
依据 examples/i18n/page.json
和模版,生成不同语言的 demo
,也就是官网 demo 展现国际化的解决。
ElementUI
官网的国际化根据的模版是 examples/pages/template
,依据不同的语言,别离生成不同的文件:
这外面都是 .tpl
文件,每个文件对应一个模版,而且每个 tpl
文件又都是合乎 SFC
标准的 Vue
文件。
咱们轻易关上一个文件:
export default {data() {
return {
lang: this.$route.meta.lang,
navsData: [
{
path: "/design",
name: "<%= 1 >",
},
{
path: "/nav",
name: "<%= 2 >",
},
],
};
},
};
外面都有数字标示了须要国际化解决的中央。
首页所有国际化相干的字段对应关系存储在 examples/i18n/page.json
中:
最终官网展现进去的就是通过下面国际化解决后的页面:
反对切换不同语言。
绕了一圈,回到主题:build/bin/i18n.js
帮咱们做了什么呢?
咱们思考一个问题:首页的展现是如何做到依据不同语言,生成不同的 vue
文件呢?
这就是 build/bin/i18n.js
帮咱们做的事件。
来看下对应的源码:
"use strict";
var fs = require("fs");
var path = require("path");
var langConfig = require("../../examples/i18n/page.json");
langConfig.forEach((lang) => {
try {fs.statSync(path.resolve(__dirname, `../../examples/pages/${lang.lang}`));
} catch (e) {fs.mkdirSync(path.resolve(__dirname, `../../examples/pages/${lang.lang}`));
}
Object.keys(lang.pages).forEach((page) => {
var templatePath = path.resolve(
__dirname,
`../../examples/pages/template/${page}.tpl`
);
var outputPath = path.resolve(
__dirname,
`../../examples/pages/${lang.lang}/${page}.vue`
);
var content = fs.readFileSync(templatePath, "utf8");
var pairs = lang.pages[page];
Object.keys(pairs).forEach((key) => {
content = content.replace(new RegExp(`<%=\\s*${key}\\s*>`, "g"),
pairs[key]
);
});
fs.writeFileSync(outputPath, content);
});
});
解决流程也很简略:遍历 examples/i18n/page.json
,依据不同的数据结构把tpl
文件的标记位,通过正则匹配进去,并替换成本人事后设定好的字段。
这样官网首页的国际化就实现了。
build/bin/version.js
依据 package.json
中的version
, 生成examples/versions.json
,对应就是残缺的版本列表
build:theme
解决款式相干。
"build:theme": "node build/bin/gen-cssfile && gulp build --gulpfile packages/theme-chalk/gulpfile.js && cp-cli packages/theme-chalk/lib lib/theme-chalk",
同样这一条也关联了多个操作,咱们拆开来看。
build/bin/gen-cssfile
这一步是依据 components.json
,生成package/theme-chalk/index.scss
文件,把所有组件的款式都导入到index.scss
。
其实是做了一个自动化导入操作,前面每次新增组件,就不必手动去引入新增组件的款式了。
gulp build –gulpfile packages/theme-chalk/gulpfile.js
咱们都晓得 ElementUI
在应用时有两种引入形式:
- 全局引入
import Vue from "vue";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
import App from "./App.vue";
Vue.use(ElementUI);
new Vue({
el: "#app",
render: (h) => h(App),
});
- 按需引入
import Vue from "vue";
import {Pagination, Dropdown} from "element-ui";
import App from "./App.vue";
Vue.use(Pagination);
Vue.use(Dropdown);
new Vue({
el: "#app",
render: (h) => h(App),
});
对应两种引入形式,Element
在打包时对应的也有两种计划。
具体如下:将 packages/theme-chalk
下的所有 scss
文件编译为 css
,当你须要全局引入时,就去引入index.scss
文件;当你按需引入时,引入对应的组件 scss
文件即可。
这其中有一点,咱们须要思考下:如何把 packages/theme-chalk
下的所有 scss
文件编译为css
?
在平时的开发中,咱们打包、压缩之类的工作往往都会交给 webpack
去解决,然而,针对下面这个问题,咱们如果采纳 gulp
基于工作流去解决会更加不便。
gulp
相干的解决就在 packages/theme-chalk/gulpfile.js
中:
"use strict";
const {series, src, dest} = require("gulp");
const sass = require("gulp-sass"); // 编译 gulp 工具
const autoprefixer = require("gulp-autoprefixer"); // 增加厂商前缀
const cssmin = require("gulp-cssmin"); // 压缩 css
function compile() {return src("./src/*.scss") // src 下的所有 scss 文件
.pipe(sass.sync()) // 把 scss 文件编译成 css
.pipe(
autoprefixer({
// 基于指标浏览器版本,增加厂商前缀
browsers: ["ie > 9", "last 2 versions"],
cascade: false,
})
)
.pipe(cssmin()) // 压缩 css
.pipe(dest("./lib")); // 输入到 lib 下
}
function copyfont() {return src("./src/fonts/**") // 读取 src/fonts 下的所有文件
.pipe(cssmin())
.pipe(dest("./lib/fonts")); // 输入到 lib/fonts 下
}
exports.build = series(compile, copyfont);
通过解决,最终就会打包出对应的款式文件
cp-cli packages/theme-chalk/lib lib/theme-chalk
cp-cli
是一个跨平台的copy
工具,和CopyWebpackPlugin
相似
这里就是复制文件到 lib/theme-chalk
下。
下面提到过屡次components.json
,上面就来理解下。
components.json
这个文件其实就是记录了组件的门路,在自动化生成文件以及入口时会用到:
{
"pagination": "./packages/pagination/index.js",
"dialog": "./packages/dialog/index.js",
"autocomplete": "./packages/autocomplete/index.js",
// ...
"avatar": "./packages/avatar/index.js",
"drawer": "./packages/drawer/index.js",
"popconfirm": "./packages/popconfirm/index.js"
}
packages
寄存着组件库的源码和组件款式文件。
这里以 Alert
组件为例做下阐明:
Alert 文件夹
这里 main.vue
对应就是组件源码,而 index.js
就是入口文件:
import Alert from "./src/main";
/* istanbul ignore next */
Alert.install = function (Vue) {Vue.component(Alert.name, Alert);
};
export default Alert;
引入组件,而后为组件提供 install
办法,让 Vue
能够通过 Vue.use(Alert)
去应用。
对于
install
能够看官网文档
packages/theme-chalk
这外面寄存的就是所有组件相干的款式,下面也曾经做过阐明了,外面有 index.scss
(用于全局引入时导出所有组件款式)和其余每个组件对应的scss
文件(用于按需引入时导出对应的组件款式)
src
说了半天,终于绕到了 src
文件夹。
下面的 packages
文件夹是离开去解决每个组件,而 src
的作用就是把所有的组件做一个对立解决,同时蕴含自定义指令、我的项目整体入口、组件国际化、组件 mixins、动画的封装和公共办法。
咱们次要来看下入口文件,也就是src/index.js
:
/* Automatically generated by './build/bin/build-entry.js' */
// 导入了 packages 下的所有组件
import Pagination from "../packages/pagination/index.js";
import Dialog from "../packages/dialog/index.js";
import Autocomplete from "../packages/autocomplete/index.js";
// ...
const components = [
Pagination,
Dialog,
Autocomplete,
// ...
];
// 提供了 install 办法,帮咱们挂载了一些组件与变量
const install = function (Vue, opts = {}) {locale.use(opts.locale);
locale.i18n(opts.i18n);
// 把所有的组件注册到 Vue 下面
components.forEach((component) => {Vue.component(component.name, component);
});
Vue.use(InfiniteScroll);
Vue.use(Loading.directive);
Vue.prototype.$ELEMENT = {
size: opts.size || "",
zIndex: opts.zIndex || 2000,
};
Vue.prototype.$loading = Loading.service;
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;
Vue.prototype.$confirm = MessageBox.confirm;
Vue.prototype.$prompt = MessageBox.prompt;
Vue.prototype.$notify = Notification;
Vue.prototype.$message = Message;
};
/* istanbul ignore if */
if (typeof window !== "undefined" && window.Vue) {install(window.Vue);
}
// 导出版本号、install 办法(插件)、以及一些性能比方国际化性能
export default {
version: "2.13.2",
locale: locale.use,
i18n: locale.i18n,
install,
Pagination,
Dialog,
Autocomplete,
// ...
};
文件结尾的:
/* Automatically generated by './build/bin/build-entry.js' */
其实在下面的 scripts
的build/bin/build-entry.js
中咱们曾经提到过:src/index.js
是由 build-entry
脚本主动生成的。
这个文件次要做下以下事件:
- 导入了
packages
下的所有组件 - 对外裸露了
install
办法,把所有的组件注册到Vue
下面,并在Vue
原型上挂载了一些全局变量和办法 - 最终将
install
办法、变量、办法导出
examples
寄存了 ElementUI
的组件示例。
其实从目录构造,咱们不难看出这是一个残缺独立的 Vue
我的项目。次要用于官网文档的展现:
这里咱们次要关注下 docs
文件夹:Element
官网反对 4 种语言,docs
一共有 4 个文件夹,每个文件夹外面的内容根本是一样的。
咱们能够看到外面全部都是 md
文档,而每一个 md
文档,别离对应着官网组件的展现页面。
其实当初各大支流组件库文档都是用采纳
md
编写。
咱们下面大抵理解了源码的几个次要文件目录,然而都比拟扩散。上面咱们从构建指令到新建组件、打包流程、公布组件残缺的看一下构建流程。
构建流程梳理
构建指令(Makefile)
平时咱们都习惯将我的项目罕用的脚本放在 package.json
中的 scripts
中。但 ElementUI
还应用了 Makefile
文件(因为文件内容较多,这里就选取了几个做下阐明):
.PHONY: dist test
default: help
# build all theme
build-theme:
npm run build:theme
install:
npm install
install-cn:
npm install --registry=http://registry.npm.taobao.org
dev:
npm run dev
play:
npm run dev:play
new:
node build/bin/new.js $(filter-out $@,$(MAKECMDGOALS))
dist: install
npm run dist
deploy:
@npm run deploy
pub:
npm run pub
test:
npm run test:watch
// Tip:
// make new <component-name> [中文]
// 1、将新建组件增加到 components.json
// 2、增加到 index.scss
// 3、增加到 element-ui.d.ts
// 4、创立 package
// 5、增加到 nav.config.json
我是第一次见,所以就去 Google
下,网上对 Makefile
对定义大略是这样:
Makefile
是一个实用于C/C++
的工具,较早作为工程化工具呈现在UNIX
零碎中,通过make
命令来执行一系列的编译和连贯操作。在领有make
环境的目录下,如果存在一个Makefile
文件。那么输出make
命令将会执行Makefile
文件中的某个指标命令。
这里我以 make install
为例简要阐明下执行流程:
- 执行
make
命令,在该目录下找到Makefile
文件。 - 找到
Makefile
文件中对应命令行参数的install
指标。这里的指标就是npm install
构建入口文件
咱们看下 scripts
中的 dev
指令:
"dev":
"npm run bootstrap &&
npm run build:file &&
cross-env NODE_ENV=development
webpack-dev-server --config build/webpack.demo.js &
node build/bin/template.js",
首先 npm run bootstrap
是用来装置依赖的。
npm run build:file
在后面也有提到,次要用来自动化生成一些文件。次要是 node build/bin/build-entry.js
,用于生成Element
的入口 js
:先是读取根目录的components.json
,这个json
文件维护着 Element
所有的组件门路映射关系,键为组件名,值为组件源码的入口文件;而后遍历键值,将所有组件进行 import
,对外裸露install
办法,把所有 import
的组件通过 Vue.component(name, component)
形式注册为全局组件,并且把一些弹窗类的组件挂载到 Vue
的原型链上(这个在下面介绍 scripts
相干脚本时有具体阐明)。
在生成了入口文件的 src/index.js
之后就会运行webpack-dev-server
。
webpack-dev-server --config build/webpack.demo.js
这个后面也提过,用于跑 Element
官网的根底配置。
新建组件
下面咱们提到了,Element
中还用了 makefile
为咱们编写了一些额定的脚本。
这里重点说一下 make new <component-name> [中文]
这个命令。
当运行这个命令的时候,其实运行的是 node build/bin/new.js
。
build/bin/new.js
比较简单,备注也很清晰,它帮咱们做了上面几件事:
1、新建的组件增加到components.json
2、在 packages/theme-chalk/src
下新建对应到组件 scss
文件,并增加到 packages/theme-chalk/src/index.scss
中
3、增加到 element-ui.d.ts
,也就是对应的类型申明文件
4、创立 package
(咱们下面有提到组件相干的源码都在package
目录下寄存)
5、增加到 nav.config.json
(也就是官网 组件
左侧的菜单)
打包流程剖析
ElementUI
打包执行的脚本是:
"dist":
"npm run clean &&
npm run build:file &&
npm run lint &&
webpack --config build/webpack.conf.js && webpack --config build/webpack.common.js && webpack --config build/webpack.component.js &&
npm run build:utils &&
npm run build:umd &&
npm run build:theme",
上面咱们一一来进行剖析:
npm run clean(清理文件)
"clean": "rimraf lib && rimraf packages/*/lib && rimraf test/**/coverage",
删除之前打包生成文件。
npm run build:file(生成入口文件)
依据 components.json
生成入口文件 src/index.js
,以及i18n
相干文件。这个在下面曾经做过剖析,这里就不再开展进行阐明。
npm run lint(代码查看)
"lint": "eslint src/**/* test/**/* packages/**/* build/**/* --quiet",
我的项目 eslint
检测,这也是当初我的项目必备的。
文件打包相干
webpack --config build/webpack.conf.js &&
webpack --config build/webpack.common.js &&
webpack --config build/webpack.component.js
build/webpack.conf.js
生成 umd
格局的 js
文件(index.js)
build/webpack.common.js
生成 commonjs
格局的 js
文件(element-ui.common.js),require
时默认加载的是这个文件。
build/webpack.component.js
以 components.json
为入口,将每一个组件打包生成一个文件,用于按需加载。
npm run build:utils(转译工具办法)
"build:utils": "cross-env BABEL_ENV=utils babel src --out-dir lib --ignore src/index.js",
把 src
目录下的除了 index.js
入口文件外的其余文件通过 babel
转译,而后挪动到 lib
文件夹下。
npm run build:umd(语言包)
"build:umd": "node build/bin/build-locale.js",
生成 umd
模块的语言包。
npm run build:theme(生成款式文件)
"build:theme": "node build/bin/gen-cssfile && gulp build --gulpfile packages/theme-chalk/gulpfile.js && cp-cli packages/theme-chalk/lib lib/theme-chalk",
依据 components.json
,生成package/theme-chalk/index.scss
。用gulp
构建工具,编译 scss
、压缩、输入css
到lib
目录。
最初用一张图来形容上述整个打包流程:
公布流程
打包实现,紧跟着就是代码的公布了。Element
中公布次要是用 shell
脚本实现的。
Element
公布一共波及三个局部:
1、git 公布
2、npm 公布
3、官网公布
公布对应的脚本是:
"pub":
"npm run bootstrap &&
sh build/git-release.sh &&
sh build/release.sh &&
node build/bin/gen-indices.js &&
sh build/deploy-faas.sh",
sh build/git-release.sh(代码冲突检测)
运行 git-release.sh
进行 git
抵触的检测,这里次要是检测 dev
分支是否抵触,因为 Element
是在 dev
分支进行开发的。
#!/usr/bin/env sh
# 切换至 dev 分支
git checkout dev
# 检测本地和暂存区是否还有未提交的文件
if test -n "$(git status --porcelain)"; then
echo 'Unclean working tree. Commit or stash changes first.' >&2;
exit 128;
fi
# 检测本地分支是否有误
if ! git fetch --quiet 2>/dev/null; then
echo 'There was a problem fetching your branch. Run `git fetch` to see more...' >&2;
exit 128;
fi
# 检测本地分支是否落后近程分支
if test "0" != "$(git rev-list --count --left-only @'{u}'...HEAD)"; then
echo 'Remote history differ. Please pull changes.' >&2;
exit 128;
fi
# 通过以上查看,示意代码无抵触
echo 'No conflicts.' >&2;
公布 npm && 官网更新
dev
分支代码检测没有抵触,接下来就会执行 release.sh
脚本,合并 dev
分支到master
、更新版本号、推送代码到近程仓库并公布到npm
(npm publish)。
官网更新大抵就是:将动态资源生成到 examples/element-ui
目录下,而后放到 gh-pages
分支,这样就能通过 github pages
的形式拜访。
到这里 ElementUI
的残缺构建流程就剖析完了。
ui 组件库搭建指北
通过对 ElementUI
源码文件和构建流程的剖析,上面咱们能够总结一下搭建一个齐备的 ui 组件库都须要做什么工作。
目录构造
目录构造对于大型项目是尤其重要的,正当清晰的构造对于前期的开发和扩大都是很有意义的。ui
组件库的目录构造,我感觉 ElementUI
的就很不错:
|-- Element
|-- .babelrc // babel 相干配置
|-- .eslintignore
|-- .eslintrc // eslint 相干配置
|-- .gitattributes
|-- .gitignore
|-- .travis.yml // ci 配置
|-- CHANGELOG.en-US.md
|-- CHANGELOG.es.md
|-- CHANGELOG.fr-FR.md
|-- CHANGELOG.zh-CN.md // 版本改变阐明
|-- FAQ.md // 常见问题 QA
|-- LICENSE // 版权协定相干
|-- Makefile // 脚本汇合(工程化编译)|-- README.md // 我的项目阐明文档
|-- components.json // 组件配置文件
|-- element_logo.svg
|-- package.json
|-- yarn.lock
|-- .github // 贡献者、issue、PR 模版
| |-- CONTRIBUTING.en-US.md
| |-- CONTRIBUTING.es.md
| |-- CONTRIBUTING.fr-FR.md
| |-- CONTRIBUTING.zh-CN.md
| |-- ISSUE_TEMPLATE.md
| |-- PULL_REQUEST_TEMPLATE.md
| |-- stale.yml
|-- build // 打包
|-- examples // 示例代码
|-- packages // 组件源码
|-- src // 入口文件以及各种辅助文件
|-- test // 单元测试文件
|-- types // 类型申明
组件开发
参考大多数 UI
组件库的做法,能够将 examples
下的示例代码组织起来并裸露一个入口,应用 webpack
配置一个 dev-server
,后续对组件的调试、运行都在此 dev-server
下进行。
单元测试
UI
组件作为高度形象的根底公共组件,编写单元测试是很有必要的。合格的单元测试也是一个成熟的开源我的项目必备的。
打包
对于打包后的文件,对立放在 lib
目录下,同时记得要在 .gitignore
中加上 lib
目录,防止将打包后果提交到代码库中。
同时针对引入形式的不同,要提供 全局引入
(UMD)和 按需加载
两种模式的包。
文档
组件库的文档个别都是对外可拜访的,因而须要部署到服务器上,同时也需具备本地预览的性能。
公布
组件库的某个版本实现开发工作后,须要将包公布到 npm 上。公布流程:
- 执行测试用例
- 打包构建
- 更新版本号
- npm 包公布
- 打 tag
- 自动化部署
保护
公布后须要日常保护之前老版本,个别须要留神一下几点:
- issue(bug 修复)
- pull request(代码 pr)
- CHANGELOG.md(版本改变记录)
- CONTRIBUTING.md(我的项目贡献者及标准)
参考
- https://segmentfault.com/a/11…
- https://zhuanlan.zhihu.com/p/…
❤️ 爱心三连击
1. 如果感觉这篇文章还不错,来个 分享、点赞、在看 三连吧,让更多的人也看到~
2. 关注公众号 前端森林,定期为你推送陈腐干货好文。
3. 非凡阶段,带好口罩,做好集体防护。