php脚手架,从零开始搭建自己的前端脚手架(一)

前言

日常开发中,我们都只专注在业务上的开发,拿起一套开箱即用的模板项目就直接开搞了,不知道大家有没有思考过,平时我们使用的脚手架里面到底做了什么,并且如果是自己来搭一套脚手架,应该怎么去搭呢?

在本博客中,将记录作者搭建脚手架的过程,整体将分为两个部分,第一部分是cli的搭建,第二部分是模板项目的搭建;

cli的搭建

在搭建脚手架cli之前,我们首先思考一下,一个cli,需要什么能力呢?答案是初始化能力,那么初始化的功能需要怎样去实现呢,这里,我们先梳理一下思路。

思路

我们在使用其他cli时,会发现,它们有问询的功能,比如询问项目名称,项目描述等;然后还可以选择模板项目将要使用什么css预处理器等的问题;所以,cli首先就要具备问询功能,用以获取定制化信息;

问询结束后,我们的cli会获得即将创建的项目的基本信息,接下来我们就需要以一个模板项目作为模板去创建,模板项目将会在第二部分讲解,这里一笔带过~;OK,既然有了模板项目,cli就需要下载这个项目,然后复制这个项目,同时将前面问询所得的定制化信息写入项目配置中,所以cli还需要有下载和复制,写入模板功能;

到此,一个模板项目基本已经创建成功了,那后面我们还希望脚手架可以帮忙进行git初始化以及安装依赖的功能,所以最终,还需要添加git初始化和安装依赖的功能;

总结一下,实现一个cli的初始化功能我们需要有如下能力:

问询 ==> 下载模板 ==> 复制,写入模板 ==> git初始化 ==> 安装依赖

准备

好了,为了实现上述思路,cli将会引入如下依赖去实现对应的功能:

const program = require('commander'); // commander负责读取命令

const inquirer = require('inquirer'); // inquirer负责问询

const download = require('download-git-repo'); // download-git-repo负责下载对应模板项目的git仓库

const fse = require('fs-extra'); // fs-extra负责文件的复制

const memFs = require('mem-fs');

const editor = require('mem-fs-editor'); // mem-fs-editor负责模板的复制以及嵌入模板字符串,它需要依赖mem-fs

const { exec } = require('child_process'); // child_process负责执行命令行

当然除了上述必须的依赖外,为了更好的交互体验,还引入了如下依赖:

const chalk = require('chalk'); // 改变命令行输出样式

const ora = require('ora'); // 一个优雅地命令行交互spinner

至此,准备的工作已经完毕,下面,就开始一步步来编写cli了

cli的编写

万事开头难,有了思路后,实现思路才是真正的开始,下面将介绍如何组织cli项目

项目组织

首先看一下,工程的组织

├── bin

| ├── begin

| ├── begin-init

├── src

| ├── constants.js

| ├── project.js

| └── utils.js

├── .gitignore

├── .npmrc

├── README.md

└── package.json

第一步,解析命令

在bin/begin中引入commander,并且声明init命令,commander会在同级目录中寻找begin-init文件

const program = require('commander');

program

.usage(' [options]')

.command('init [name]', 'init a project')

.parse(process.argv);

第二步,问询

有了第一步的解析后,我们可以在begin-init文件中编写创建逻辑,这里,我们再抽象project文件到src目录底下,以便更好地分离职责,bin文件只负责解析命令就好啦~

下面就看看project文件中,如何实现问询

inquirer.prompt([{

type: 'input',

name: 'projectName',

message: '请输入项目名:',

validate(input) {

if (!input) {

return '项目名不能为空';

}

if (fse.existsSync(input)) {

return '当前目录已存在同名项目,请更换项目名';

}

return true;

}

}]);

inquirer提供prompt函数来实现问询,其参数为数组,问询顺序将按照数组的顺序来进行;

第三步,下载仓库

在问询结束后,我们基本知道需要创建的项目的名称、描述等信息了,下一步,就是下载仓库了,下面我们来看看核心代码:

const downloadPath = path.join(projectPath, '__download__');

download(TEMPLATE_GIT_REPO, downloadPath, { clone: true }, (err) => {

// 拷贝

// 此处省略若干代码

// 拷贝完成后删除临时文件

fse.remove(downloadPath);

}

这里需要注意的是,模板工程所在的仓库,即TEMPLATE_GIT_REPO,最好是public的

第四步,复制文件,将信息写入模板

下载仓库只是把模板工程存放在一个临时文件夹内,真正的工程文件需要等信息写入模板后再生成;

这里需要注意的是,模板写入时遵循ejs规范

const memFs = require('mem-fs');

const editor = require('mem-fs-editor');

// 这里需要mem-fs进行内存优化

const store = memFs.create();

this.memFsEditor = editor.create(store);

// 这里source表示源文件,dest表示目标文件,data表示需要写入的数据

this.memFsEditor.copyTpl(

source,

dest,

data

);

在调用copyTpl时,data字段中的key-value将被写入到模板中,举个栗子:

// 模板文件中,字段是这样的

{

name: ""

}

// data就要这样去写

{

projectName: 'this is your project name'

}

第五步,进行git init和npm install

这两步的核心都是使用nodejs提供的child_process中exec方法去执行命令来实现,exec能帮助我们在命令行中执行shell命令,exec函数有对应的回调方法来让我们判断命令执行是否成功,核心代码如下:

exec('npm install', (error, stdout, stderr) => {

if (error) {

// 出错了

} else {

// 成功了

}

})

是不是很简单呢,想了解更多的操作可以搜索官方文档查看哈,这里就不详解了。

调试和发布

到这里,我们的cli已经实现的差不多了,这里我们总结一下如何测试和发布吧

npm link // 本地调试

npm publish // 发布

通过npm link命令,即可以在命令行工具测试你的cli了,注意在package.json的bin字段中定义好入口命令和文件

// package.json

{

"bin": {

"begin": "bin/begin"

}

}

小结

OK,文章主要总结了编写一个脚手架中init功能的思路以及一些实现的方法,具体一些细节仍有优化的空间,欢迎大家讨论!

文章的具体代码可以参考我的仓库begin-cli

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值