programmer-yang / blog

Blog
19 stars 0 forks source link

webpack前端代码优化之旅 #7

Open programmer-yang opened 6 years ago

programmer-yang commented 6 years ago

起因

最近接手了一个前端项目,由于之前前端开发人员比较多加上没有人很好的来约束管理,到我手上的时候已经变的比较恐怖,这里的恐怖主要指代码臃肿和体积庞大,随便改点东西,热加载都需要8秒左右的时间,在此基础上改需求已经异常难受,优化代码变的刻不容缓。

任务

简单列一下优化任务清单:

  1. 梳理第三方组件
  2. 使用DllPlugin优化开发环境
  3. 使用CommonsChunkPlugin优化生产环境

步骤 1

要完成这一步,我们要先分析一下当前代码的第三方组件使用情况,这里我推荐使用webpack-bundle-analyzer

yarn add webpack-bundle-analyzer

***.prod.js中添加

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
//...
plugins: [
  new BundleAnalyzerPlugin(),
]

然后运行编译命令,编译结束后本地会启一个服务并在浏览器中弹出一个页面,页面中就是当前编译后代码的组件使用情况,从中找出没用用且很大的组件,然后从代码中移除或注解

很多人在写代码的时候不会注意,就是只要你import的组件,不管是否使用,都会打包进去,切记开启no-unused-vars规则

这是个体力活儿,慢慢处理吧 当我完成这这一步的时候,我的项目已经从7mb的容量缩小到了3mb

步骤 2

我们代码已经比最开始清爽了很多,但我发现现在在开发的时候热加载还是4到5秒左右,还是不能忍受,所以我们现在要开始优化开发体验

webpack的组件dllplugin可以让你的热加载只编译业务部分,从而来大大提升热加载速度,这里我推荐使用autodll-webpack-plugin

yarn add autodll-webpack-plugin

然后在你的***.dev.js配置文件中加上

const AutoDllPlugin = require('autodll-webpack-plugin'); // dll
//...
plugins: [
  new AutoDllPlugin({
      inject: true, // will inject the DLL bundles to index.html
      filename: '[name].[hash].js',
      path: 'static/js',
      entry: {
        vendor: [
          'react',
          'react-dom',
          // 这里放步骤1中分析出来的比较大,但又必须使用的组件库
        ]
      }
    }),
]

完成这一步后这个项目的热加载速度已经降低到了3s以内,已经可以接受了

我的电脑年级比较大了,新电脑应该能到2s以内

步骤 3

我们来进行最后一步,优化此项目的线上表现 这里其实有几种思路,比如按需加载,但考虑到一些原因,这次的优化暂时不上按需,只是提取一下公共文件 这里我们要用到CommonsChunkPlugin***.prodj.js

//...
plugins: [
  new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: module => {
        return module.resource && /node_modules/.test(module.resource)
      }
    }),
]

这里的意思是把node_modules下的所有包都提取到公共文件中 现在的webpack已经没有"boilerplatemanifest 代码可能在每次编译时都会变化"的问题,所以不用单独提取

总结

通过这3步,我在很短的时间内解决了当下这个项目的几个痛点,但优化的路还很长,而且优化永远是补救措施,更关键的还是从源头解决问题,比如整体团队的能力提升,整体代码质量的把控,都是需要很多精力去搞的事情,让我们一起加油吧

参考

DllPlugin CommonsChunkPlugin autodll-webpack-plugin https://www.erichain.me/2017/07/11/2017-07-11-speeding-up-webpack-with-dllplugin/ https://github.com/creeperyang/blog/issues/37

programmer-yang commented 6 years ago

步骤 3 中出现一个比较奇怪的bug,最终分析是因为这个写法会把业务代码的样式全部提取出去,所以这里要手动排除一下

new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: module => {
        if(module.resource && (/^.*\.(css|less|scss)$/).test(module.resource)) {
          return false;
        }
        return module.resource && /node_modules/.test(module.resource)
      }
    }),
programmer-yang commented 6 years ago

再说两句 后续的工作中发现一些问题,分析其原因还是一些开发人员对create-react-appantd理解不是很好,也许还有其他人在使用过程中也会有同样的困惑,这里记录下来,以便能帮到其他人

关于引入antd

这里其实能说的不多,最核心的就是一个关于antd样式的引入需要注意一下 antd官方介绍:关于使用create-react-app来构建项目 这里的核心是使用react-app-rewired来覆盖原来的默认react-app 然后在配置文件里添加

config = injectBabelPlugin(['import', { libraryName: 'antd', libraryDirectory: 'es', style: 'css' }], config);

这里需要说一下的就是在使用了eject命令后的项目 可能很多人在这种情况下就直接使用.babelrc来解决问题,这样没问题,但不优雅

因为这样你会覆盖原有的关于babel的配置(babel应该是优先用户的配置文件的),这种情况下你还要自己安装babel-preset-es2015 babel-preset-stage-1等等,所以说不优雅

正确的方式应该是这样的:package.json

"babel": {
    "plugins": [
      ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
    ],
    "presets": [
      "react-app"
    ]
  },

这是官方提供的添加babel配置的入口

关于打包后的大小

这里其实要说的不多,记录一下初始大小以便以后查看吧

// react
119K  4 27 10:25 main.14d7adfe.js
// react antd (Button)
143K  4 27 10:50 main.b85f62e5.js
// react antd (Button Modal)
179K  4 27 10:51 main.9f51c035.js
// react antd (Button Modal) react-router
226K  4 27 10:56 main.20227069.js
dontdrinkmylemontea commented 5 years ago

写得很赞。博主怎么不继续更了