使用 react 脚手架 create-react-app 创建项目后的几个优化

# 安装

npm install -g create-react-app
1

# 创建项目

create-react-app demo
1

# 开启自主配置

执行 yarn eject 转换到可自主配置的模式

# proxy 配置

package.json:

"proxy": {
    "/api/v1": { "target": "https://cnodejs.org" }
}
1
2
3

# css 模块化

修改 webpack.config.devwebpack.config.prod

css-loaderoptions 中加入 module: true

这样就可以使用 import 来导入需要的 CSS 了。

# postcss-px2rem

慎用!按需求用!

安装

yarn add postcss-px2rem
1

使用

const px2rem = require("postcss-px2rem");
1
const newSize = document.documentElement.getBoundingClientRect().width / 10; // 假定标准宽度 750px,分成 10 份
document.documentElement.style.fontSize = `${newSize}px`;
1
2

postcss-loaderplugins 中加入 px2rem({remUnit: 75}) 表示一个单位 rem 等于 75px。

# 加入 react-router 4

yarn add react-router react-router-dom
1
import { HashRouter as Router, Route, Link } from "react-router-dom";
//...
<Router>
  <div>
    <Route exact path="/" component={Hello} />
  </div>
</Router>;
1
2
3
4
5
6
7

JS 控制跳转

this.props.history.push("/result");
1

# 加入 redux

src:

import React from "react";
import ReactDOM from "react-dom";
import { createStore, combineReducers } from "redux";
import { Provider, connect } from "react-redux";

const reducer = (state = {}, action) => {
  switch (action.type) {
    case "test":
      return { ...state, ...{ demo: action.data } };
    default:
      return state;
  }
};

const store = createStore(reducer);

// 不稳定的语法,ES7 装饰器
// @connect(mapStateToProps,mapDispatchToProps)
class App extends React.Component {
  render() {
    return (
      <div>
        <div onClick={ev => this.props.triggerFun("WOW!")}>Hello</div>
        <div>{this.props.demo}</div>
      </div>
    );
  }
}

const mapStateToProps = state => ({ demo: state.demo });
const mapDispatchToProps = dispatch => ({ triggerFun: data => dispatch({ type: "test", data: data }) });
const AppView = connect(
  mapStateToProps,
  mapDispatchToProps,
)(App);

ReactDOM.render(
  <Provider store={store}>
    <AppView />
  </Provider>,
  document.getElementById("react-root"),
);
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
33
34
35
36
37
38
39
40
41
42

如果使用了路由:

class MainPage extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <Router>
          <div>
            <Route exact path="/" component={HelloView} />
          </div>
        </Router>
      </Provider>
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 快速点击修正

yarn add react-fastclick
1
import initReactFastclick from "react-fastclick";
initReactFastclick();
1
2

# 打包后路径不是相对路径

package.json 中添加 "homepage": "./", 即可

# 打包时抽离公共 JS

entry: {
  polyfills: require.resolve('./polyfills'),
  app: paths.appIndexJs,
  reactVendor: [
    'react',
    'react-dom',
    'react-router',
    'react-router-dom'
  ],
  utils: [
    "moment",
    "lodash",
    "axios"
  ]
},

// ...

plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    names: ["polyfills", "reactVendor", "utils"],
    minChunks: Infinity
  }),
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 组件懒加载(针对大型项目)

https://www.npmjs.com/package/react-loadable (opens new window)

# 路由拆分

集中化的路由配置是一个很糟糕的方案,尤其是在大型 Web 应用中,路由拆分是很有必要的。

const App = () => {
  return (
    <HashRouter>
      <div>
        <Route cache component={Home} path="/" />
        <Route component={Products} path="/products" />
      </div>
    </HashRouter>
  );
};

const Products = () => {
  return (
    <div>
      <Route component={ScienceProducts} path="/sci" />
      <Route component={DailiUseProducts} path="/dai" />
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

实际开发中可以将大量的路由配置信息,按照模块化的方式进行拆分,跟路由只引入模块入口,内部页面配置在模块内部,模块内可以再切分二级模块,以此实现路由的拆分。