使用 react 脚手架 create-react-app 创建项目后的几个优化
安装
sh
npm install -g create-react-app
创建项目
sh
create-react-app demo
开启自主配置
执行 yarn eject
转换到可自主配置的模式
proxy 配置
package.json:
js
"proxy": {
"/api/v1": { "target": "https://cnodejs.org" }
}
css 模块化
修改 webpack.config.dev
和 webpack.config.prod
在 css-loader
的 options
中加入 module: true
这样就可以使用 import
来导入需要的 CSS 了。
postcss-px2rem
慎用!按需求用!
安装
sh
yarn add postcss-px2rem
使用
js
const px2rem = require("postcss-px2rem");
js
const newSize = document.documentElement.getBoundingClientRect().width / 10; // 假定标准宽度 750px,分成 10 份
document.documentElement.style.fontSize = `${newSize}px`;
在 postcss-loader
的 plugins
中加入 px2rem({remUnit: 75})
表示一个单位 rem 等于 75px。
加入 react-router 4
sh
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>;
JS 控制跳转
js
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")
);
如果使用了路由:
jsx
class MainPage extends React.Component {
render() {
return (
<Provider store={store}>
<Router>
<div>
<Route exact path="/" component={HelloView} />
</div>
</Router>
</Provider>
);
}
}
快速点击修正
sh
yarn add react-fastclick
jsx
import initReactFastclick from "react-fastclick";
initReactFastclick();
打包后路径不是相对路径
在 package.json
中添加 "homepage": "./"
, 即可
打包时抽离公共 JS
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
}),
]
组件懒加载(针对大型项目)
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"));
实际开发中可以将大量的路由配置信息,按照模块化的方式进行拆分,跟路由只引入模块入口,内部页面配置在模块内部,模块内可以再切分二级模块,以此实现路由的拆分。