博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
写一个属于你的前端脚手架工具
阅读量:5931 次
发布时间:2019-06-19

本文共 5045 字,大约阅读时间需要 16 分钟。

你可能用到过很多前端脚手架工具,有没有试想过到底如何写一个属于你的脚手架呢?

脚手架依赖工具

命令行工具

git仓库代码下载

命令行输出样式美化

命令行交互

命令行加载中效果

项目搭建

初始化项目

创建项目目录后执行npm init按照提示完成初始化项目。

安装依赖

安装上面我们提到过的这几个脚手架依赖工具,执行npm install chalk commander download-git-repo inquirer ora --save完成安装。

项目结构

项目初始化完成后,创建bin文件和commands文件。bin文件为可执行命令入口目录,commands则负责编写一些命令交互。

bin 目录下 react-cli 文件

#!/usr/bin/env nodeprocess.env.NODE_PATH = __dirname + '/../node_modules/'const { resolve } = require('path')const res = command => resolve(__dirname, '../commands/', command)const program = require('commander')program.version(require('../package').version )program.usage('')program.command('init')  .option('-f, --foo', 'enable some foo')  .description('Generate a new project')  .alias('i')  .action(() => {    require(res('init'))  })if(!program.args.length){  program.help()}

创建该react-cli.js为可执行命令入口文件,并且定义了一个'init'命令,执行命令后会去commands 目录下寻找对应的init.js文件

commands 目录下 init 文件

const {prompt} = require('inquirer')const program = require('commander')const chalk = require('chalk')const download = require('download-git-repo')const ora = require('ora')const fs = require('fs')const path = require('path')const option =  program.parse(process.argv).args[0]const defaultName = typeof option === 'string' ? option : 'react-project'const tplList = require(`${__dirname}/../templates`)const tplLists = Object.keys(tplList) || [];const question = [  {    type: 'input',    name: 'name',    message: 'Project name',    default: defaultName,    filter(val) {      return val.trim()    },    validate(val) {      const validate = (val.trim().split(" ")).length === 1      return validate || 'Project name is not allowed to have spaces ';    },    transformer(val) {      return val;    }  }, {    type: 'list',    name: 'template',    message: 'Project template',    choices: tplLists,    default: tplLists[0],    validate(val) {      return true;    },    transformer(val) {      return val;    }  }, {    type: 'input',    name: 'description',    message: 'Project description',    default: 'React project',    validate (val) {      return true;    },    transformer(val) {      return val;    }  }, {    type: 'input',    name: 'author',    message: 'Author',    default: 'project author',    validate (val) {      return true;    },    transformer(val) {      return val;    }  }]module.exports = prompt(question).then(({name, template, description, author}) => {  const projectName = name;  const templateName = template;  const gitPlace = tplList[templateName]['place'];  const gitBranch = tplList[templateName]['branch'];  const spinner = ora('Downloading please wait...');  spinner.start();  download(`${gitPlace}${gitBranch}`, `./${projectName}`, (err) => {    if (err) {      console.log(chalk.red(err))      process.exit()    }    fs.readFile(`./${projectName}/package.json`, 'utf8', function (err, data) {      if(err) {        spinner.stop();        console.error(err);        return;      }      const packageJson = JSON.parse(data);      packageJson.name = name;      packageJson.description = description;      packageJson.author = author;      var updatePackageJson = JSON.stringify(packageJson, null, 2);      fs.writeFile(`./${projectName}/package.json`, updatePackageJson, 'utf8', function (err) {        if(err) {          spinner.stop();          console.error(err);          return;        } else {          spinner.stop();          console.log(chalk.green('project init successfully!'))          console.log(`            ${chalk.bgWhite.black('   Run Application  ')}            ${chalk.yellow(`cd ${name}`)}            ${chalk.yellow('npm install')}            ${chalk.yellow('npm start')}          `);        }      });    });  })})

1. program.parse(process.argv) 可以解析执行init 时候传入的参数, 我们可以拿到这个参数做为项目创建的目录名,如果没有传入该参数则为其设置一个默认目录名称。

