资讯专栏INFORMATION COLUMN

做一个基于react-scripts的脚手架

linkFly / 1943人阅读

摘要:前言作为官方的脚手架是相当好用的。注意就是脚手架的核心配置代码。另一个是使用,用户通过增加修改配置。所以才有了今天的主题基于的脚手架,确切说应该是基于的脚手架。其中一定要填写。

前言

create-react-app作为facebook官方的react脚手架是相当好用的。主要设计原理是将配置好的如Webpack,Babel,ESLint,合并到react-scripts这npm包中,用户就可以开箱即用。很多开发者都在这基础上进行改造开发。注意react-scripts就是create-react-app脚手架的核心配置代码。

目前如果要自己定制配置,有两种方案可选。一个是eject,他的原理是将react-scripts拆除然后将配置暴露到应用顶层,用户就可以自行进行配置。另一个是使用react-app-rewired,用户通过config-overrides.js增加修改配置。两者各有好处。eject直接暴露可以自行配置,但是坏处就是react-scripts被解散了,就不能随官方配置进行升级。react-scripts包揽了那些最基础配置的脏活累活,并且一直再维护,比如修复BUG和打包优化,运行速度优化。前端发展的迅速,这些基础配置随着基础设施的升级,可能随时都会变化。我觉得eject后要就需要承担维护成本的风险。我的理念是将专业的事情交给专业的人去做就好了,我们应该享受金字塔底层带来的基础设施便利去创造价值,没必要重复造轮子,更没必要在轮子上耗费过多的维护成本。

我的理念是推荐使用config-overrides.js来定制配置,降低维护成本。也就是在react-scripts的配置上进行增删改查,不影响底层配置代码,在未来需要的时候还可以进行无缝升级react-scripts,来提升速度或者解决你未关注到的BUG等等。但是create-react-app只是提供最最基础的设施建设,我们最常用的框架配置都需要自己去定制,每次创建项目的时候都需要再写一次定制代码,相当烦人。所以才有了今天的主题基于create-react-app的脚手架,确切说应该是基于react-scripts的脚手架。

所以这篇文章主题应该有两个

怎么制作CLI工具

怎么根据react-scripts来写脚手架

项目核心代码在github上:(github.com/LinYouYuan/…),这个链接上面也有使用帮助说明,可以先点击进去看,可以更好的理解使用和需求。

项目核心需求

我们需求是:

    保证基础依赖和官方同步;

    创建时增加常用框架选择;

    创建项目后配置项可定制;

第一点,我们需要引入react-scriptsreact-app-rewired,来保持官方同步和可定制型。

第二点,我整理出我们常用的框架可选项:

类型 可选框架名称
语言 JavaScript / TypeScript
状态管理库 Redux / Mobx
css预处理器 SCSS / LESS / styled-components
UI组件 Antd / Ant-mobile
代码规范 Airbnb
HTTP库 Axios
路由 react-router

第三点,创项目后我们可以通过config-overrides.js文件来预先配置,然后用户可以再此文件进行继续配置和改造。

制作CLI工具 引入常用工具包

首先创建nodejs项目。制作常用的Cli工具,我们一般都需要安装下面5个工具包:(执行npm install或者其他工具安装)

commander: 用来接收输入命令参数,然后处理事件;

execa: 用来执行操作命令,一个更好的child_process

inquirer: 这是创建cli最主要的工具,可以生成非常美观的命令行界面;

chalk: 可以修改字体颜色;

fs-extra: 比原生fs更好用的fs;

创建全局使用

我们首先要创建一个像creact-react-app一样直接在全局就可以执行使用的命令。

    我们在根目录下创建文件夹和文件lib/index.js,这个其实就是入口执行文件。其中#!/usr/bin/env node一定要填写。

lib/index.js

</>复制代码

  1. #!/usr/bin/env node
  2. console.log("hello world")

    然后在package.json中添加代码,如下,其中react-cli就是全局要使用的命令名称,lib/index.js就是上面要执行的文件地址。

package.json

