搭建前端脚手架

it2026-04-19  2

1.什么是脚手架 

 

脚手架用于快速生成新项目的目录模板,并集成一系列体系化工具的安装,无需自己从零开始一步步配置,减少copy操作,有效提升开发体验和效率,尽管这些脚手架非常优秀,但是未必是符合我们的实际应用的,所以我们可以定制一个属于自己的脚手架,来提升自己的开发效率。平时我们在开发React-Native的时候就会使用到raect-native-cli这个脚手架为我们创建项目

 

脚手架的作用 

 

减少重复性的工作,不需要复制其他项目再删除无关代码,或者从零创建一个项目和文件。 可以根据交互动态生成项目结构和配置文件。 多人协作更为方便,不需要把文件传来传去。 

 

目前比较主流的脚手架 

 

React-Native脚手架 react-native-cli React.js脚手架 cract-react-app Vue.js脚手架 vue-cli Webpack脚手架 webpack-cli 

 

2.实现思路 

 

项目模板放在github上 用户通过命令交互的方式下载不同的模版 经过模版引擎渲染定制项目模版 模版变动,只需更新模版即可,不需要用户更新脚手架 

 

设计模块知识点 

 

commander.js命令行工具 download-git-repo: 用来下载远程模板 inquirer: 交互式命令行工具 ora: 显示loading动画 chalk: 修改控制台输出内容样式 log-symbols: 显示出 √ 或 × 等的图标 

 

3.项目初始化 

 

这里假设我们的脚手架名字是qiyitest-cli,以下都用这个名字。我们在命令行使用脚手架命令为qiyitest-cli

1.创建一个空项目qiyitest-cli 

 

mkdir qiyitest-cli cd qiyitest-cli npm init -y 

 

2.安装相关的依赖 

 

npm install babel-cli babel-env chalk commander download-git-repo ini inquirer log-symbols ora 

 

3. 新建一个bin文件夹里面添加 index.js

行首加入一行 #!/usr/bin/env node 指定当前脚本由node.js进行解析 

 

#! /usr/bin/env node console.log('hello demo') 

 

4.配置package.js中的bin字段 (node.js 内置了对命令行操作的支持,package.json 中的 bin 字段可以定义命令名和关联的执行文件)

 

{   "name": "qiyitest-cli",   "version": "1.0.0",   "description": "",   "main": "index.js",   "bin": {     "qiyitest": "bin/index.js"   },   "scripts": {     "test": "echo \"Error: no test specified\" && exit 1"   },   "keywords": [],   "author": "",   "license": "ISC",   "dependencies": {     "babel-cli": "^6.26.0",     "babel-env": "^2.4.1",     "chalk": "^4.0.0",     "commander": "^5.1.0",     "download-git-repo": "^3.0.2",     "ini": "^1.3.5",     "inquirer": "^7.1.0",     "log-symbols": "^3.0.0",     "ora": "^4.0.4"   } }

 

这样当我们发布上npm,别人下载下来后,就可以直接使用qiyitest命令了。

 

5.目录结构

├── bin │   └── index.js        //可执行文件 ├── .babelrc             //babel配置文件 ├── package.json ├── README.md

 

6.执行npm link链接命令到全局(npm unlin移除命令) 

执行bin中配置的命令测试。 

例如在终端输入: 

 

npm link qiyitest

输出 

hello demo 

 

4.处理命令行 

 

使用commander处理控制台命令(github查看如何使用), commander提供解析命令行

在index.js文件下面添加 

 

#! /usr/bin/env node // 使用Node开发命令行工具所执行JavaScript脚本必须在顶部加入 #! /usr/bin/env node const { program } = require('commander'); program.version('1.0.0') // -v 或者 --versions输出版本号 program   .command('init <template> <project>')   .description('初始化项目模版')   .action((templateName, projectName) => {     console.log(templateName, projectName)   }) program   .command('list')   .description('查看所有可用的模版')   .action(() => {     console.log(       `template-A A模板       template-B B模板       template-C C模板`           )   }) program.parse(process.argv);

 

在控制台输入

qiyitest -V(或者qiyitest --version)

qiyitest -h(或者 qiyitest --help)

qiyitest init template-A A

qiyitest list 

输出结果如下:

 

5. 准备模版 

 

