[脚手架搭建]如何搭一个本身的脚手架

因为react的脚手架配置项过多,致使项目生成很慢,每次都要等待好久。本身搭建环境的话,每次都进行搭建又有不少重复性的工做。javascript

因此笔者就打算本身搭建一个脚手架name:simple-create-react,简化了打包环境配置并提供可选配置(axios,react-router-dom,redux,react-redux)的功能。java

1、初始化包

npm init -ynode

package.json中增长两项react

"bin":{
	testCli:"./main.js"
}
"private":false
复制代码

bin目录下的testCli 表示,咱们在命令行输入testCli 则会调用main.js内的内容,ios

private:false 表示内容是公开的,便可以被npm发布的git

在main.js中增长github

#!/usr/bin/env node 
复制代码

其中 #!/usr/bin/env node 的做用就是这行代码是当系统运行到这一行的时候,去 env 中查找 node 配置,而且调用对应的解释器来运行以后的 node 程序shell

而后咱们须要测试代码,这里可能须要用到 npm link 或者 npm install -g 。这样在命令行执行testCli就能够看到你在main.js中写入的代码,这里写一个hello worldnpm

console.log("Hello World")
复制代码

npm link: 将当前package连接到全局 —— npm unlinkjson

npm install -g: 将当前package安装到全局 —— npm uninstall -g

2、增长功能

交互命令—— 使用commander

const { program } = require('commander')

program
    .version('0.1.0')  // --version 版本
    .command('init <name> [branch]') // 初始化命令
    .description('初始化项目文件')
    .action( (name,branch) => { // 获得name 
        console.log('Hello World') // 进行输出
    })

program.parse(process.argv) // 解析变量
复制代码

The arguments may be <required> or [optional],尖括号必须,optional可选

文件拉取 —— 使用download-git-repo

