详解基于node.js的脚手架工具开发经历(4)

模板引擎我选择handlebars。当然,还可以有其他选择,例如ejsjade swig

用handlebars的语法对模板做一些调整,例如修改模板中的 package.json

{ "name": "{{projectName}}", "version": "{{projectVersion}}", "description": "{{projectDescription}}", "author": "Forcs Zhang", "private": true, "scripts": { "dev": "node build/dev-server.js", "start": "node build/dev-server.js", "build": "node build/build.js", "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", "test": "npm run unit", "lint": "eslint --ext .js,.vue src test/unit/specs" }, "dependencies": { "element-ui": "^2.0.7", "macaw-ui": "{{supportUiVersion}}", "vue": "^2.5.2", "vue-router": "^2.3.1" }, ... }

package.json 的 name 、 version 、 description 字段的内容被替换成了handlebar语法的占位符,模板中其他地方也做类似的替换,完成后重新提交模板的更新。

实现脚手架给模板插值的功能

在 lib 目录下创建 generator.js ,封装metalsmith。

touch ./lib/generator.js

// npm i handlebars metalsmith -D const Metalsmith = require('metalsmith') const Handlebars = require('handlebars') const rm = require('rimraf').sync module.exports = function (metadata = {}, src, dest = '.') { if (!src) { return Promise.reject(new Error(`无效的source:${src}`)) } return new Promise((resolve, reject) => { Metalsmith(process.cwd()) .metadata(metadata) .clean(false) .source(src) .destination(dest) .use((files, metalsmith, done) => { const meta = metalsmith.metadata() Object.keys(files).forEach(fileName => { const t = files[fileName].contents.toString() files[fileName].contents = new Buffer(Handlebars.compile(t)(meta)) }) done() }).build(err => { rm(src) err ? reject(err) : resolve() }) }) }

给 macaw-init.js 的 go() 添加生成逻辑。

// ... const generator = require('../lib/generator') function go () { next.then(projectRoot => { // ... }).then(context => { // 添加生成的逻辑 return generator(context) }).then(context => { console.log('创建成功:)') }).catch(err => { console.error(`创建失败:${err.message}`) }) }

至此,一个带交互,可动态给模板插值的脚手架算是基本完成了。

tips:墙裂推荐一下tj的另一个工具包: consolidate.js ,在vue-cli中发现的,感兴趣的话可以去了解一下。

美化我们的脚手架

通过一些工具包,让脚手架更加人性化。这里介绍两个在vue-cli中发现的工具包:

ora - 显示spinner

chalk - 给枯燥的终端界面添加一些色彩

这两个工具包用起来不复杂,用好了会让脚手架看起来更加高大上

用ora优化加载等待的交互

ora可以用在加载等待的场景中,比如脚手架中下载项目模板的时候可以使用,如果给模板插值生成项目的过程也有明显等待的话,也可以使用。

以下载为例,对 download.js 做一些改良:

npm i ora -D

const download = require('download-git-repo') const ora = require('ora') module.exports = function (target) { target = path.join(target || '.', '.download-temp') return new Promise(resolve, reject) { const url = 'https://github.com:username/templates-repo.git#master' const spinner = ora(`正在下载项目模板,源地址:${url}`) spinner.start() download(url, target, { clone: true }, (err) => { if (err) { spinner.fail() // wrong :( reject(err) } else { spinner.succeed() // ok :) resolve(target) } }) } }

用chalk优化终端信息的显示效果

chalk可以给终端文字设置颜色。

// ... const chalk = require('chalk') const logSymbols = require('log-symbols') // ... function go () { // ... next.then(/* ... */) /* ... */ .then(context => { // 成功用绿色显示,给出积极的反馈 console.log(logSymbols.success, chalk.green('创建成功:)')) console.log() console.log(chalk.green('cd ' + context.root + '\nnpm install\nnpm run dev')) }).catch(err => { // 失败了用红色,增强提示 console.error(logSymbols.error, chalk.red(`创建失败:${error.message}`)) }) }

详解基于node.js的脚手架工具开发经历

根据输入项移除模板中不需要的文件

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/c562e77570651779402799b9885046b8.html