Element源码系列——build:file命令
build:file是一个组合命令,它由四个子命令构成.命令大致都是通过解析配置文件,生成最终文件.
那么下面,让我们来一个一个具体的看看每个命令是做什么的.
1.icon图标初始化 node build/bin/iconInit.js
该子命令的作用是读取icon的样式表,通过解析样式表.最终生成一份所有可用的icon清单
它承接了样式表与官方文档icon介绍之间的关系,也是说当我们在样式表中添加新的字体图标时,只需重新编译文件后打包网站代码就可以实现更新
(1).首先通过fs.readFileSync读取’../../packages/theme-chalk/src/’下的icon.scss文件,所有已经编写好的字体icon样式代码都在该文件中。
var fontFile = fs.readFileSync(path.resolve(__dirname, '../../packages/theme-chalk/src/icon.scss'), 'utf8');
// icon.scss文件部分代码
// .el-icon-info:before { content: "\e61a"; } "\e61a"为注册的字体
// .el-icon-error:before { content: "\e62c"; }
(2).通过postcss解析后样式表后,通过正则捕获el-icon-(xxx):before中的内容,并存入数组中
var nodes = postcss.parse(fontFile).nodes;
var classList = [];
var reg = new RegExp(/\.el-icon-([^:]+):before/);
var arr = selector.match(reg);
if (arr && arr[1]) {
classList.push(arr[1]); //arr[1]为第一个捕获组
}
(3).生成’../../examples/icon.json’ 文件
fs.writeFile(path.resolve(__dirname, '../../examples/icon.json'), JSON.stringify(classList), () => {});
// icon.json文件格式如下
// ["info","error","success","warning",......]
(4).在’../../examples/docs/icon.md’中调用icon.json文件,生成网页文档
</script>
var iconList = require('examples/icon.json');
export default {
data() {
return {
icons: iconList //获取json文件中的数组
};
}
}
<script>
<ul class="icon-list">
<li v-for="name in icons" :key="name"> //遍历数组数据生成所有已配置的icon
<span>
<i :class="'el-icon-' + name"></i>
<span class="icon-name">{{'el-icon-' + name}}</span>
</span>
</li>
</ul>
2.编译入口文件 node build/bin/build.entry.js
我们在开发时,为了考虑分工以及效率等因素,开发的源码肯定是分模块分包的.但是考虑到别人使用方便,一次引入的版本肯定是必须的,再不济也要为webpack考虑下.所以,每次打包前都要修改入口文件的代码肯定是不可取的.这个命令就是为了解决入口文件的问题,他会通过解析json文件,并使用字符串模板生成一个入口文件.
(1).编写字符串模板
// 入口文件导出路径
var OUTPUT_PATH = path.join(__dirname, '../../src/index.js');
// import文件模板
var IMPORT_TEMPLATE = 'import {{name}} from \'../packages/{{package}}/index.js\';';
// 安装组件名称模板
var INSTALL_COMPONENT_TEMPLATE = ' {{name}}';
// 主模板中{{ inclue }},{{ install }},{{ version }},{{ list }}为需要替换的模板语法
// {{ include }} 需要替换为 import Row from '../packages/row/index.js';
// {{ install }} 是为需要安装的组件
// {{ version }} 是当前版本号
// {{ list }} 是最终导出的模块
var MAIN_TEMPLATE = `/* Automatically generated by './build/bin/build-entry.js' */
{{include}}
import locale from 'element-ui/src/locale';
import CollapseTransition from 'element-ui/src/transitions/collapse-transition';
const components = [
{{install}},
CollapseTransition
];
。。。
module.exports = {
version: '{{version}}',
locale: locale.use,
i18n: locale.i18n,
install,
CollapseTransition,
Loading,
{{list}}
};`;
(2).通过json-templater 插件对模板进行编译
// render函数会将第二个参数中的key,与{{ mustache }}语法模板中的变量一一对应,最终以value值对其替换
var render = require('json-templater/string');
// EOL是当前系统下的行尾符的常量。windows下为'\r\n'
var endOfLine = require('os').EOL;
// render模板
var template = render(MAIN_TEMPLATE, {
// import语法字符串,通过endOfLine进行换行
include: includeComponentTemplate.join(endOfLine),
// Vue安装组件字符串,通过,加上endOfLine进行分割
install: installTemplate.join(',' + endOfLine),
// 获取版本信息
version: process.env.VERSION || require('../../package.json').version,
// 导出模块,通过,加上endOfLine进行分割
list: listTemplate.join(',' + endOfLine)
});
(3).写入文件
var OUTPUT_PATH = path.join(__dirname, '../../src/index.js');
fs.writeFileSync(OUTPUT_PATH, template); // 写入文件
// 最终生成的入口文件index.js
import Pagination from '../packages/pagination/index.js';
import Dialog from '../packages/dialog/index.js';
...
const components = [
Pagination,
Dialog,
Autocomplete,
...
]
module.exports = {
version: '2.3.6',
locale: locale.use,
i18n: locale.i18n,
install,
CollapseTransition,
Loading,
Pagination,
Dialog,
...
}
...
3.node build/bin/i18n.js
国际化用老土点的话说就是一套网页模板,里面的内容语言不同,选择不同的语言内容而已.而这个命令就是干这个事情的
(1).获取page.json文件,文件中主要存放了按照约定编写的三套网页内容
// 获取json文件
var langConfig = require('../../examples/i18n/page.json');
page.json文件格式如下,可以看到数据一个数组.每个数组存放了一种语言.pages字段下所代表的的是不同的页面.
而1,2,3等序号就是我们需要根据不同语言所替换模板中的内容.
[
{
"lang": "zh-CN",
"pages": {
"index": {
"1": "网站快速成型工具",
"2": "Element,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库",
"3": "指南",
"4": "了解设计指南,帮助产品设计人员搭建逻辑清晰、结构合理且高效易用的产品。",
"5": "查看详情",
"6": "组件",
"7": "使用组件 Demo 快速体验交互细节;使用前端框架封装的代码帮助工程师快速开发。",
"8": "资源",
"9": "下载相关资源,用其快速搭建页面原型或高保真视觉稿,提升产品设计效率。",
"lang": "zh-CN",
"titleSize": "34",
"paraSize": "18"
},
"component": {},
"changelog": {
"1": "更新日志",
"2": "zh-CN"
},
"design": {
"1": "设计原则",
"2": "一致",
...
}
...
}
...
},
...
]
(2).遍历文件,生成文件
在了解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);
});
});
4.编译版本信息 node build/bin/version.js
该命令主要作用取package.json或者配置环境信息中的版本号,生成version.json,并通过Vue组件读取json文件生成示例页面
var fs = require('fs');
var path = require('path');
// 获取版本信息
var version = process.env.VERSION || require('../../package.json').version;
// 重要版本列表
var content = { '1.4.13': '1.4', '2.0.11': '2.0', '2.1.0': '2.1', '2.2.2': '2.2', '2.3.9': '2.3' };
// 添加当前版本信息
if (!content[version]) content[version] = '2.4';
// 写入文件
fs.writeFileSync(path.resolve(__dirname,
'../../examples/versions.json'), JSON.stringify(content));
// versions.json
{"1.4.13":"1.4","2.0.11":"2.0","2.1.0":"2.1","2.2.2":"2.2","2.3.9":"2.3","2.4.3":"2.4"}
// 调用文件../examples/components/header.vue
created() {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = _ => {
if (xhr.readyState === 4 && xhr.status === 200) {
const versions = JSON.parse(xhr.responseText);
//复制对象
this.versions = Object.keys(versions).reduce((prev, next) => {
prev[next] = versions[next];
return prev;
}, {});
}
};
xhr.open('GET', '/versions.json'); //请求json数据
xhr.send();
}
总结
感谢阅读!
感觉element团队的贡献!
如需跳转,请点Element源码系列——搭建开发环境