download("direct:https://github.com/oniya24/simple-create-react_template.git",
targetPath,{ clone:true }, // 目标路径
(err)=>{ // 回调函数
    console.log(err)
}
复制代码

坑:'git clone' failed with status 128 经过git clone拉取出错

将git改成经过 direct: http:// URl的方式进行clone

命令行交互 —— 使用inquirer

program
    .version('0.1.0')
    .command('init <name>')
    .description('初始化模板')
    .action( (name) => {
        inquirer.prompt([
            {
                name:"description",
                message:"请输入描述"
            },{
                name:"author",
                message:"请输入做者"
            }
        ]).then((paramater)=>{
            console.log(paramater);
        })})
复制代码

prompt提交一个询问数组,name是key值,message是输入时的提示,

返回一个对象,返回上述字段输入的value,{ description: xxx, author: yyy}

替换模板内容 —— 使用 handlebars

// 输入源模板
const source = "<p>description is {{description}} , author is {{ author }}</p> ";
// 进行模板的解析
const template = Handlebars.compile(source);
// 内容的定义
const paramater = { description: 'xxx', author: 'yyy' };
// 进行内容的替换
console.log(template(paramater));
// description is xxx,author is yyy
复制代码

由这个模板咱们能够替换掉配置文件的内容,因此咱们须要将模板的package.json进行改造,而后下载模板成功后,经过inquirier查询到的变量,进行内容的替换

// package.json

author: "{{ author }}",
description: "{{ description }}"
复制代码

拉取到代码以后,经过fs模块首先判断是否有package.json文件,若是有则读取文件内容,对文件内容经过handlebars进行内容的替换,而后再写入文件中。

const content = fs.readFileSync(packagePath).toString();
const template = Handlebars.compile(content);
const result = template(paramater);
fs.writeFileSync(packagePath,result);
复制代码

美化命令行 —— 使用chalk ora

高亮终端打印出来的信息:chalk。

终端加载效果:ora, 在代码拉取过程有加载的效果

const spinner = ora("模板下载中^.^ 请稍后");
spinner.start();
spinner.success();
chalk.green('成功了');
chalk.red('失败了')
复制代码

总体代码

静态拉取代码见:github.com/oniya24/sim… 的staticFillPull的文件

3、可选择配置项

咱们发现基础功能已经实现了,可是还存在两个问题

  1. 拉取的是静态代码,对于一些咱们不须要的配置,如react-router、loadsh没法选择
  2. 拉取代码后还须要本身进行npm install,不能直接使用

如何实现按需添加 —— inquirer的type + handlebars的判断

查阅资料后发现,咱们的inquirer功能比较强大,还能够经过更改type,来支持confirm判断或者list选择,因此选择的部分咱们就能够用inquirer来实现,而后根据咱们查询获得的结果进行package.json的更改。

Confirm - {type: 'confirm'}

Take type, name, message, [default] properties. default is expected to be a boolean if used.

package.json中咱们须要用到模板的写法,这里再次查阅handlebars的文档,发现它支持判断语句(nice!)

官网文档:handlebarsjs.com/guide/

{{#if isReactRedux}}
 "react-redux": "^7.2.0",
 {{/if}}
 {{#if isReactRouterDom}}
 "react-router-dom": "^5.1.2",
 {{/if}}
 {{#if redux}}
 "redux": "^4.0.5",
 {{/if}}
复制代码

这样可选配置的部分咱们就完成了,你们能够根据本身的须要来增删配置。

如何实现node命令的使用 —— child_process

process.cwd()返回当前执行目录

使用child_process的spawn()启动一个子进程执行命令,参数(command, [args], [option])

这里增长了三个参数,cwd命令执行目录,stdio:"inherit"继承父进程的输入输出流,shell:在shell下执行

与exec()方法均开启一个子进程执行命令,不一样的是exec()有一个回调函数货值子进程的状态

const spawn = require('child_process').spawn;
const chalk = require("chalk");

let runInstall = async function(cwd,callback,executable = 'npm',args = ['install']){
    console.log(chalk.greenBright("正在安装项目依赖……\n"));
    // 执行executable args 对应到默认参数即 npm install 安装依赖
    await new Promise((resolve, reject) => {
        const installProcess = 
        spawn(executable, args, { cwd: cwd,stdio: "inherit", shell: true });
        //文件目录, 继承父进程的输入输出【即控制台能够看到子进程输出】,开启shell 
        installProcess.on('exit', () => {
            console.log(chalk.greenBright("依赖安装完成!"));
            resolve();
        });
        installProcess.on('error',(err)=>{
            console.log(chalk.red("依赖安装失败"));
            reject(err);
        })
    }).then(()=>{ callback(); })
    .catch((err)=> { console.log(chalk.red("出现错误"));console.log(err) });

}
复制代码

4、打包发布

--- main.js

--- utils

------ outputFunc

------ npmInstall

------ inquirerArr

增长了重名文件判断,再总体再进行一下结构优化,就能够准备发布啦!

配置更改

发布前要对package.json的配置进行更改

name: 主要是包名,必须惟一
version: 版本号,每次发布至 npm 须要修改版本号
description: 描述。
main: 入口文件,import/require的
keyword:关键字,以空格分离但愿用户最终搜索的词。
author:做者
private:是否私有,须要修改成 false 才能发布到 npm
复制代码

发布

npm login 登陆

npm publish packageName 发布

可能存在的问题

1.报错 Private mode enable, only admin can publish this module [no_perms] Private mode enable, only admin can publish this module: clitest
错误:403
这是由于咱们设置了淘宝镜像,https://registry.npm.taobao.org/,将registry设置为原来的镜像
命令:npm config set registry=http://registry.npmjs.org

2. 报错If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator (though this is not recommended).
清理下缓存:删除C:\Users\Administrator\下的.npmrc文件
而后再次登陆
(还有一个缘由多是忘记登陆了,捂脸QAQ)

3. 打包使用的时候,要将__dirname 替换为 process.cwd()

复制代码

发布成功后,就能够快乐的使用啦!

npm install -g simple-create-react 全局安装

simple-create-react init projectName 拉取模板进行初始化

如图:

5、总结

  1. 经过commander实现命令行的交互
  2. 经过download-git-repo实现仓库代码的拉取
  3. 经过inquirer实现配置的选择和相关项的填写,实现可选配置
  4. 经过handlebars实现对package.json模板的替换
  5. 经过chalk和ora对命令行的输出进行美化
  6. 经过child_process模块开启子进程,实现依赖的npm install

源码github.com/oniya24/sim…

参考:

相关文章
相关标签/搜索