Skip to content

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

安装

bash
npm install -g create-react-app
npm install -g create-react-app

创建项目

bash
create-react-app demo
create-react-app demo

开启自主配置

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

proxy 配置

package.json:

javascript
"proxy": {
    "/api/v1": { "target": "https://cnodejs.org" }
}
"proxy": {
    "/api/v1": { "target": "https://cnodejs.org" }
}

css 模块化

修改 webpack.config.devwebpack.config.prod

css-loaderoptions 中加入 module: true

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

postcss-px2rem

慎用!按需求用!

安装

bash
yarn add postcss-px2rem
yarn add postcss-px2rem

使用

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

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

加入 react-router 4

bash
yarn add react-router react-router-dom
yarn add react-router react-router-dom
jsx
import { HashRouter as Router, Route, Link } from "react-router-dom";
//...
<Router>
  <div>
    <Route exact path="/" component={Hello} />
  </div>
</Router>;
import { HashRouter as Router, Route, Link } from "react-router-dom";
//...
<Router>
  <div>
    <Route exact path="/" component={Hello} />
  </div>
</Router>;

JS 控制跳转

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

加入 redux

src:

jsx
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")
);
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")
);

如果使用了路由:

jsx
class MainPage extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <Router>
          <div>
            <Route exact path="/" component={HelloView} />
          </div>
        </Router>
      </Provider>
    );
  }
}
class MainPage extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <Router>
          <div>
            <Route exact path="/" component={HelloView} />
          </div>
        </Router>
      </Provider>
    );
  }
}

快速点击修正

bash
yarn add react-fastclick
yarn add react-fastclick
jsx
import initReactFastclick from "react-fastclick";
initReactFastclick();
import initReactFastclick from "react-fastclick";
initReactFastclick();

打包后路径不是相对路径

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

打包时抽离公共 JS

javascript
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
  }),
]
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
  }),
]

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

https://www.npmjs.com/package/react-loadable

路由拆分

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

jsx
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"));
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"));

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

最后编辑时间:

Version 4.0 (framework-1.0.0-rc.20)