2. 命令行交互问答

  • question 数组为交互命令配置,数组中每一个对象都对应一个执行命令时候的一个问题
  • type为该提问的类型,name为该问题的名字,可以在后面通过name拿到该问题的用户输入答案
  • message为问题的提示
  • default则为用户没输入时的默认为其提供一个答案
  • validate方法可以校验用户输入的内容,返回true时校验通过,若不正确可以返回对应的字符串提示文案
  • transformer为用户输入问题答案后将对应的答案展示到问题位置,需要有返回值,返回到字符串为展示内容

3. 问答结束的回调

  • prompt方法中then里的参数是一个对象,可以由此拿到问题由name定义的用户输入内容。
  • 根据用户输入的内容,可以对应为其生成下载模版,这里使用download-git-repo工具来下载git仓库代码
  • download方法第一个参数为要下载代码仓库位置,如果为GitHub代码仓库只需要写用户名和项目名称即可,如'Hzy0913/react-template'即为下载该仓库master的代码,如果需要切换对应分支则在仓库地址后面加入对应分支名,如'Hzy0913/react-template#complete'
  • download方法第二个参数为生成下载文件的文件名,我将他保存在命令执行目录下,文件名使用用户输入的名字,如参数为'./projectName',即可在当前执行命令目录下生成对应的文件名。
  • ora模块可以为我们生成下载时候的旋转图标,ora方法传入的第一个参数为等待时候的提示文案并生成实例,在实例对象上调用start()方法开始出现旋转动画和提示,stop()方法停止。
  • 模版下载好以后需要为package.json文件生成用户自定义输入的内容,node的fs模块的readFile方法可以帮助我们获取生成文件的内容,writeFile则可以写入内容
  • 最后完成后可以在命令行面板上使用console方法给出一些提示内容,chalk 模块可以帮助我们美化输出内容。

文章中脚手架示例代码可以见

工具测试及发布

  • 在写的过程中免不了在我们本地进行测试,因为本身项目为node的工具,我们可以在项目目录下执行 node bin/react-cli运行。
  • 当然在发布以后肯定不能使用该命令,此时在发布前,添加backage.json中的bin对象,key为脚本执行的名字,value为执行目录,如"bin": {"build-react": "bin/react-cli"} ,即可在输入build-react的时候等同于执行 node bin/react-cli命令,在我们全局安装脚手架的时候,bin对象里面的内容即可变成全局可执行命令。
  • 发布npm包,npm包发布非常简单,注册npm账号后本地登录即可,在项目目录下执行npm publish即可发布,注意包名不能与现有的npm里的相同、每次发布新版本的包时需要修改package.json里的版本号,发布的包只有在24小时内可以删除。

最后推荐两个我写的脚手架工具

转载地址:http://dsutx.baihongyu.com/

你可能感兴趣的文章
Ubuntu16.04下编译android6.0源码
查看>>
MySql批量插入数据
查看>>
微信开发-点击链接自己主动加入关注
查看>>
The Relationship Between Layers and Views
查看>>
算法笔记之动态规划
查看>>
2801 LOL-盖伦的蹲草计划
查看>>
GridView数据绑定控件的模版列时设置显示的格式
查看>>
mac下配置adb
查看>>
php利用curl获取网页title内容
查看>>
Maven插件的使用
查看>>
mOOC 编绎原理
查看>>
SVN版本库修改URL路径或者IP地址
查看>>
2016年 成渝校招软件上机练习
查看>>
2014/7/24
查看>>
Codeforces Round #277 (Div. 2)---C. Palindrome Transformation (贪心)
查看>>
如何利用JS判断当前来路域名并跳转到指定页面
查看>>
HDU 2188-悼念512汶川大地震遇难同胞――选拔志愿者(巴什博奕)
查看>>
React Native开发技术
查看>>
“聊天剽窃手”--ptrace进程注入型病毒
查看>>
vue-cli笔记
查看>>