Creat-React-App 奇妙之旅

3,230 阅读4分钟

最近一年多工作中,都在用vue进行开发,但心中一直对react有念念不忘。于是最近又想把react拎出来捣鼓一番。业界中总有vue好还是react更优的讨论(好比php是最美的语言哈哈哈哈哈),我觉得都挺好,vue的指令真的香,react一切皆组件的思想真的是高(如今有了hooks加持,函数组件也更香了)。你品,你细品。

言归正传。总之,想要学习一门框架语言,首先得有学习的轮廓基石吧。基于此,React官方推出的Create-React-App(以下简称CRA)很好地解决了我们的烦恼。

CRA提供了开箱即用的服务,默认内置了大量优秀的项目(比如Webpack、Babel、Eslint)为应用做了支持。无论你是使用 React还是其他库,Create React App 都可以让你专注于代码,而不是专注于构建工具。

但在实际应用开发中,CRA默认配置可能无法满足我们的业务需求,所以本篇文章的目标就是对CRA实现有效扩展。让我们一起开始CRA奇妙之旅吧~


初始化项目

为了更好规范团队多人协同开发,采用Typescript。TypeScript是JavaScript的类型超集,可编译为纯 JavaScript 。

使用 TypeScript 创建新的 Create React App 项目,你可以运行:

$ npx create-react-app my-react-app-ts --typescript

如何扩展默认内置Webpack?

如果你对构建工具和配置选项不满意,官方提供eject脚本指令,直接eject出整个配置在业务项目里维护。切记该操作的缺点是不可逆,一旦配置文件暴露后就不再可隐藏。

$ npm run eject

显然,eject操作违背了CRA专注于代码,而不是专注于构建的初衷,思考有什么方式可以在不eject前提下,对默认CRA webpack配置做定制化修改,然后根据修改后配置编译工程呢? 于是在React社区出现了react-app-rewired

react-app-rewired 此工具可以在不eject也不创建额外react-scripts的情况下修改CRA内置的webpack配置,然后你拥有CRA的一切特性,且你可以根据你的业务需要去定制化配置webpack的plugins、loaders等。

另外customize-cra(对于react-app-rewired@2.x以上版本)辅助提供了一组用于自定义利用react-app-rewired核心功能的CRA2.0配置。

1)安装react-app-rewired(针对使用webpack4.0)

$ npm install react-app-rewired customize-cra --save-dev

2)在根目录下创建一个config-override.js

/* react-app-rewired@2.x以下版本 */
module.exports = function override(config, env) {
    //do stuff with the webpack config...
    return config;
}
    
/* react-app-rewired@2.x以上版本 */
const {override, overrideDevServer, addWebpackAlias} = require('customize-cra');
    
module.exports = {
    webpack: override(
        addWebpackAlias({
            '@': path.resolve(__dirname, '.', 'src')
        })
    ),
    devServer: overrideDevServer()
};

3)修改package.json文件

"scripts": {
    "start": "react-app-rewired start"
},

如何分不同环境读取变量值?

通常从开发到发布,会经过FAT、UAT、PROD三个环境,而不同环境下相同变量对应的值是不一样的。例如,接口baseURL在三个环境下分别是a、b、c,在分环境打包时如何自动根据不同环境读取不同变量值呢?于是,社区出现了dotenv-cli

1)安装dotenv-cli

$ npm install dotenv-cli --save-dev

2)在根目录下分别创建.env.fat,.env.uat,.env.prod

3)修改package.json文件

"scripts": {
    "serve:fat": "dotenv -e .env.fat react-app-rewired start",
    "serve:uat": "dotenv -e .env.uat react-app-rewired start",
    "serve:prod": "dotenv -e .env.prod react-app-rewired start",
    "build:fat": "dotenv -e .env.fat react-app-rewired build",
    "build:uat": "dotenv -e .env.uat react-app-rewired build",
    "build:prod": "dotenv -e .env.prod react-app-rewired build",
},

如何规范git commit提交信息?

通常规范这种事情,人为约定去执行一定是非最佳选择,对于人为误操作无法控制。在多人协同开发团队中引入工具自动化校验是最合适的了。引入commitizen规范commit信息格式,引入yorkie通过git hooks在commit之前对信息进行校验,通过方可commit成功。

1)安装commitizen、cz-conventional-changelog、yorkie

$ npm install commitizen cz-conventional-changelog yorkie --save-dev

2)在根目录下创建verify-commit-msg.ts

