新世纪福音脚手架
she said, "it's futuristic."
好的作品不在于其形式,重要的是内容,我的很多音乐作品都是没有名字的,然而没有名字的东西无法商业流通,所以你才会看到我那些没有特殊意义、单纯靠滚键盘得到的名字。 —— 泽野弘之曾经这样说过(其实并没有)。
这篇文章也是这个道理,想介绍一下我在半年前开始做的脚手架工具。给文章起标题也是一件很困难的事,最开始想到的是「史上最优雅的脚手架工具」、「来自未来的脚手架」,不过这些未免显得太标题党了,华而不实我自己都很尴尬。最近我刚好做了个新世纪福音战士标题卡生成器,于是就随机将几个关键词组合在一起 —— 新世纪福音脚手架,意外地显得还不错。
为了不让你对标题不明所以,简单地说明了它的来历,以下才是正文。
脚手架
经常造轮子就会发现脚手架的重要性,这也是为什么 Yeoman 的发明者之一是 @sindresorhus 的原因。后者已经在 npm 上发布了超过 1000 个模块,很难后有来者了。
Yeoman 十分健壮,生态繁荣,然而要写一个 generator 的复杂度和写普通的代码几乎是差不多的,而我在能尽可能减少思考的时候就想减少思考,vue-cli 的思路很好地解决了我想减少思考的诉求,一个 generator 中间生成文件的过程有很多步骤是可以自动解决的。
vue-cli 虽然名字里有 vue 属性,但是作为任意类型项目的脚手架工具都是可以的,尽管运行 vue init react
这样的命令会显得有些奇怪。这也是为什么我做了 SAO 的原因,一个类似 vue-cli 的脚手架工具。在拥有 vue-cli 的功能的同时,它也能像 Yeoman 一样用 npm package 作为模板并支持测试。
举个例子,在运行 sao vue
的时候,如果 template-vue 这个 npm 模块没有全局安装,它会提示你安装,之后再使用模板根目录里的配置文件 sao.js
将同目录里的 template/
中的文件生成到 process.cwd()
即当前目录。如果不存在配置文件,那么只会当成一个普通的目录,简单地复制粘贴到当前目录。
📄 template-vue/sao.js:
module.exports = {
// 从用户获取一些信息
prompts: {
pwa: {
type: 'confirm',
message: 'Add Progressive Web App support',
default: true
}
},
// 如果要发布到 npm
// .gitignore 会自动被 npm 更名为 .npmignore
// 为了避免这种情况需要起个另外的名字
// 然后在生成的时候改名为 .gitignore
move: {
gitignore: '.gitignore'
},
// 只在用户确认了 pwa 选项的时候生成 pwa.js
filters: {
'pwa.js': 'pwa'
}
}
上面的这个配置文件满足了大部分脚手架的需求,即从用户获取信息 --> 根据此信息生成需要的文件。而且几乎与代码无关,这个配置文件完全是由数据组成的,只不过刚好是以 JS 对象的格式。
SAO 接收的第一个参数可以是:
- 本地模板路径,比如
./my-template
/path/to/my-template
。 - GitHub 项目缩略名,比如
egoist/template-vue
。 - npm 模块名(自动加上
template-
前缀),比如vue
将会使用 npm 上的template-vue
这个包。
而第二个参数是可选的,不存在时将会生成文件到工作区目录(当前目录),否则将会生成到指定的文件夹中。
测试脚手架
当脚手架变得复杂,你需要系统地测试以便让其在各种情况下都能生成正确的文件。对于一个脚手架,能从用户影响到它的变量只有 prompts
这个参数,也就是从用户获取的信息。而 SAO 的测试也主要是围绕这个来的,你可以模拟用户输入来检测生成结果。
📄 template-vue/test.js:
import test from 'ava'
import sao from 'sao'
test('generate pwa entry', async t => {
const template = process.cwd() // 模板根目录
const res = await sao.mockPrompt(template, {
// 模拟的 prompts 数据
// 默认使用 `prompts` 中的默认值
// 在上面的 `sao.js` 中 `pwa` 默认为 `true`
})
t.true(res.fileList.includes('pwa.js'))
})
test('ignore pwa entry', async t => {
const template = process.cwd() // 模板根目录
const res = await sao.mockPrompt(template, {
pwa: false
})
t.false(res.fileList.includes('pwa.js'))
})
这里的 res.fileList
是生成的文件列表,形如:
[
'.gitignore',
'pwa.js',
'src/index.js'
]
以及 res.files
,包含了生成文件的信息:
{
'.gitignore': {
contents: Buffer,
stats: {}, // fs.Stats,
path: '/absolute/path/to/this/file'
},
// ...
}
最后
分享几个我自己经常使用的模板:
- template-nm: 生成一个 npm 模块,我的所有模块都是用这个生成的。
- template-vue: 生成一个几乎无需配置的 Vue 项目,基于 Poi。
- awesome-sao: 相关 SAO 资源。
关于更多 SAO 的使用方法和配置文件参数,可以访问 sao.js.org :P 虽然本文标题是来源于新世纪福音战士,但 SAO 显然是来源于 Sword Art Online 的。
Please enable JavaScript to view the<a href="https://disqus.com/?ref_noscript" rel="nofollow">comments powered by Disqus.</a> 文章勘误可以直接到 源代码地址 修改或者 提交 ISSUE,感谢阅读!