问题:
我们知道 vue-cli create-react-app 等都可以根据你输入的参数进行快速脚手架的搭建.
那问题来了, 我们怎么构建自己的脚手架呢?
分析与思路
- 我们可以确定这个命令基本上是一个全局命令(或者说就是一个命令行)
- 依赖于 npm (node) 进行执行与安装, 有进一步了解
shell的应该想到要有头标志 - 接收参数, 应该是
shell相关的东西 - 脚手架代码, 不管何种形式, 应该是有类似模板项目之类的文件存在. (这个可以从网站下载, 或者直接放在我们的
npm中进行拷贝) - 可能的一些其他处理, 比如
npm install自动安装, 自动执行等(我目前想到的)
执行
一个非常简单的 demo
-
初始化项目
# 创建自己的项目 mkdir my-cli && cd $_ ## 创建并进入文件夹 npm init -y ## 快速新建自己的 npm 项目 -
模仿~, 看一看 vue-cli
# 我们去 /usr/local/bin 文件夹下 ll vue ## 如果 ll 不行的话, 尝试执行 `ls -alF` 吧 # 发现类似的 vue -> ../lib/node_modules/@vue/cli/bin/vue.js #所以这个可执行文件一个是一个 js 文件 # 我们进去看一下 # vue 文件内容 #!/usr/bin/env node // Check node version before requiring/doing anything else // The user may be on a very old node version const { chalk, semver } = require('@vue/cli-shared-utils') const requiredVersion = require('../package.json').engines.node const leven = require('leven') ... -
创建自己的 通过以上内容, 我们大体得知就是依赖本地的 node 环境去执行这个 js 文件而已. node 是一个服务器语言, 可以操作文件系统, 我们大体知道了后. 尝试创建一下自己
我尝试复制 模板文件内容 到当前的文件夹
新建一个
文件, 名字叫my-cli新建一个文件夹, 名字template目录结构如下
-template |- index.js -my-climy-cli 文件的内容
#!/usr/bin/env node console.log('我自己的脚手架项目')复制功能: (我们搜索查一下, 我采用执行 linux 的命令, 搜索一大堆, 比如 node复制文件 )
var child_process = require('child_process'); function copyDir(src, dist) { child_process.spawn('cp', ['-r', src, dist]); } copyDir('./template', './project'); -
试着执行一下 因为上边用到了
child_process包, 所以我们安装一下npm install child_process -S然后执行以下
# 可能需要弄一个全局链接, 我们这里先不做, 执行执行一下 ./my-cli zsh: permission denied: ./my-cli #提示这个错误, 增加一下执行权限 # 增加一下执行权限 chmod a+x ./my-cli # 继续执行 ./my-cli执行成功的话, 就会出现一个根据模板文件夹复制的 projet 文件夹了
进一步
增加接收参数
需要用到的包为
commander, 我怎么知道的呢, 搜索一下就可以 ^_^commander的 github地址看到 说明文档中介绍的, 我们直接按照 example 中的进行处理
// 我的稍微修改的版本 const { Command } = require('commander'); const program = new Command(); program.version('0.0.1') //声明一下版本, 通过 -V 来获取 program .command('create <name>') .description('create your project') .action((name) => { //这里处理你要的东西 console.log('build', name); });一些基本功能, 我们就暂时列2个
-
打印脚手架的版本 上边的直接进行执行
./my-cli -V即可 -
接收包的名字 根据 name 进行处理, 我们可以在我们的模板中定义一个名字用于替换 我新建了一个特殊符号
<%=name>进行替换console.log('我是模板文件的具体内容, 我的名字是 <%=name>')// 主要是用 node 中的 file 包进行数据处理 // 需要安装 file 和 path 包 function replaceFileContent(filePath, srcContent, targetContent) { fs.readFile(path.resolve(filePath), 'utf8', function (err, data) { if (err) { return console.log(err); } var result = data.replace(new RegExp(srcContent, 'g'), targetContent); fs.writeFile(path.resolve(filePath), result, 'utf8', function (err) { if (err) return console.log(err); }); }); }
-
代码与思考
整体的思路其实并不是很难, 主要就是文件的处理与替换, 主要包含一些脚本的知识.
代码位置: my-cli