青训营Pro自定义脚手架从1到∞ - 自动化思维搭建koa脚手架
Posted YK菌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了青训营Pro自定义脚手架从1到∞ - 自动化思维搭建koa脚手架相关的知识,希望对你有一定的参考价值。
嗨!~ 大家好,我是YK菌 🐷 ,一个微系前端 ✨,爱思考,爱总结,爱记录,爱分享 🏹,欢迎关注我呀 😘 ~ [微信公众号:
ykyk2012
]
文章目录
本文相关代码:youth_camp_ykjun: 青训营&开课吧 实战课程代码仓库 - Gitee.com
一、前言
今天来复习&总结青训营实训营第二天的内容,在上次课程中我们从0到1创建了一个vue的脚手架,今天我们跟着崔老师@阿崔cxr使用自动化思维来搭建一个koa脚手架
PS:本博文是崔老师 前端工程化 课程的第一部分:初始化,后面我会尽力更新完~ 包括:webpack原理、rollup原理、实现mini-vite、自动测试等
二、分析vue-cli
- 使用指令创建一个项目
vue create hello-world
- 提供选择 单选/多选
- 安装依赖
总结一下步骤就是:① 输入指令 ② 选择配置 ③ 创建文件 ④ 安装依赖
那么我们就按照这个步骤来写我们的脚手架
三、起步
接下来我们就要自己实现一个脚手架,有了上节课的基础知识,今天的内容可以让你更上一层楼。
首先创建我们脚手架的项目目录 learn-koa-setup
然后初始化项目npm init -y
将项目模块化规范改成ESM,即在package.json中添加"type": "module",
创建好index.js
,在这里编写脚手架要做的事情
import fs from "fs";
// 核心:自动化思维【先想手动创建一个项目的基本步骤】
// 1. 创建了文件夹(项目名)
fs.mkdirSync("ykyk");
// 2. 创建了index.js
fs.writeFileSync("./ykyk/index.js", "index");
// 3. 创建了package.json
fs.writeFileSync("./ykyk/package.json", "package");
// 4. 安装依赖
// TODO package -> npm
我们测试一下
node index.js
文件夹和文件已经创建,也填充了基本内容
我们每次执行这个命令,都要手动删除ykyk这个文件夹,然后再新建,比较麻烦,我们用指令让他自动
执行,在package.json中添加指令(我这里使用的是windows删除文件夹的指令)
"scripts":
"test": "rd /s ykyk && node index.js"
,
此时就可以直接使用 npm test
命令来完成删除文件夹,然后执行index.js文件了!
四、完善
上面的步骤虽然很easy,但是已经是大体的方向已经明确了,接下来要做的就是不断完善这里面的具体细节。
注意:我们这里使用
小步骤
的方式写代码。一点一点的完善,一次只完成一个很小的功能,然后进行测试。功能没问题再往下写,这样保证我们在编写代码的时候及时知道哪里出了错,及时修正。
我们这里用到了很多根路径,我们将他封装起来
function getRootPath()
return "./ykyk";
就可以这样使用了
// 1. 创建了文件夹(项目名)
fs.mkdirSync(getRootPath());
// 2. 创建了index.js
fs.writeFileSync(getRootPath()+"/index.js", "index");
// 3. 创建了package.json
fs.writeFileSync(getRootPath()+"/package.json", "package");
1. 生成index.js内容
① 生成模板
我们创建一个模板 indexTemplate.js
先将模板内容写死,然后导出创建模板的函数
export function createIndexTemplate()
return `
const Koa = require("koa");
const app = new Koa();
app.listen(8000, () =>
console.log("open server localhost:8000");
);
`;
在index.js中引入,并使用
import createIndexTemplate from "./indexTemplate.js";
fs.writeFileSync(getRootPath() + "/index.js", createIndexTemplate());
最后执行指令,查看效果
② 动态生成模板
接下来我们就要让模板的内容可以根据不同的设置,来呈现不同的代码
这里我们用到一个第三方库 ejs 高效的嵌入式 JavaScript 模板引擎
安装 npm i ejs
创建文件 template/index.ejs
const Koa = require("koa");
const app = new Koa();
app.listen(8000, () =>
console.log("open server localhost:8000");
);
此时在 indexTemplate.js 就应该这样引入和使用
import ejs from "ejs";
import fs from "fs";
export function createIndexTemplate()
// 读取ejs模板
const template = fs.readFileSync("./template/index.ejs", "utf-8");
// 交给ejs来渲染
const code = ejs.render(template);
// 返回渲染后的模板
return code;
此时再测试一下,发现没有问题,然后就要进行条件渲染了
修改index.ejs文件【根据文档中给出的语法】
const Koa = require("koa");
<% if (router) %>
const Router = require("koa-router");
<% %>
const app = new Koa();
<% if (router) %>
const router = new Router();
router.get("/", (ctx) =>
ctx.body = "hello YK菌";
);
app.use(router.routes());
<% %>
app.listen(8000, () =>
console.log("open server localhost:8000");
);
通过给渲染函数传递参数来决定是否渲染响应的内容
const code = ejs.render(template,
router: true,
);
③ 模拟用户输入的数据
其实这个参数应该是由用户来选择的,但是我们是小步骤
的方式编写代码,所以我们先将用户的输入写死。
// 先把配置中间件数据写死
const inputConfig =
middleware:
router: true,
,
;
// 将配置文件传入创建模板函数
fs.writeFileSync(getRootPath() + "/index.js", createIndexTemplate(inputConfig));
在indexTemplate.js
中这样使用即可
export function createIndexTemplate(inputConfig)
// 读取ejs模板
const template = fs.readFileSync("./template/index.ejs", "utf-8");
// 交给ejs来渲染
const code = ejs.render(template,
router: inputConfig.middleware.router,
);
// 返回渲染后的模板
return code;
④ 拓展完整选项
我们把四个选项补齐
// 程序的input
const inputConfig =
middleware:
router: true,
static: true,
views: true,
body: true
,
;
indexTemplate.js
import ejs from "ejs";
import fs from "fs";
export function createIndexTemplate(inputConfig)
// 读取ejs模板
const template = fs.readFileSync("./template/index.ejs", "utf-8");
// 交给ejs来渲染
const code = ejs.render(template,
router: inputConfig.middleware.router,
static: inputConfig.middleware.static,
views: inputConfig.middleware.views,
body: inputConfig.middleware.body
);
// 返回渲染后的模板
return code;
template/index.ejs
const Koa = require("koa");
<% if (router) %>
const Router = require("koa-router");
<% %>
<% if (static) %>
const serve = require("koa-static");
<% %>
<% if (views) %>
const views = require("koa-views");
<% %>
<% if (body) %>
const body = require("koa-body");
<% %>
const app = new Koa();
<% if (router) %>
const router = new Router();
router.get("/", (ctx) =>
ctx.body = "hello YK菌";
);
app.use(router.routes());
<% %>
<% if (static) %>
app.use(serve(__dirname + "/static"));
<% %>
<% if (views) %>
app.use(
views(__dirname + "/views",
extension: "pug",
)
);
<% %>
<% if (body) %>
app.use(
body(
multipart: true,
)
);
<% %>
app.listen(8000, () =>
console.log("open server localhost:8000");
);
测试我们的代码功能 npm test
此时创建出的ykyk项目中的index.js就是根据选项生成的完整的代码了
显示 ykyk/index.js 中的内容符合我们的预期
const Koa = require("koa");
const Router = require("koa-router");
const serve = require("koa-static");
const views = require("koa-views");
const body = require("koa-body");
const app = new Koa();
const router = new Router();
router.get("/", (ctx) =>
ctx.body = "hello YK菌";
);
app.use(router.routes());
app.use(serve(__dirname + "/static"));
app.use(
views(__dirname + "/views",
extension: "pug",
)
);
app.use(
body(
multipart: true,
)
);
app.listen(8000, () =>
console.log("open server localhost:8000");
);
2. 生成package.json内容
简单使用ejs生成了index.js模板,我们再基于数据生成package.json,和上面的步骤基本一样
① 生成模板
首先创建 packageTemplate.js
import ejs from "ejs";
import fs from "fs";
export function createPackageTemplate(inputConfig)
// 读取ejs模板
const template = fs.readFileSync("./template/package.ejs", "utf-8");
// 交给ejs来渲染
const code = ejs.render(template,
router: inputConfig.middleware.router,
static: inputConfig.middleware.static,
views: inputConfig.middleware.views,
body: inputConfig.middleware.body,
);
// 返回渲染后的模板
return code;
然后创建一个模板 template/package.ejs
"name": "koa-setup-ykyk",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts":
"test": "echo \\"Error: no test specified\\" && exit 1",
"build": "rm -rf hei && node index.js"
,
"keywords": [],
"author": "",
"license": "ISC",
"dependencies":
"koa": "^2.13.1"
<% if (router) %>
,"koa-router": "^10.1.1"
<% %>
<% if (static) %>
,"koa-static": "^5.0.0"
<% %>
<% if (views) %>
,"koa-views": "^7.0.1"
,"pug": "^3.0.2"
<% %>
<% if (body) %>
,"koa-body": "^4.1.3"
<% %>
这里有一个小技巧,就是把可选包的前面加上逗号,这样就可以保证这里的格式没有问题了~
② 获取项目名称
模拟用户输入packageName
// 程序的input
const inputConfig =
packageName: 'yk_demo',
middleware:
router: true,
...
,
;
在这里引入即可
...
// 交给ejs来渲染
const code = ejs.render(template,
packageName: inputConfig.packageName,
...
);
...
最后根据ejs的语法在template/package.ejd中这样写就可以
"name": "<%= packageName %>",
最后我们测试一下npm test
,可以看到生成的package.json符合我们的预期
"name": "yk_demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts":
"test": "echo \\"Error: no test specified\\" && exit 1",
"build": "rm -rf hei && node index.js"
,
"keywords": [],
"author": "",
"license": "ISC",
"dependencies":
"koa": "^2.13.1",
"koa-router": "^10.1.1",
"koa-static": "^5.0.0",
"koa-views": "^7.0.1",
"pug": "^3.0.2",
"koa-body": "^4.1.3"
相同的写法,我们可以把index.js中的端口号也设置成可供用户自己选择的模式,具体的可以看我代码仓库中的代码
youth_camp_ykjun: 青训营&开课吧 实战课程代码仓库 - Gitee.com
3. 获取用户输入
接下来我们要做的就是获取真实的用户输入,这里我们使用 inquirer
这个库(A collection of common interactive command line user interfaces.) 网址:inquirer - npm (npmjs.com)
首先安装这个库 npm i inquirer
创建question/index.js获取用户输入
import inquirer from "inquirer";
export function question()
return inquirer.prompt([
// 获取用户输入的项目名称
type: "input", name: "packageName", message: "set package name" ,
// 获取用户输入的端口号,默认值为8080
type: "number",
name: "port",
message: "set port number",
default: () => 8080,
,
// 多选,获取用户选择的中间件
type: "checkbox",
name: "middleware",
choices: [
name: "koaRouter" ,
name: "koaStatic" ,
name: "koaViews" ,
name: "koaBody" ,
],
,
]);
然后将模拟的数据替换成真实用户输入的数据
import question from "./question/index.js";
const answer = await question();
// 程序的input
const inputConfig =
packageName: answer.packageName,
port: answer.port,
middleware:
router: answer.middleware.indexOf("koaRouter") !== -1,
static: answer.middleware.indexOf("koaStatic") !== -1,
views: answer.middleware.indexOf("koaViews") !== -以上是关于青训营Pro自定义脚手架从1到∞ - 自动化思维搭建koa脚手架的主要内容,如果未能解决你的问题,请参考以下文章
青训营Pro️从0到1实现一个自己的前端约定路由项目脚手架️ 工具~
青训营Pro️从0到1实现一个自己的前端约定路由项目脚手架️ 工具~
青训营Pro 前端框架设计理念 - Vue3动机 - 手写实现mini-vue