Description
背景
脚手架在前端工程化领域的重要性不言而喻,每个公司(或团队)都会根据自己的业务特性维护适合自己的脚手架。具体来说其重要性体现在以下几个方面:
- 统一开发流程(项目初始化,启动,打包,部署都可以收拢在脚手架内部完成,业务人员只用关注业务即可);
- 与其他基建能力更好的配合,比如代码检测,mock等。都可以在脚手架层面对接;
既然如此,那作为一个前端人员,得理解脚手架的工作原理以及其基本实现吧。接下来我们一步一步从零开始完成一个简单的脚手架。
项目搭建
初始化项目
mkdir simple-cli
cd simple-cli
mkdir cli // 存放cli源码的目录
mkdir demo // 存放demo的目录
进入到cli
目录(后续操作默认都在cli目录下)
平平无奇,直接执行npm init
。一顿回车就能得到一个项目。但是只有一个package.json
文件。
同一层级新建index.js
#!/usr/bin/env node
// 上边这一行代码很重要,指定开发环境为 node
console.log('---index.js-----')
全局链接配置
package.json
文件增加配置:
{
"bin": {
"simple-cli": "index.js"
}
}
bin
的配置很重要,用来指明对应可执行文件的位置。 未来用户通过npm
全局安装我们的脚手架之后,就可以执行simple-cli
指令了。
更多关于package.json配置的解读在这里。
但是这个包还在开发阶段,当然不可能安装了。此时可以借助另一个指令npm link
。控制台进入当前目录下执行:
npm link
此时npm
会将bin
下的指令链接到全局(未来可以通过npm unlink
断开)。
此时在控制台执行:
simple-cli // 输出 ---index.js-----
babel配置
脚手架的执行环境是node
。而node
是遵循CommonJs
的。 为了能执行ES6
代码,则需要对我们的代码进行转义。继续在package.json
中增加如下配置:
"scripts": {
"dev": "npx babel src --watch --out-dir lib"
}
这个配置的含义是:babel
转义src
目录下的文件,并输出到lib
目录下, --watch
的含义是监听src
目录,当该目录下有代码改动时,就会重新编译一次。
配置 .babelrc, 新建文件cli/.babelrc
:
{
"presets": [
"@babel/preset-env"
]
}
控制台执行:
npm install @babel/cli --save-dev
npm install @babel/core --save-dev
npm install @babel/preset-env --save-dev
npm run dev
新建文件src/index.js
,写入代码:
console.log('src/index.js')
此时会自动新建一个文件lib/index.js
,其内容就是src/index.js
转义后的代码。
修改cli/index.js
文件代码为:
#!/usr/bin/env node
// 上边这一行代码很重要,指定开发环境为 node
require('./lib/index')
此时控制台输入
simple-cli // 输出'src/index.js'
到这里得到如下目录:
.
├── cli
│ ├── index.js
│ ├── lib
│ │ └── index.js
│ ├── package.json
│ ├── .babelrc
│ └── src
│ └── index.js
└── demo
我们的项目基础配置已经完成了。后续在src目录下开发具体功能。
定义基础指令
对于一个脚手架工具,应该具有以下基础指令:
simple-cli start
simple-cli build
simple-cli publish
这里借助commander
来实现其定义。 首先npm install commander --save-dev
。修改src/index.js
文件:
import { program } from 'commander'
const pkg = require('../package.json')
// 定义 -v/ --version 指令
program.version(`当前版本: ${pkg.version}`, '-v, --version', 'get current version')
// 自定义指令 start
program
.command('start')
.description('start a program')
.action(() => {
// todo
console.log('command start ')
})
// 自定义指令 build
program
.command('build')
.description('build program')
.action(() => {
// todo
console.log('command build')
})
// 自定义指令 publish
program
.command('publish')
.description('publish program')
.action(() => {
// todo
console.log('command publish')
})
program.parse(process.argv)
此时控制台执行simple-cli help
将得到如下输出:
Options:
-v, --version get current version
-h, --help display help for command
Commands:
start start a program
build build program
publish publish program
help [command] display help for command
这里只做了其定义,每个指令的具体实现将在后面陆续实现。
未完待续