</>复制代码

  1. "bin": {
  2. "react-cli": "lib/index.js"
  3. }

    执行npm link。执行完成后,我们就可以把命令挂载到全局,效果和npm install -g后一样,可以全局输入命令。link的主要目的是给我开发调试用的。现在可以直接在控制台输入react-cli执行,你就可以看到打印的hello world了。

    等开发完成,你可以试试发布到npm包上,但是我推荐等开发完成后再发布,当然不妨碍你好奇心想试试。发布前需要执行npm login,登录npm账号密码,注意你如果是淘宝源你需要通过npm config set registry http://registry.npm.tongdun.cn暂时切回官方源。然后执行npm publish发布,这个时候也要注意,你的package.json中的name也就是项目名称不要和别人重名了。发布好你就可以通过npm i -g来全局安装你的包。

命令管理

lib/index.js中,我们输入如下

</>复制代码

  1. const program = require("commander");
  2. const chalk = require("chalk");
  3. program
  4. .version(require("../package").version)
  5. .usage(" [options]");
  6. program
  7. .command("create ")
  8. .description("create a new project powered by react-cli")
  9. .action(name => {
  10. // 这里处理逻辑
  11. console.log(chalk.blue(`React CLI v${require("../package").version}`));
  12. // const create = require("./cli/create");
  13. // create(name);
  14. });

这里主要通过commander来配置接受不同命令处理。这里主要就是要接受create 参数,然后处理输入命令后的逻辑。其中chalk就是颜色处理。

然后继续处理未输入和输入错时候弹出帮助如下

</>复制代码

  1. program
  2. .arguments("")
  3. .action((cmd) => {
  4. program.outputHelp()
  5. console.log(` ` + chalk.red(`Unknown command ${chalk.yellow(cmd)}.`))
  6. console.log()
  7. })
  8. program.parse(process.argv);
  9. if (!program.args.length) {
  10. program.outputHelp();
  11. }
交互界面

接收到用户输入的命令后,我们就要呈现交互界面,这个时候我们就用到了非常好用的工具inquirer。具体可以实现多少种交互形式可以点inquirer的npm网站的介绍看。我这里主要用了listconfirm的功能,也就是列表选择和寻问功能。比如让用户选择使用什么框架:

</>复制代码

  1. function selectManually(appName) {
  2. inquirer
  3. .prompt([
  4. {
  5. type: "list",
  6. name: "language",
  7. message: "pick a language:",
  8. choices: [
  9. "JavaScript",
  10. "TypeScript",
  11. ]
  12. },
  13. {
  14. type: "list",
  15. name: "stateManagement",
  16. message: "Pick a state management:",
  17. choices: [
  18. "Mobx",
  19. "Redux",
  20. ]
  21. },
  22. {
  23. type: "list",
  24. name: "cssPre",
  25. message: "Pick a CSS pre-processor:",
  26. choices: [
  27. "LESS",
  28. "SCSS/SASS",
  29. "styled-components",
  30. ]
  31. },
  32. {
  33. type: "list",
  34. name: "design",
  35. message: "Pick a UI Design:",
  36. choices: [
  37. "Ant Design",
  38. "Ant Design Mobile",
  39. ]
  40. },
  41. ])
  42. .then(answers => {
  43. const creator = new Creator(appName, answers);
  44. creator.create();
  45. })
  46. }
创建项目

新建一个Creator类,主要用来创建项目用的,初始化接受两个参数,一个是项目名称,一个是用户选择的框架。我项目中的模板存放在lib/packages/common-default中。这里我主要针对各种不同的配置,来修改packages.jsonbabelrcconfig-overrides.js文件的内容就好了,然后执行复制操作。