在github上面建立需要使用到的模版,这里分别建立了template-A template-B template-C三个模版(https://github.com/dongtaotao/-template-C) 

 

添加下载模版 

 

当输入qiyitest init template-A a-name时候下载基于template-A模版进行初始化

当输入qiyitest init template-B b-name时候下载基于template-B模版进行初始化

当输入qiyitest init template-C c-name时候下载基于template-A模版进行初始化 

注:项目名可以随便取 

 

模版下载地址 

 

const templates = {   'template-A' : {     url: 'https://github.com/dongtaotao/template-A',     downloadUrl: 'http://github.com:dongtaotao/template-A#master',     description: 'A模版'   },   'template-B' : {     url: 'https://github.com/dongtaotao/template-B',     downloadUrl: 'http://github.com:dongtaotao/template-B#master',     description: 'B模版'   },   'template-C' : {     url: 'https://github.com/dongtaotao/template-C',     downloadUrl: 'http://github.com:dongtaotao/template-C#master',     description: 'C模版'   }, };

 

6 根据init指定的模版名和项目名下载生成到本地 

 

download-git-repo 支持从 Github、Gitlab 下载远程仓库到本地。 

 

const download = require('download-git-repo'); program   .command('init <template> <project>')   .description('初始化项目模版')   .action((templateName, projectName) => {          const {downloadUrl} = templates[templateName];     //download      // 第一个参数: 仓库地址     // 第二个参数: 下载路径     download(downloadUrl, projectName, {clone: true}, (err) => {       if(err) {         console.log('下载失败')       } else {         console.log('下载成功')       }     })   })

 

在控制台输入qiyitest init template-A ademo

这时候就会下载对应的template-A模版,同时在桌面上多了一个ademo的文件。

文件ademo里面的内容就是template-A模版的内容 

 

 

download函数

 

第一个参数就是仓库地址端口号后面的'/'在参数中要改成':'master 代表分之名

              不同的模版可以放在不同的分枝中,更改分之便可以实现下载不同的模版文件了

 

第二个参数是路径

 

上面我们直接在当前路径下创建一个ademo的文件存放模版。

 

 

7 命令行交互 

 

命令行交互功能可以在用户执行init命令之后,向用户提出问题,接收用户输入并作出相应的处理,这里使用inquirer.js来实现

安装:

npm install inquirer

 

const inquirer = require('inquirer'); inquirer.prompt([ {   type: 'inpute',   name: 'name',   message: '请输入项目名称' }]).then((answers) => {   console.log(answers) })

 

问题就放在prompt()中问题的类型为input就是输入类型name就是作为答案对象中的keymessage就是问题了用户输入的答案就在answers中

 

8.模板引擎

 

我们通过询问交互后,肯定内部做了些改变。这里我们可以把package.json的作者和描述简单改了可以使用handlebars,模板语法简单

 

在模版中准备package.json文件

{   "name": "{{name}}",   "version": "1.0.0",   "description": "{{description}}",   "main": "index.js",   "scripts": {     "test": "echo \"Error: no test specified\" && exit 1"   },   "keywords": [],   "author": "{{author}}",   "license": "ISC",   "dependencies": {       } }

 

并在下载模版完成只有将用户输入的答案渲染到package.json中

 

const { program } = require('commander'); const download = require('download-git-repo'); const handlebars = require('handlebars'); const inquirer = require('inquirer'); const ora = require('ora'); const logSymbols = require('log-symbols'); const chalk = require('chalk'); const fs = require('fs'); const templates = {   'template-A' : {     url: 'https://github.com/dongtaotao/template-A',     downloadUrl: 'http://github.com:dongtaotao/template-A#master',     description: 'A模版'   },   'template-B' : {     url: 'https://github.com/dongtaotao/template-B',     downloadUrl: 'http://github.com:dongtaotao/template-B#master',     description: 'B模版'   },   'template-C' : {     url: 'https://github.com/dongtaotao/template-C',     downloadUrl: 'http://github.com:dongtaotao/template-C#master',     description: 'C模版'   }, }; //qiyitest init template-A a-name基于template-A模版进行初始化 //qiyitest init template-B a-name基于template-A模版进行初始化 program.version('1.0.0') // -v 或者 --versions输出版本号 program   .command('init <template> <project>')   .description('初始化项目模版')   .action((templateName, projectName) => {     // 下载之前做loading提示     const spinner = ora('正在下载模版...').start()          const {downloadUrl} = templates[templateName];     //download     // 第一个参数: 仓库地址     // 第二个参数: 下载路径     download(downloadUrl, projectName, {clone: true}, (err) => {       if(err) {         spinner.fail();         console.log(logSymbols.error, chalk.red(err))         return;       }       spinner.succeed(); // 下载成功提示       // 把项目下的package.json文件读取出来       // 使用向导的方式采集用户输入的数据解析导       // 使用模板引擎把用户输入的数据解析到package.json 文件中       // 解析完毕,把解析之后的结果重新写入package.json wenjianzhong       inquirer.prompt([         {           type: 'inpute',           name: 'name',           message: '请输入项目名称'         },         {           type: 'inpute',           name: 'description',           message: '请输入项目简介'         },         {           type: 'inpute',           name: 'author',           message: '请输入作者名称'         }     ]).then((answers) => {       const packagePath = `${projectName}/package.json`       const packageContent = fs.readFileSync(packagePath, 'utf8')       const packageResult = handlebars.compile(packageContent)(answers);       fs.writeFileSync(packagePath, packageResult)       console.log(chalk.yellow('初始化模版成功'))     })     })   }) program.parse(process.argv);

 

这里使用了node.js的文件模块fs, 将handlebars渲染后的模版重新写入到文件中

 

这时候打开demob 文件夹下面的package.json,可以看到里面的name,description,author变成我们输入的

 

 

9.视觉美化

 

在用户输入答案之后,开始下载模版,这时候使用ora来提示用户正在下载中。

 

安装:

npm install ora

 

使用

const ora = require('ora'); // 开始下载 const spinner = ora('正在下载模版...'); spinner.start(); // 下载失败 spinner.fail(); // 下载成功 spinner.succeed();

 

也可以使用chalk和logSymbols增加文本样式

chalk

 

这是用来修改控制台输出内容样式的,比如颜色啊,具体用法如下:

const chalk = require('chalk'); console.log(chalk.green('success')); console.log(chalk.red('error'));

然后通过chalk来为打印信息加上样式,比如成功信息为绿色,失败信息为红色,这样子让用户更容易分辨,同事也让终端的显示更加好看。

这时候在控制台输入命令可以看出带了图标和颜色

 

 

10.npm 发包

 

打开npmjs.com官网注册一个npm账号在npm检索是否有重名的包将package.json中的name修改发不到npm上的包名打开控制台,执行npm login,在控制台登录npm登录成功后,在项目下执行npm publish发布发布成功,就可以在本地安装测试了 npm install -g qiyitest-cli

 

这时候就可以使用qiyitest命令了,至此一个简单的脚手架搭建过程结束了

 

项目地址

源码

最新回复(0)