第二章 前端工程化实战
模块一 开发脚手架及封装自动化构建工作流
Yeoman使用
安装yeoman
yarn global add yo
1
安装对应的generator
yarn global add generator-node
1
在对应文件目录下运行generator
mkdir yo-test
cd yo-test
yo node
1
2
3
2
3
生成webapp类型的generator
yarn global add generator-webapp
mkdir yo-web
cd yo-web
yo webapp
1
2
3
4
2
3
4
自定义 generator
自定义 generator 的名称必须为 generator-<name>
这种形式

安装基类 generator
yarn add yeoman-generator
1
将 generator link到全局
yarn link
1
使用自定义 generator
yo sample
1
index.js 内容
// generator的核心入口,需要导出一个继承自 yeoman-generator 的类型
const Generator = require("yeoman-generator");
module.exports = class extends Generator {
// 接收用户输入方法
prompting() {
return this.prompt([
{
type: "input",
name: "title",
message: "your title",
default: this.appname, // 项目目录名称
},
]).then((answers) => {
this.answers = answers;
});
}
// 生成文件方法
writing() {
// 通过fs.write方法直接生成文件并写入内容
// this.fs.write(this.destinationPath("temp.txt"), Math.random().toString());
// 通过模板文件生成文件
// 模板地址 templates文件夹下
const temp = this.templatePath("foo.txt");
// 输出文件目录
const output = this.destinationPath("foo.txt");
// 模板数据上下文,ejs内的数据
// const context = { title: "hello", success: true };
// 接收用户输入的数据
const context = this.answers;
// 输出文件
// this.fs.copyTpl(temp, output, context);
// 多个文件通过文件相对路径数组的形式生成
const templates = ["foo.txt", "temp.txt"];
templates.forEach((item) => {
this.fs.copyTpl(this.templatePath(item), this.destinationPath(item), this.answers);
});
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
发布自定义 generator , 发布时注意npm的镜像地址
yarn publish
1
Plop使用
安装 Plop 到开发依赖
yarn add plop --dev
1
在项目目录下新增 plopfile.js 文件,为plop的入口,需要导出一个函数
module.exports = plop => {
// 模板的名称为component,之后执行yarn plop component命令生成
plop.setGenerator("component", {
description: "create a component",
prompts: [
{
type: "input",
name: "name",
message: "component name",
default: "Mycomponent"
}
],
actions: [
{
type: "add", // add为新增文件
path: "src/components/{{name}}/{{name}}.js",
templateFile: "plop-templates/components.hbs" // 模板的地址,为hbs类型文件
}
]
});
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
生成模板
yarn plop component
1
模块二 模块化开发与规范化标准
模块化开发
在浏览器环境采用 ES Moudles规范,在node环境采用 CommonJS规范
ES Moudles 特性
// 1. 通过给 script 标签添加 type = module 让script成为一个module
<script type="module">
console.log(123)
</script>
// 2. ES modules 自动采用严格模式,忽略了 'use strict' 声明
<script type="module">
console.log(this) // undefined
</script>
// 3. 每个 ES modules 都是运行在单独的私有作用域中
<script type="module">
var a = 1
console.log(a) // 1
</script>
<script type="module">
console.log(a) // 报错
</script>
// 4. ES modules 中的外部地址引用 src 文件时,时通过CORS的方式请求外部 JS 模块
<script type="module" src="https://xxx.con/xxx.js"></script> // 可能跨域
// 5. ES modules 的 script 标签会延迟执行脚本,等同于 defer 属性
<script type="text/javascript">
alert(1)
</script>
<p>内容</p> // 内容会被阻塞不显示
<script type="module">
alert(1)
</script>
<p>内容</p> // 内容会直接显示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
webpack5
使用 asset 模块 代替之前的一些loader
// asset/reseource --> file-loader
// asset/inline --> url-loader
// asset/source --> raw-loader
// asset
// module.rules 下配置loader的地方
{
test: /\.(png|svg|gif|jpe?g)$/,
type: 'asset/resource', // 代替 file-loader 的情况
generator: {
filename: 'img/[name].[hash:4][ext]'
}
}
{
test: /\.(png|svg|gif|jpe?g)$/,
type: 'asset/inline' // 代替 url-loader 的情况
}
{
test: /\.(png|svg|gif|jpe?g)$/,
type: 'asset',
generator: {
filename: 'img/[name].[hash:4][ext]'
},
parser: { // 处理 url-loader 的其他配置
dataUrlCondition: {
maxSize: 10 * 1024
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33