</>复制代码

  1. const chalk = require("chalk");
  2. const fs = require("fs-extra");
  3. const path = require("path");
  4. const inquirer = module.require("inquirer");
  5. const {
  6. getPackageJson,
  7. writeJsonToApp,
  8. copyFiles,
  9. setNewPackageVersion,
  10. installPackge,
  11. setUserConfig,
  12. } = require("../packages/common");
  13. class Creator {
  14. constructor(appName, answers) {
  15. this.appName = appName;
  16. this.answers = answers;
  17. this.appDir = path.resolve(process.cwd(), this.appName);
  18. this.package = getPackageJson("cli-switch");
  19. this.babelrc = {
  20. plugins: [
  21. [
  22. "import",
  23. {
  24. libraryName: "antd",
  25. style: true,
  26. }
  27. ]
  28. ]
  29. }
  30. }
  31. async testExistDir() {
  32. if (fs.existsSync(this.appDir)) {
  33. const { override } = await inquirer.prompt([
  34. {
  35. type: "confirm",
  36. name: "override",
  37. message: chalk.red(`directory ${this.appName} exist,override it");)
  38. }
  39. ]);
  40. if (override) {
  41. console.log(chalk.green("removing..."));
  42. fs.removeSync(this.appDir);
  43. return true;
  44. } else {
  45. process.exit(1);
  46. return false;
  47. }
  48. }
  49. return true;
  50. }
  51. async create() {
  52. const { stateManagement, cssPre, design } = this.answers;
  53. console.log();
  54. console.log(`you pick: ${chalk.yellow(`${stateManagement}, ${cssPre}, ${design}, Router, ESLint`)}`);
  55. console.log();
  56. const isOk = await this.testExistDir(this.appDir, this.appName);
  57. if (!isOk) {
  58. return;
  59. }
  60. console.log(`

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/7313.html

相关文章

  • 从零开始开发一个react手架(二)

    摘要:弄清之后,就去脚手架源代码里面找。这样更加灵活,而且复用性高,起新项目,如果差别不大,几乎可以做到零配置,这样开发者压根就不需要关心业务之外的东西从零开始开发一个脚手架三 上一篇已经初步整了个kkk-react,这一篇不写代码,粗略讲解下create-react-app的部分源码。 前沿:科普下看源码的思路。以本人看过N多源码的经验总结,想要看这种脚手架或者npm包的源码,第一步就是看...

    Y3G 评论0 收藏0
  • 深度解析`create-react-app`源码

    摘要:这个选项看意思就知道了,默认使用来安装,运行,如果你没有使用,你可能就需要这个配置了,指定使用。 2018-06-13 更新。昨天突然好奇在Google上搜了一波关于create-react-app 源码的关键词,发现掘金出现好几篇仿文,就连我开头前沿瞎几把啰嗦的话都抄,我还能说什么是吧?以后博客还是首发在Github上,地址戳这里戳这里!!转载求你们注明出处、改编求你们贴一下参考链...

    waruqi 评论0 收藏0
  • 在 React-CRA 应用中配合 VSCode 使用 ESLint 实践前端代码规范

    摘要:编码规范是独角兽公司内部的编码规范,该项目是上很受欢迎的一个开源项目,在前端开发中使用广泛,本文的配置规则就是以编码规范和编码规范作为基础的。 更新时间:2019-01-22React.js create-react-app 项目 + VSCode 编辑器 + ESLint 代码检查工具 + Airbnb 编码规范 前言 为什么要使用 ESLint 在项目开发过程中,编写符合团队编码规...

    Hujiawei 评论0 收藏0
  • 实现antd按需加载

    摘要:使用来进行按需加载安装关于插件的介绍和使用,可参考使用这个插件之后仍然可以用来引入组件,但是这个时候插件会帮你转换成的写法。另外此插件配合属性可以做到模块样式的按需自动加载。 引言 create-react-app:是一个创建react项目特别方便的脚手架,他帮我们配置好了各种需要使用的工具,减少了很多工作量。antd:是蚂蚁金服推出的一个很优秀的react UI库,其中包含了很多我...

    0xE7A38A 评论0 收藏0
  • 通过create-react-app从零搭建react环境

    摘要:通过文件可以对图标名称等信息进行配置。注意,注册的只在生产环境中生效,并且该功能只有在下才能有效果该文件是过滤文件配置该文件是描述文件定义了项目所需要的各种模块,以及项目的配置信息比如名称版本许可证等元数据。 一、 快速开始: 全局安装脚手架: $ npm install -g create-react-app 通过脚手架搭建项目: $ create-react-app 开始项目: ...

    Cympros 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<