作为大前端时代的页面仔, 工作至今, 在项目中一直使用的是 Vue, 很遗憾对 React 的了解仅限于几个版本之前官方文档与网上的教程。新春伊始,有幸在下一个项目中用到 React, 既是从零开始, 不妨写一点东西以记录学习的过程,这也是用了一上午搭建的初衷。首当其冲的是项目的搭建, 相信没有人会喜欢 webpack 繁琐的配置,因此这里学一下 Create React App(CRA) 的用法。
快速开始
根据官网上的介绍,只需下面两个命令,就能实现项目的基本搭建:
$ yarn global add create-react-app$ create-react-app react-demo
生成的项目目录结构如下图所示 ?:
和 Vue Cli 相比还是比较简陋的, Vue Cli 通过命令行选择是否使用 vuex 或 vue-router,CRA 貌似需要手动添加路由库与状态管理库,这也是可以理解的,毕竟 React 生态圈中类似路由与状态管理的库不止一家。
看了下 package.json 中的 scripts 命令,如下:
"scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }
执行 start 命令会启动 webpack-dev-server 方便本地开发调试,build 命令对应打出生产环境的包。eject 命令作用是将 webpack 配置暴露出来, 默认利用 CRA 生成项目的一些 webpack 配置是不可覆盖的, 比如内置的环境变量 Process.env.NODE_ENV。 通过 eject 得到具体的 webpack 配置之后可以进行修改, 这里没有演示, 就是不想看到一堆 webpack 配置, 要的就是主流前端开发工具的开箱即用,而且 eject 执行之后是不可恢复的。
到这里就会有一个问题, 在使用 Vue Cli 时, build 命令提供了 mode 选项设置 process.evn.NODE_ENV 的值为 development 还是 production。遗憾的是, CRA 没有相似的选项。但是在实际开发中, 可能测试环境上上部署的代码需要开发环境下打包的代码以方便调试, 比如在测试环境上可以有 VConsole 和 SourceMap,但是在生产环境下就需要去掉。
那如何才能有开发环境的打包呢 ??
build 区分 development 和 production 模式
查阅文档发现, 为了达到区分生产环境构建和开发环境构建的目的, 可以通过自定义环境变量来实现, 参考 , 在项目文件夹下创建 .env.production 和 .env.development 文件。 分别设置 REACT_APP_ENV 为 production 和 development。 在package.json 中创建新的命令如下:
// yarn add dotenv-cli -D"dev-build": "dotenv -e .env.development react-scripts build"
当使用 yarn start 和 yarn dev-build 命令时会加载 .env.development 文件。 当使用 yarn build 命令时,对应加载 .env.production 文件。因此可以在业务代码中可以通过使用 process.env.REACT_APP_ENV 来区分不同构建环境(实际 dev-build 打包还是生产环境的,仅用于业务代码区分 )。
Sass/Less 处理
文档中有提到如何添加 Sass, 并没有提到如何添加 Less,真是是逼死强迫症 ?。各种查找,发现了一个工具 react-app-rewired 可以很方便的覆盖 CRA 的 webpack 配置而不用执行 eject 命令。于是乎, 安装 react-app-rewired, 并将 package.json 中的命令修改如下:
"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "dev-build": "dotenv -e .env.development react-app-rewired build", "test": "react-app-rewired test", "eject": "react-app-rewired eject" },
同时, 有 react-app-rewire-less 工具用来提供 Less 支持,瞬间人生充满希望,仿佛胜利近在咫尺。 撸起袖子,对照文档, 在项目根目录下添加 config-overrides.js 文件,内容如下:
/* config-overrides.js */ const rewireLess = require('react-app-rewire-less'); module.exports = function override(config, env) { config = rewireLess(config, env); return config; };
执行 yarn start
查看效果:
很遗憾报错了, 根据提示 getBbabelLoader 工具方法在 2.0 版本废弃, 可以使用 customize-cra 进行替代,于是安装 customize-cra。
修改 config-overrides.js 如下:
const { override, addLessLoader } = require('customize-cra');module.exports = override( addLessLoader());
重新执行 yarn start
,demo 能够正常运行了, 试了一下, 貌似还支持 css modules。 虽然有点曲折,终归是车到山前必有路。(其实心里已经喊了好多次mmp了, 整个 Less 还这么麻烦~ ?)
支持 Less 之后, 在项目中必不可少的就是 PostCSS了,还好这块文档中有提到。
PostCSS
CRA 内部已经使用了 Autoprefixer 添加浏览器前缀, 只需要在 package.json 中添加 browserslist 属行来定义支持的浏览器。
在开发 H5 app 的时候, 为了适配通常采用 rem 布局, 方便起见, 通常会用到 postcss-px2rem 这个工具, 如何在 CRA 中配置 px2rem 呢?
在上面折腾 customize-cra 的基础上,发现这个库中提供了 addPostcssPlugins 函数。
const { override, addPostcssPlugins} = require("customize-cra");module.exports = override( addPostcssPlugins([ require('postcss-px2rem')({ remUnit: 37.5 }) ]),);
代码如上, 就可以开心的使用 px2rem 了。
路由解决方案 react-router
CRA 的文档中提到最受欢迎的路由解决方案是 react-router。 命令如下
$ yarn add react-router-dom
所以 react-router-dom 是什么鬼? 参见
react-router 实现了路由的核心功能, react-router-dom 基于 react-router, 加入了在浏览器环境下的一些功能。
react-router 4.x 相较于之前的版本有着较大的变化,不过还好,对于我这种初学者来说都一样。
状态管理方案 redux or mobx
提到 React 的状态管理, 像我这样的小白, 瞬间想到的就是 Redux,但是作为初学者在没有仔细看 redux 教程时, 对一些术语, 比如 actions、reducers、middleware等感到头疼。 搜了一下社区其他的状态管理方案,看到 mobx这个库,打算对比一下学习, 挑一个用在项目中踩坑。
代码拆分(路由懒加载)
参考 React.lazy 以及 React.Suspense
写在最后
折腾一番,到这里项目结构基本上已经搭建了, 后续关于 CRA 的问题,遇到之后,再进行补充 ?。