csm0 2019-07-01
虽然在工作中用react+antd写页面写了一年,但从来没自己去认认真真配置一个webpack,去分析去优化自己打出的包。在工程化成熟或者大点的公司,都有自己的打包工具,所以自己工作中很少去琢磨这些。为了试一下写出的组件库(antd-doddle)性能,就尝试自己去写一个webpack构建,真的是吓了自己一跳,流水账(tu)开始。
打包工具:webpack4 + babel6
开始前,大概说一下项目内容。项目基于react+react-router+antd+antd-doddle,自己日常在这个项目做一些技术验证与demo,就4个页面。组成如下:
<Content style={{ margin: '24px 16px', padding: 24, background: '#fff', minHeight: 280 }}> <Switch> <Route exact path={menus.home.path} component={Home} /> <Route exact path={menus.renderProps.path} component={ExampleTable} /> <Route exact path={menus.hoc.path} component={Hoc} /> <Route exact path={menus.learnTest.path} component={LearnTest} /> </Switch> </Content>
页面js与公共(node_modules引用)js使用splitChunks分开打包。npm run dev,结果如下图,async.bundle.js大小24M,有点惊人的大。
打包工具:webpack4 + babel7
由于webpack在(mode)模式development与production还是有很大区别,当我直接将mode从development变成production,再运行npm start。打包大小还是有明显的变化,同时也报了三个警告,包体积大于244kb
打包大小从24M缩减到17M,由于run start是启用的webpack-dev-server来构建的,所以对应的production模式默认启用UglifyJsPlugin是无效的,但是可以手动去加入这段配置,然后打包大小能看到直线下降到3.25M,见下图
optimization: { minimizer: [ new UglifyJsPlugin() ], splitChunks: { name: 'async', minSize: 30000, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, chunks: 'all' }, } } }
以上其实都是在用webpack-dev-server构建,当用webpack去构建时,然后npm run build,结果是这样的:
压缩后大小已经减小到2.6M,还是有实质的进步,然后通过BundleAnalyzerPlugin这个插件看包的构成,会发现antd,antd-doddle,moment占了绝大多数的空间。
恰好我知道moment虽然不支持按需打包,由于支持了多语言,所以省去无用的语言选项,就可以有明显的优化,所以使用ContextReplacementPlugin这个插件,并加上只匹配中文的筛选,如下所示:
new webpack.ContextReplacementPlugin( /moment[/\\]locale$/, /zh-cn/, )
打包体积由2.6减少到2.3M。
当一个一个浏览完包的构成时,大小组成是这样的:
我留下了一些疑问:
为了减少大小,我还使用了babel-plugin-import插件,但没有实质性的改变,然后看到包的路径是es,说明现有的构建本来就已经做了tree-shaking,所以这确实是无用功。但公司项目和网上大多数文章提到的,都是打包都能优化到1M左右,所以应该还有优化的空间。后面我干了什么呢?
打包工具:webpack4 + babel7
babel6升到babel7,修改一下配置。然后再运行npm run build, 结果如下:
当一个一个浏览完包的构成时,大小组成是这样的:
不能说是奇迹,但确实解决了一些上面留下的疑问:moment,immutable重复打包;draft无端引入;antd与antd-doddle包数激增。大小也减少了至少1M,所以升级才是自然界应有的规律,更不要说前端。
看到这种优化的效果真的让我惊喜与惊讶,但究竟是什么带来了这种变化更让我更好奇。还没抓到核心的区别,有清楚的,请指点一下,怎么避免js公共函数的重复注入,怎么来优化编译来完美对接后面webpack打包的?想往外去看看大神们都什么意见,可特殊时期,我的梯子被折断了(衰)。
文章提到的项目地址:webpack打包,master分支是对应babel6,roadhg分支是对应babel7