哇塞,有好吃的~

如何手写一个react项目生成工具,并发布到npm官网

前言

  • 基于前面自己手动搭建的React项目,我把项目分成了四种,一种什么都不带的空项目,一种带多级路由的空项目,一种带状态管理的空项目,一种带多级路由以及状态管理的空项目。这样的话每次用的时候根据需要去获取自己想要的模板,但是往往还要去github上去拷贝,感觉很不方便,所以就想到了要做一个自动生成对应的空项目的cli工具。

准备工作

  • 文件目录结构

根路径

bin

index.js

template

base项目模板
route项目模板
redux项目模板
route-redux项目模板

.gitignore
.npmignore
README.md

  • 项目模板没啥好讲的,都是之前的博客里写过了如何去手动搭建一个React项目,有兴趣的可以去看看之前的博客。这里主要看一下如何去编写这个cli工具。

原理

  • package.json文件中配置了bin的属性时,就会出现类似命令行工具的东西,当你安装过后系统会自动运行你的bin对应的文件。

步骤

  1. package.json中添加一个bin属性,指向./bin/index.js
{
    ...
    "bin": "./bin/index.js"
    ...
}
  1. 编写bin/index.js文件。第一行的注释一定要写,这个指明了你这个bin文件需要通过什么环境去执行,通常情况下,我们是通过node来执行我们的js文件的。
#! /usr/bin/env node
const fs = require('fs');
const path = require('path');

// 当你的bin被执行时,process前面的两个参数一定是node,bin/index.js这个两个参数,所以模板的参数如果传递了就是第三个参数。
const list = process.argv;
const type = list[2] || 'base';
const p = path.resolve(__dirname, `../template/${type}`); // 获取到相对应的模板路径

// 遍历文件夹下的所有目录,如果是文件夹继续走对比文件夹的方法,如果是文件就直接copy
const copy = function (src, dst) {
  let paths = fs.readdirSync(src); //同步读取当前目录
  paths.forEach(async function (path) {
    const _src = src + '/' + path;
    const _dst = dst + '/' + path;
    await fs.stat(_src, async function (err, stats) { //stats 该对象 包含文件属性
      if (err) throw err;
      if (stats.isFile()) { //如果是个文件则拷贝
        let readable = fs.createReadStream(_src);//创建读取流
        let writable = fs.createWriteStream(_dst);//创建写入流
        await readable.pipe(writable);
        console.log(`${path} 写入完成`)
      } else if (stats.isDirectory() && path !=='node_modules') { //是目录则 递归
        await checkDirectory(_src, _dst, copy);
      }
    });
  });
}

// 检查文件夹,当目标地址不存在文件夹时,为目标文件夹生成一个新的文件夹
const checkDirectory = function (src, dst, callback) {
  fs.access(dst, fs.constants.F_OK, async (err) => {
    if (err) {
      await fs.mkdirSync(dst);
      callback(src, dst);
    } else {
      callback(src, dst);
    }
  });
};


function consoleCommon() {
    console.log('暂时没有该类型的模板');
    console.log('当前支持模板如下');
    console.log('base: 基本的空项目');
    console.log('route: 带router的空项目');
    console.log('redux: 带redux的空项目');
    console.log('route-redux: 带redux和router的空项目');
}

fs.stat(p, (err, stats) => {
  if (err) {
    consoleCommon();
    return;
  }
  if (stats.isDirectory()) {
    checkDirectory(p, './', copy);
  } else {
    consoleCommon();
  }
})
  1. 测试
  • 由于不能保证自己写的bin一定没有问题,所以必要的测试时不可少的,当你实现了cli的逻辑之后,可以在当前项目路径下,直接npm install . -g,这样就会将本地的cli安装到全局。然后找一个空的文件夹,在里面去执行该cli命令,如果结果符合你的期望,那么恭喜你,你的cli工具基本就大功告成了。
  1. 发布
  • 接下来就是发布npm包这个操作了,首先在自己的node环境下去登录自己的npm账号,没有就去注册一个,然后记得把仓库切换回npm官方仓库,如果仓库地址是镜像地址,会不能发布成功的。再在项目目录下执行npm publish命令,就可以发布了,每次更新发布时,一定要记得改项目的版本号,不然就会发布不通过。

小结

  • 看过别人有一种去链接线上项目地址然后下载拷贝的实现思路,但是感觉cli工具如果能安装过后能不依赖网络去生成空的项目可能体验会更好一点,毕竟大多时候都是链接的github的地址,一旦这个网站抽筋,就下载的很慢,急死人。相对应的缺点就是这个cli工具如果出现了线上模板的更新,就需要同步去更新cli的版本才可以获取最新的包。有利就有弊吧我感觉,完全看个人喜好。
  • 我这个工具的包地址是:https://www.npmjs.com/package/create-react-auto,安装命令:npm i create-react-auto -g
  • 项目代码地址:https://github.com/810307015/react-demo-cli
  • 有兴趣的可以支持支持
posted @ 2020-08-27 10:02  风行者夜色  阅读(424)  评论(1编辑  收藏  举报