我作 react 开发时一般是直接用的 create-react-app。最近想分析一下一个用 create-react-app 开发的项目的打包结果,看看有没有什么能够优化的地方。html
执行 npm run eject
导出配置(单向操做,不可逆)。
项目中使用的一些库:react
"dependencies": { "antd": "^3.9.2", "axios": "^0.18.0", "echarts": "^3.8.5", "less": "^3.0.1", "moment": "^2.21.0", "react": "^16.4.2", "react-dom": "^16.2.0", "react-router-dom": "^4.2.2", }, "devDependencies": { "babel-loader": "7.1.2", "babel-plugin-import": "^1.6.5", "webpack": "3.8.1", "webpack-bundle-analyzer": "3.0.2", }
按照官网配置,使用 babel-plugin-import,在 package.json 中配置:webpack
"babel": { "plugins": [ [ "import", { "libraryName": "antd", "style": true } ] ] }
项目中直接使用:ios
import { Button } from 'antd';
create-react-app 的 webpack 已经作好配置了:git
plugins: [ ... // Moment.js is an extremely popular library that bundles large locale files // by default due to how Webpack interprets its code. This is a practical // solution that requires the user to opt into importing specific locales. // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack // You can remove this if you don't use Moment.js: new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), ... ]
import React from 'react'; export default class Bundle extends React.Component { state = { mod: null } componentWillMount() { this.load(this.props); } componentWillReceiveProps(nextProps) { if (nextProps.load !== this.props.load) { this.load(nextProps); } } async load(props) { this.setState({ mod: null }); /* 使用 props.load() 返回的是一个 promise */ const mod = await props.load(); this.setState({ mod: mod.default ? mod.default : mod }); } render() { return this.state.mod ? this.props.children(this.state.mod) : null; } }
const lazyLoad = loadComponent => props => ( <Bundle load={loadComponent}> {Comp => (Comp ? <Comp {...props} /> : <Loading/>)} </Bundle> );
使用:github
// dynamic import const Demo = lazyLoad(() => import('../components/demo')); // react-router <Route path="/demo" component={Demo} />
使用工具webpack-bundle-analyzer,将打包内容转换成可缩放的树状图。web
// 安装 yarn add -D webpack-bundle-analyzer
在 config/webpack.config.dev.js
或 config/webpack.config.prod.js
中添加:npm
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; ... plugins: [ ... new BundleAnalyzerPlugin(), ... ] ...
默认在 127.0.0.1:8888
页面显示。
添加在 config/webpack.config.dev.js
后,每次 npm start
时都会弹出分析页面。
添加在 config/webpack.config.prod.js
后,每次 npm build
时都会弹出分析页面。
项目分析结果:json
发现问题:axios
因为我对 webpack 不算太熟,知道 webpack 3 中能够用 plugin CommonsChunkPlugin
抽取公共代码,但具体用法不甚明了,折腾了好久都没有做用,终于在 antd github 的 issues 中找到答案:
plugins: [ ... new webpack.optimize.CommonsChunkPlugin({ minChunks: 2, minSize: 0, children: true, deepChildren: true, async: true }), ... ]
彷佛去掉 name
就能够了?这一点我还没搞清楚是为何。
import echarts from 'echarts/lib/echarts'; import 'echarts/lib/chart/map'; import 'echarts/lib/chart/pie'; import 'echarts/lib/chart/scatter'; import 'echarts/lib/chart/effectScatter'; import 'echarts/lib/component/geo'; import 'echarts/lib/component/tooltip'; import chinaJson from 'echarts/map/json/china.json'; ... echarts.registerMap('china', chinaJson); ...
须要注意,能够按需引入的模块列表见 https://github.com/ecomfe/ech...