如果你是个前端工程师,你对脚手架就不会陌生。React、Vue、Angular各大框架都不止一个脚手架,现在之所以几乎成为一个前端框架的标配,那是因为各框架无不是依赖Node.js进行开发的,需要集成webpack、rollup、vite之类工具才能开发或生产。脚手架的出现极大地节约了你的配置成本,那对于业务层面而言是没有意义的浪费。
Node.js能做到的事情,Deno显然也能做到。比如你的团队将使用Deno进行后端开发,那么大概率需要一个自己的脚手架,免于让每个成员复制粘贴模板代码,再一一修改配置的苦恼。
下文将教你怎么开发一个脚手架。
准备
首先,你需要规划一下,我们的脚手架需要哪些步骤。
就像把大象装进冰箱需要3步一样,脚手架也不例外:
- 下载模板代码
- 解压模板代码
- 修改模板代码
所以你的前提是得有个地址存放模板代码,并可以让外界下载到。github提供了这个能力,找到你的工程,在选择下载那里,把链接地址复制出来即可。
路径大概是这样的: github.com/用户名/工程名/arc…
也可以发布一个tag,到这里找地址:
地址通常是:github.com/用户名/工程名/arc…
下载
Deno下载远程文件很简单,直接用fetch API请求后再写入本地文件就可以了:
export async function download(url: string, fileName: string) {
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/zip",
},
});
const buffer = await response.arrayBuffer();
return Deno.writeFile(fileName, new Uint8Array(buffer));
}
解压
解压我们在deno.land上面找一个星多点的包:deno.land/x/zip@v1.2.…。 用法很简单:
import { decompress } from "https://deno.land/x/zip@v1.2.3/mod.ts";
console.log(await decompress("myfile.zip")); //=> ./
解压后,不要忘了删除这个zip包:
await Deno.remove(zipName);
修改
模板代码当然是有些地方要修改的,最常见的是修改工程名,也就是把模板工程的名称修改为自定义的名称。 这个自定义名称从哪儿来呢?一般是从命令行参数中获取,比如Deno.args[0]。比如我们最终的cli命令是deno_cli,调用时是deno_cli aa,那么Deno.args[0]就是aa。
如果参数比较多,也可以使用deno.land/x/ask,它是问答式的交互页面:
修改工程名是非常简单的,Deno的rename API就可以:
await Deno.rename(原名称, 新名称);
如果你的模板代码的README.md文件里也带了模板名称,那么你可能还要把它替换:
import { join } from "https://deno.land/std@0.120.0/path/mod.ts";
async function writeReadme(name: string) {
const realPath = join(name, "README.md");
const doc = await Deno.readTextFile(realPath).catch((_) => null);
if (!doc) {
console.warn(`没有找到【${realPath}】`);
return;
}
const newDoc = doc.replaceAll(templateName, name);
await Deno.writeTextFile(realPath, newDoc);
}
再有其它文件的替换可自行实现。
最终这个文件的核心代码为:
async function main() {
let name = Deno.args[0];
if (!name) {
const ask = new Ask({
prefix: ">",
});
// deno-lint-ignore no-explicit-any
const answers: any = await ask.prompt([
{
name: "name",
type: "input",
message: "projectName:",
},
]);
name = (answers as Params).name;
}
await download(url, zipName);
await decompress(zipName, "./");
await Deno.rename(projectName + "-" + branchName, name);
await Deno.remove(zipName);
await writeReadme(name);
console.log(`init project ${projectName} end`);
}
完整样例可参见这里。
验证
假设你的文件名称为project.ts,那么可以本地运行验证:
# 可以把参数加上
deno run --allow-write --allow-read --allow-net --allow-run --unstable ./project.ts
看本地目录是不是下载了一个文件夹,名称和内容是不是符合你的预期? 如果没有问题,再安装后验证:
# 全局安装
deno install --allow-write --allow-read --allow-net --allow-run --unstable -n deno_cli -f ./project.ts
# 使用
deno_cli
# 或者
deno_cli my_app
如果都没有问题,就可以把你的脚手架发布到deno.land上,以后在任何一台安装了Deno的机器上都可以一行命令安装使用你的脚手架了。
deno install --allow-write --allow-read --allow-net --allow-run --unstable -n deno_cli -f https://deno.land/x/你的命名/project.ts
怎么发布请见上篇手把手教你发布一个Deno模块。