共计 14941 个字符,预计需要花费 38 分钟才能阅读完成。
引言
因为业务须要,近期团队要搞一套本人的 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. 非凡阶段,带好口罩,做好集体防护。