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

2020-06-17 06:38:37易采站长站整理

实现方案

根据以上思路,我先定义了属于我们项目自己的

ignore
文件,取名为
templates.ignore

然后在这个

ignore
文件中添加需要被忽略的文件名。


{{#unless supportMacawAdmin}}
# 如果不开启admin后台,登录页面和密码修改页面是不需要的
src/entry/login.js
src/entry/password.js
{{/unless}}

# 最终生成的项目中不需要ignore文字自身
templates.ignore

然后在

lib/generator.js
中添加对
templates.ignore
的处理逻辑


// ...

const minimatch = require('minimatch') // https://github.com/isaacs/minimatch

module.exports = function (metadata = {}, src, dest = '.') {
if (!src) {
return Promise.reject(new Error(`无效的source:${src}`))
}

return new Promise((resolve, reject) => {
const metalsmith = Metalsmith(process.cwd())
.metadata(metadata)
.clean(false)
.source(src)
.destination(dest)
// 判断下载的项目模板中是否有templates.ignore
const ignoreFile = path.join(src, 'templates.ignore')
if (fs.existsSync(ignoreFile)) {
// 定义一个用于移除模板中被忽略文件的metalsmith插件
metalsmith.use((files, metalsmith, done) => {
const meta = metalsmith.metadata()
// 先对ignore文件进行渲染,然后按行切割ignore文件的内容,拿到被忽略清单
const ignores = Handlebars.compile(fs.readFileSync(ignoreFile).toString())(meta)
.split('n').filter(item => !!item.length)
Object.keys(files).forEach(fileName => {
// 移除被忽略的文件
ignores.forEach(ignorePattern => {
if (minimatch(fileName, ignorePattern)) {
delete files[fileName] }
})
})
done()
})
}
metalsmith.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()
})
})
}

基于插件思想的metalsmith很好扩展,实现也不复杂,具体过程可参见代码中的注释。

总结

经过对vue-cli的整理,借助了很多node模块,整个脚手架的实现并不复杂。

将项目模板与脚手架工具分离,可以更好的维护模板和脚手架工具。
通过commander.js处理命令行