最近对团队开发的脚手架研究了下并参与进去做了一点工作,觉得非常的有意思,自此开辟了前端学习的另一条道路。
目的
相信大家在开发过程中都遇到这样的问题:为了新建项目,要不停地拷贝文件,配置什么的,或者干脆从零开始,这样是非常浪费时间的。
这个时候,一个善解人意的scaffold就很被大家需要了,它可以仅用简单的命令就帮助我们完成项目的创建,编译打包,发布等工作,让我们可以专注于我们的核心业务。
总体来说,一个贴心的scaffold可以帮我们解决以下问题:
- 减少重复性的工作,不再需要复制其他项目再删除无关代码,或者从零创建一个项目和文件。
- 根据交互动态生成项目结构和配置文件等。
- 多人协作更为方便,不需要把文件传来传去。
功能实现
通过命令行询问用户并获取用户输入参数,根据用户的输入参数进行项目的创建,启动,编译,发布,删除,更新依赖包等工作。
开发scaffold常用依赖包:
交互界面相关:scaffold需要通过命令行或者可视化工具与用户互动来获取用户的意图,这里我们采用命令行的方式询问用户并获取用户输入。下面的几个包可以帮助我们完成这些事情:
yargs | 通过解析参数并生成优雅的用户界面来构建交互式命令行工具 | https://www.npmjs.com/package... |
inquirer | 常见的交互式命令行用户界面的集合 | https://www.npmjs.com/package... |
chalk | 可以修改控制台中字符串的样式 | https://www.npmjs.com/package... |
yargs用法示例:
#!/usr/bin/env node
require('yargs') // eslint-disable-line
.command('serve [port]', 'start the server', (yargs) => {
yargs
.positional('port', {
describe: 'port to bind on',
default: 5000
})
}, (argv) => {
if (argv.verbose) console.info(`start server on :${argv.port}`)
serve(argv.port)
})
.option('verbose', {
alias: 'v',
type: 'boolean',
description: 'Run with verbose logging'
})
.argv
用--help参数运行此段脚本如下:
node进程和文件操作相关:由于我们的scaffold是在node环境下运行,所以要用到很多node的API,最多的就是子进程child_process和文件系统fs,不过我们并没有使用原生的node API,而是尝试了一些兼容性更好,使用更方便的第三方node依赖包。
cpx | linux的cp命令,多了watching功能 | https://www.npmjs.com/package... |
cross-spawn | node的spawn和spawnSync的跨平台(window,macos等)解决方案 | https://www.npmjs.com/package... |
asnyc | 处理异步javascript | https://www.npmjs.com/package... |
fs-extra | 补充了node的fs模块,支持方法的promise | https://www.npmjs.com/package... |
replace | 用于在文件上执行搜索和替换的命令行实用程序 | https://www.npmjs.com/package... |
empty-dir | 检查目录是否为空 | https://www.npmjs.com/package... |
用法示例:
const spawn = require('cross-spawn');
// Spawn NPM asynchronously
const child = spawn('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' });
// Spawn NPM synchronously
const result = spawn.sync('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' });
文件编译相关:scaffold的开发过程中经常需要处理配置文件的创建,替换内容等,这些都与AST(抽象语法解析树)紧密相关。esprima和escodegen就是两个经常用的处理AST的依赖包。
esprima | 将javascript解析成AST的解析器 | https://www.npmjs.com/package... |
escodegen | 将AST生成javascript | https://www.npmjs.com/package... |
escodegen用法示例:
escodegen.generate({
type: 'BinaryExpression',
operator: '+',
left: { type: 'Literal', value: 40 },
right: { type: 'Literal', value: 2 }
});
esprima用法示例:
var esprima = require('esprima');
var program = 'const answer = 42';
console.log(esprima.tokenize(program));
// 可以看到把const answer = 42解析如下:
[
{ type: 'Keyword', value: 'const' },
{ type: 'Identifier', value: 'answer' },
{ type: 'Punctuator', value: '=' },
{ type: 'Numeric', value: '42' }
]
众多typescript类型文件
当使用第三方库时,我们需要引用它的声明文件,这样才能获得对应的代码补全、接口提示等功能。推荐使用 @types
统一管理第三方库的声明文件,比如@types/async,@types/cross-spawn,@types/empty-dir等。
总体来说开发scaffold是一件很有意思的事情,后面还会继续探索。
参考文章
- #!/usr/bin/env node 到底是什么?https://juejin.im/post/5cb93c...
- typescript声明文件:https://ts.xcatliu.com/basics...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。