const chalk = require('chalk');
const msgPath = process.env.GIT_PARAMS;
const msg = require('fs').readFileSync(msgPath, 'utf-8').trim();

const commitRE = /^(revert: )?(feat|fix|improvement|docs|style|refactor|perf|test|build|workflow|ci|chore|revert)(\(.+\))?: .{1,50}/;

if (!commitRE.test(msg)) {
  console.log();
  console.error(
    `  ${chalk.bgRed.white(' ERROR ')} ${chalk.red(`invalid commit message format.`)}\n\n` +
    chalk.red(`  Proper commit message format is required for automated changelog generation. Examples:\n\n`) +
    `    ${chalk.green(`feat(compiler): add 'comments' option`)}\n` +
    `    ${chalk.green(`fix(v-model): handle events on blur (close #28)`)}\n\n` +
    chalk.red(`  See .github/COMMIT_CONVENTION.md for more details.\n`) +
    chalk.red(`  You can also use ${chalk.cyan(`npm run commit`)} to interactively generate a commit message.\n`)
  );
  process.exit(1)
}

3)修改package.json

"scripts": {
    "commit": "git-cz"
},
"gitHooks": {
    "commit-msg": "node scripts/verify-commit-msg.ts"
},
"config": {
    "commitizen": {
        "path": "cz-conventional-changelog"
    }
}

4)执行

$ npm run commit

如何引入scss预处理器&导入scss公共样式文件

要想使用sass,CRA官方文档已经有了详细说明,首先安装node-sass

$ npm install node-sass --save-dev

将所有 *.css 文件后缀改成 *.scss或 *.sass,该类文件将会自动编译。

要在 Sass 文件之间共享变量,可以使用 Sass 导入。 例如,src/App.scss和其他组件样式文件可能包含 @import "./shared.scss"; 中定义的变量。

但是随着业务饱满,代码量增加,每个scss文件都手动@import公共样式文件是不是觉得很累,也太傻瓜了呢(哈哈哈哈哈)。通常会通过引入sass-resources-loader解决这种烦恼,但是在CRA中通过rewired方式引入sass-resources-loader呢?让我们回到customize-cra。

1)安装sass-resources-loader

$ npm install sass-resources-loader --save-dev

2)修改config-overrides.js

const {override, adjustStyleLoaders} = require('customize-cra');
module.exports = {
  webpack: override(
    adjustStyleLoaders(rule => {
      if (rule.test.toString().includes('scss')) {
        rule.use.push({
          loader: require.resolve('sass-resources-loader'),
          options: {
            resources: './src/styles/shared.scss'
          }
        });
      }
    }),
  )
};

如何实现移动端自适应?

由于本人实际工作方向以移动端H5为主,那么移动端针对不同大小机型实现页面布局的响应式变化是我特别关注的一点。通常页面自适应可以通过rem或vwvh等来实现,但设计师给到开发的设计稿都是以固定宽高像素px设计的,那么如何把px根据设计比例转化为rem或vwvh单位呢,人工手工换算或者每次引入公共mixin函数是不是都会觉得繁琐,试想这件事如果交给webpack去做呢。 以px转vh为例,如何在CRA中通过rewired方式自动转换?

1)安装postcss-px-to-viewport

$ npm install postcss-px-to-viewport --save-dev

2)修改config-overrides.js

const {override, addPostcssPlugins} = require('customize-cra');

module.exports = {
  webpack: override(
    addPostcssPlugins([
      require('postcss-px-to-viewport')({
        unitToConvert: 'px',
        viewportWidth: 1024,
        viewportHeight: 768,
        unitPrecision: 5,
        propList: ['*'],
        viewportUnit: 'vh',
        fontViewportUnit: 'vh',
        selectorBlackList: [],
        minPixelValue: 1,
        mediaQuery: false,
        replace: true,
        exclude: [],
        landscape: false,
        landscapeUnit: 'vh',
        landscapeWidth: 568
      })
    ])
  )
};

总结

到此,本文主要介绍的是如何扩展CRA的一些基础 webpack配置,每个人可以根据自身业务需求,再进行定制化扩展,比如自定义eslint规则、prettier格式规范等。

当然一个完整的SPA应用,当然少不了路由的概念,可以通过react-router官方去学习,在v4之后,照着路由皆组件的思想应该更易理解。在这里就不做详述了。

最后再提一句react hooks吧,hooks就是曾经函数组件(无状态组件)的加强武器,使其具备了类组件同等的能力,还大大减少了代码量。以后是不是就可以大声说:一切皆函数组件了😊。

感谢大家的阅读~