Webpack|Webpack 3 - 打包优化

随着项目复杂程度的增加,代码打包的耗时也越来越长,于是我想结合实际开发环境提升一下首次打包的速度。
目前项目中使用的打包压缩工具是webpack默认的UglifyJS插件,它使用的是单线程压缩代码,也就是说当多个js文件需要被压缩时,它需要将文件一个一个进行压缩。因此在正式环境中打包压缩代码就显得非常慢。最后使用一下几种方法来优化项目文件(基于webpack3)。
1、使用HappyPack多进程解析和处理文件
  • 由于有大量文件需要解析和处理,所以构建是文件读写和计算密集型的操作,特别是当文件数量变多后,Webpack构建慢的问题会显得更为严重。运行在 Node.之上的Webpack是单线程模型的,也就是说Webpack需要一个一个地处理任务,不能同时处理多个任务。Happy Pack ( https://github.com/amireh/happypack )就能让Webpack做到这一点,它将任务分解给多个子进程去并发执行,子进程处理完后再将结果发送给主进程。
1)HappyPack插件安装: $ npm install -D happypack 2)对文件webpack.base.conf.js 引入 const HappyPack = require('happypack'); const os = require('os'); const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length }); plugins: [ new HappyPack({ // 用id,来代表当前的HappyPack是用来处理一类特定的文件 id: 'babel', // 如何处理.js文件,用法和Loader配置中一样 loaders: [{ path: 'babel-loader', cache: true, }], // include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')], threadPool: HappyPackThreadPool, }),new HappyPack({ // 用id,来代表当前的HappyPack是用来处理一类特定的文件 id: 'vue', loaders: [ { loader: 'vue-loader', options: vueLoaderConfig } ], threadPool: HappyPackThreadPool, }), ], module: { rules: [ { test: /\.js$/, // 将对.js 文件的处理转交给 id 为 babel 的HappyPack实例 use: ['happypack/loader?id=babel'], include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')], // 排除第三方插件 exclude: path.resolve(__dirname, 'node_modules'), }, { test: /\.vue$/, use: ['happypack/loader?id=vue'], }, ] },

【Webpack|Webpack 3 - 打包优化】2、使用cdn优化依赖包的体积
  • 日常开发过程中,前端这块早就已经开始进行工程化和组件化开发了,所以免不了下载各种node包,使得打包后的体积也是非常的庞大,下面使用webpack的一个配置外部扩展就可以解决这类问题
1)在index.html中引入cdn,可以使用国内的bootcdn服务2) 在webpack.base.conf.js 配置externals,externals与output同级,属性是包暴露出的方法名称,后面的值是你在项目中使用的名称 externals: { 'vue': 'Vue', 'vue-router': 'VueRouter', 'vuex': 'Vuex', 'element-ui': 'ELEMENT', 'axios': 'axios', }, 3)在router.js配置,把Vue注释或者删除 // import Vue from 'vue'; import VueRouter from 'vue-router'; import index from 'views/index'; // Vue.use(Router); 4)在main.js注释掉引用的element,可以使用按需引入element // 按需引入 import { Loading, Message, MessageBox, Notification, } from 'element-ui' // 按需使用 Vue.use(Loading.directive) // 挂载到vue实例上面 Vue.prototype.$loading = Loading.service Vue.prototype.$msgbox = MessageBox Vue.prototype.$confirm = MessageBox.confirm Vue.prototype.$alert = MessageBox.alert Vue.prototype.$prompt = MessageBox.prompt Vue.prototype.$message = Message Vue.prototype.$notify = Notification,

3、使用ParallelUglifyPlugin多进程压缩代码文件
// 在webpack.prod.conf.js文件配置 // ParallelUglifyPlugin插件安装: $ npm i -D webpack-parallel-uglify-plugin const ParallelUglifyPlugin =require('webpack-parallel-uglify-plugin'); plugins: [ new ParallelUglifyPlugin({ cacheDir: '.cache/', uglifyJs:{ compress: { warnings: false, drop_debugger: true, drop_console:true,// 打包移除console pure_funcs: ['console.log'] }, sourceMap: config.build.productionSourceMap, } }), ]

4、Gzip压缩和sourceMap优化
// 在webpack的build文件中,开启Gzip压缩功能和禁用资源地图。打包以后就不会再有sourceMap文件了,也会多了几个以.js.gz后缀名的文件 module.exports = { // ... build: { productionSourceMap: false, productionGzip: true, } }

5、路由异步加载 可以帮助我们根据路由来按需加载。它的原理是使用了import() 而非 import 是因为 import 是静态编译,而import() 同 require,是可以进行动态加载的。 但是千万要注意的是,引用过程中千万不要使用变量,这会导致编译通过但是编译时间长得令人发指又或者直接内存溢出。
// 使用require方法 const example = resolve => require(['../components/index.vue'], resolve);

优化效果
打包时间
  • 打包前

    Webpack|Webpack 3 - 打包优化
    文章图片
  • 打包后

    Webpack|Webpack 3 - 打包优化
    文章图片
打包体积
  • 打包前

    Webpack|Webpack 3 - 打包优化
    文章图片
  • 打包后

    Webpack|Webpack 3 - 打包优化
    文章图片
到此 进行了部分的webpack优化,剩下的问题,都是根据个人需求来处理。因为是基于webpack3进行优化,有些功能没有实现。原本设想是升级到 webpack4 的,过程不算太顺利,过多的依赖升级错误只能放弃,但是升级到 webpack4,尝试一下说不定就成功,毕竟 webpack4 进行了多处优化,一些存在安全问题的依赖包也得到解决了,后期会升级到webpack4的。最后还需要提醒大家一点,本篇文章中的例子仅供参考学习,切误将本篇文章中的代码直接使用在正式项目当中。希望以上代码对大家有所帮助。

    推荐阅读