前言
在写了两年的vue后,终于又能愉快的用react了~2021了,得益于那些伟大的项目,前端的环境搭建也早已不像从前那样风格迥异,艰难异常。我们就来已创建一个lib工程为例,看看如何用create-react-app
(cra)配合一系列其他工具,快速搭建一个用于开发组件lib库的react开发环境。
我们的目标
- 用cra创建,但不用
eject
来反编译生成构建源码。 - 使用
react-app-rewired
来扩展webpack的构建功能 - 配置代码校验和提交message校验工具,从而保证代码规范
- 迅速生成开发组件的示例以及文档
- 根据生产环境配置build出相应的lib包
用cra创建项目
首先,创建项目目录。不同以往,现在我们用cra初始化react项目非常简单,只需如下简单一步。
1 | npx create-react-app my-app |
生成的代码目录一目了然,也比较简单,这里说下public,这个目录存放的是静态资源,编译之后都会被copy到build目录
1 | my-app |
现在在看package.json中的script,自动写入了4个脚本,我们运行start即可成功启动项目。
1 | "scripts": { |
注:eject脚本会把cra的配置完全暴露病托付给开发者,而且是一个不可逆转的操作,因此,在非必要的情况下,尽可能不要去用到这个脚本。
用cra创建的项目,默认是src/index.js
的单入口的SPA,也只有一个dev和build的环境,但在现实开发中我们的配置是多样化的,比如多入口打包,多环境打包甚至其他一些意想不到的骚操作等。就好像我们正在搭建的lib项目,需要在本地开发时运行dev能看到效果,但在build时只需要组件部分的打包。
cra虽然便捷的帮我们创建了项目,但并不能让我们自由地进行配置,若我们使用eject来反编译出配置,除了增加了项目的理解负责度和学习成本,也不利于将来的维护。因此我们应该使用react-app-rewired来配置cra生成的项目。
react-app-rewired自定义配置
首先肯定是安装依赖:
- 对于使用 Webpack 4 的 create-react-app 2.x
1
2
3npm install react-app-rewired --save-dev
// or
yarn add react-app-rewired --dev - 对于 create-react-app 1.x 或 react-scripts-ts 与 Webpack 3再替换package.json中的scripts,来接管react-scripts:
1
2
3npm install react-app-rewired@1.6.2 --save-dev
// or
yarn add react-app-rewired@1.6.2 --dev1
2
3
4
5
6
7
8
9"scripts": {
- "start": "react-scripts start",
+ "start": "react-app-rewired start",
- "build": "react-scripts build",
+ "build": "react-app-rewired build",
- "test": "react-scripts test --env=jsdom",
+ "test": "react-app-rewired test --env=jsdom",
"eject": "react-scripts eject"
}
然后,为了变更create-react-app的配置,我们可以采取两种方式:
- 在package.json中配置第三方的
config-overrides.js
:1
"config-overrides-path": "node_modules/some-preconfigured-rewire"
- 在根目录中创建一个
config-overrides.js
文件:- 默认情况下,该文件导出
单个函数
,以便在开发或生产模式下自定义webpack配置1
2
3
4module.exports = function override(config, env) {
//do stuff with the webpack config...
return config;
} - 也可以使文件中导出一个对象,每个属性都是一个函数。这种增强型的方式,就可以另外配置Webpack Dev Server或Jest。在我们项目中,需要根据编译环境调整文件入口,此时我们需要多环境配置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33module.exports = {
// The Webpack config to use when compiling your react app for development or production.
webpack: function(config, env) {
// ...add your webpack config
return config;
},
// The Jest config to use when running your jest tests - note that the normal rewires do not
// work here.
jest: function(config) {
// ...add your jest config customisation...
return config;
},
// The function to use to create a webpack dev server configuration when running the development
// server with 'npm run start' or 'yarn start'.
// Example: set the dev server to use a specific certificate in https.
devServer: function(configFunction) {
// Return the replacement function for create-react-app to use to generate the Webpack
// Development Server config. "configFunction" is the function that would normally have
// been used to generate the Webpack Development server config - you can use it to create
// a starting configuration to then modify instead of having to create a config from scratch.
return function(proxy, allowedHost) {
// Create the default config by calling configFunction with the proxy/allowedHost parameters
const config = configFunction(proxy, allowedHost);
// Return your customised Webpack Development Server config.
return config;
};
},
// The paths config to use when compiling your react app for development or production.
paths: function(paths, env) {
// ...add your paths config
return paths;
},
}
- 默认情况下,该文件导出
用env-cmd设置环境
安装env-cmd
后在项目根目录新建.env
文件,我们项目里定义为library,项目结构如下:
1 | my-app |
然后我们在.env.library
中写入环境变量
1 | REACT_APP_NODE_ENV = "library" |
然后在package.json的scripts中改写build脚本,让我们的编译带上指定的环境变量:
1 | "scripts": { |
重写config-overrides.js
安装了react-app-rewires
和env-cmd
后,我们就可以根据环境变量配置相应的webpack配置了,这里我们只是简单的把打包方式和css做下处理。
我们新建一个脚本,比如scripts/library.config.js
,写入我们的自定义配置:
1 | const path = require('path'); |
上面代码中的externals,主要是用来在process.env
中筛选出react
,react-dom
等作为外部依赖,写法比较独特。
然后在config-overrides.js
中,将我们刚才写的逻辑加入:
1 | const libraryConfig = require('./scripts/library.config.js'); |
此时传入我们在.env.library
中定义的REACT_APP_NODE_ENV变量,即可复写webpack中的配置。
至此,我们通过cra以及其他工具,就已经搭建了好了一个能用来打包lib的开发环境,接下来就可以开始组件的开发了。
组件编写
在src目录下,新建组件放的目录components和样式目录styles:
1 | src |
以Demo组件为例,按照如下格式依次在components下创建文件:
1 | components |
最后在src/index.js
中对外抛出即可。
1 | import Demo from './components/Demo'; |
本地调试 & 文档
本地开发模式下参与调试的文档工具很多,比如大名鼎鼎的storybook
和docz
,这里,我们选用react-styleguidist,看看github上的示例图,应该还挺好用。
这里不多赘述,只要按照官方文档的操作,react-styleguidist会默认为src/components/**/*.js
的js文件生成文档。通过生成的文档我们可以看出,react-styleguidist读取了注解、Button.propTypes和Button.defaultProps为我们生成了组件文档,并且将propTypes的注解放到description中。
注:react-styleguidist读取的是注解,不是注释语句
在实际开发中,我们还能通过在组件下新建Readme.md
来自定义文档,在md文件中可以写jsx和style,可谓是非常贴心了。
安装后,修改package.json:
1 | scripts: { |
来,启动start,感受下吧~
总结
通过以上步骤,我们就能创建出一个比较合理的开发环境。2021了,在日新月异大浪淘沙的前端领域,这些神奇的项目工具让我们能站在巨人的肩膀上,摆脱曾经刀耕火种般的手工劳动,轻轻松松就能搭建出一整套react开发环境,虽然工程是多样的,但是终究是万变不离其宗的。项目搭建后,可以通过增加一系列的lint,来完善项目的工程化,保证项目的规范化,在下一篇中再详细介绍。