webpack打包优化的几个方法总结


Posted in Javascript onFebruary 10, 2020

为什么要优化打包?

  • 项目越做越大,依赖包越来越多,打包文件太大
  • 单页面应用首页白屏时间长,用户体验差

我们的目的

  • 减小打包后的文件大小
  • 首页按需引入文件
  • 优化 webpack 打包时间

优化方式

1、 按需加载

1.1 路由组件按需加载

const router = [
 {
  path: '/index',
  component: resolve => require.ensure([], () => resolve(require('@/components/index')))
 },
 {
  path: '/about',
  component: resolve => require.ensure([], () => resolve(require('@/components/about')))
 }
]

1.2 第三方组件和插件。按需加载需引入第三方组件

// 引入全部组件
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)

// 按需引入组件
import { Button } from 'element-ui'
Vue.component(Button.name, Button)

1.3 对于一些插件,如果只是在个别组件中用的到,也可以不要在 main.js 里面引入,而是在组件中按需引入

// 在main.js引入
import Vue from vue
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)

// 按组件按需引入
import { Vuelidate } from 'vuelidate'

2、优化 loader 配置

  • 优化正则匹配
  • 通过 cacheDirectory 选项开启缓存
  • 通过 include、exclude 来减少被处理的文件。
module: {
 rules: [
  {
   test: /\.js$/,
   loader: 'babel-loader?cacheDirectory',
   include: [resolve('src')]
  }
 ]
}

3、优化文件路径——省下搜索文件的时间

  • extension 配置之后可以不用在 require 或是 import 的时候加文件扩展名,会依次尝试添加扩展名进行匹配。
  • mainFiles 配置后不用加入文件名,会依次尝试添加的文件名进行匹配
  • alias 通过配置别名可以加快 webpack 查找模块的速度。
resolve: {
  extensions: ['.js', '.vue', '.json'],
  alias: {
   'vue$': 'vue/dist/vue.esm.js',
   '@': resolve('src'),
  }
 },

4、生产环境关闭 sourceMap

  • sourceMap 本质上是一种映射关系,打包出来的 js 文件中的代码可以映射到代码文件的具体位置,这种映射关系会帮助我们直接找到在源代码中的错误。
  • 打包速度减慢,生产文件变大,所以开发环境使用 sourceMap,生产环境则关闭。

5、代码压缩

  • UglifyJS: vue-cli 默认使用的压缩代码方式,它使用的是单线程压缩代码,打包时间较慢
  • ParallelUglifyPlugin: 开启多个子进程,把对多个文件压缩的工作分别给多个子进程去完成

两种方法使用如下:

plugins: [
 new UglifyJsPlugin({
  uglifyOptions: {
   compress: {
    warnings: false
   }
  },
  sourceMap: true,
  parallel: true
 }),

 new ParallelUglifyPlugin({
  //缓存压缩后的结果,下次遇到一样的输入时直接从缓存中获取压缩后的结果并返回,
  //cacheDir 用于配置缓存存放的目录路径。
  cacheDir: '.cache/',
  sourceMap: true,
  uglifyJS: {
   output: {
    comments: false
   },
   compress: {
    warnings: false
   }
  }
 })
]

6、提取公共代码

  • 相同资源重复被加载,浪费用户流量,增加服务器成本。
  • 每个页面需要加载的资源太大,导致网页首屏加载缓慢,影响用户体验。

webpack3 使用 CommonsChunkPlugin 的实现:

plugins: [
 new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  minChunks: function(module, count) {
   console.log(module.resource, `引用次数${count}`)
   //"有正在处理文件" + "这个文件是 .js 后缀" + "这个文件是在 node_modules 中"
   return module.resource && /\.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, './node_modules')) === 0
  }
 }),
 new webpack.optimize.CommonsChunkPlugin({
  name: 'common',
  chunks: 'initial',
  minChunks: 2
 })
]

webpack4 使用 splitChunks 的实现:

module.exports = {
 optimization: {
  splitChunks: {
   cacheGroups: {
    vendor: {
     priority: 1, //添加权重
     test: /node_modules/, //把这个目录下符合下面几个条件的库抽离出来
     chunks: 'initial', //刚开始就要抽离
     minChunks: 2 //重复2次使用的时候需要抽离出来
    },
    common: {
     //公共的模块
     chunks: 'initial',
     minChunks: 2
    }
   }
  }
 }
}

7、CDN 优化

  1. 随着项目越做越大,依赖的第三方 npm 包越来越多,构建之后的文件也会越来越大。
  2. 再加上又是单页应用,这就会导致在网速较慢或者服务器带宽有限的情况出现长时间的白屏。

1、将 vue、vue-router、vuex、element-ui 和 axios 这五个库,全部改为通过 CDN 链接获取,在 index.html 里插入 相应链接。

<head>
 <link rel="stylesheet" href="https://cdn.bootcss.com/element-ui/2.0.7/theme-chalk/index.css" rel="external nofollow" />
</head>
<body>
 <div id="app"></div>
 <script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
 <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
 <script src="https://cdn.bootcss.com/vuex/3.1.0/vuex.min.js"></script>
 <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js"></script>
 <script src="https://cdn.bootcss.com/element-ui/2.6.1/index.js"></script>
 <!-- built files will be auto injected -->
</body>

2、在 webpack.config.js 配置文件

module.exports = {
 ···
  externals: {
   'vue': 'Vue',
   'vuex': 'Vuex',
   'vue-router': 'VueRouter',
   'element-ui': 'ELEMENT',
   'Axios':'axios'
  }
 },

3、卸载依赖的 npm 包,npm uninstall axios element-ui vue vue-router vuex

4、修改 main.js 文件里之前的引包方式

// import Vue from 'vue'
// import ElementUI from 'element-ui'
// import 'element-ui/lib/theme-chalk/index.css'
// import VueRouter from 'vue-router'

import App from './App.vue'
import routes from './router'
import utils from './utils/Utils'

Vue.use(ELEMENT)
Vue.use(VueRouter)

const router = new VueRouter({
 mode: 'hash', //路由的模式
 routes
})

new Vue({
 router,
 el: '#app',
 render: h => h(App)
})

8、使用 HappyPack 多进程解析和处理文件

  • 由于运行在 Node.js 之上的 Webpack 是单线程模型的,所以 Webpack 需要处理的事情需要一件一件的做,不能多件事一起做。
  • HappyPack 就能让 Webpack 把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。
  • HappyPack 对 file-loader、url-loader 支持的不友好,所以不建议对该 loader 使用。

使用方法如下:

1、HappyPack 插件安装: npm i -D happypack
2、webpack.base.conf.js 文件对 module.rules 进行配置

module: {
 rules: [
  {
   test: /\.js$/,
   use: ['happypack/loader?id=babel'],
   include: [resolve('src'), resolve('test')],
   exclude: path.resolve(__dirname, 'node_modules')
  },
  {
   test: /\.vue$/,
   use: ['happypack/loader?id=vue']
  }
 ]
}

3、在生产环境 webpack.prod.conf.js 文件进行配置

const HappyPack = require('happypack')
// 构造出共享进程池,在进程池中包含5个子进程
const HappyPackThreadPool = HappyPack.ThreadPool({ size: 5 })
plugins: [
 new HappyPack({
  // 用唯一的标识符id,来代表当前的HappyPack是用来处理一类特定的文件
  id: 'babel',
  // 如何处理.js文件,用法和Loader配置中一样
  loaders: ['babel-loader?cacheDirectory'],
  threadPool: HappyPackThreadPool
 }),
 new HappyPack({
  id: 'vue', // 用唯一的标识符id,来代表当前的HappyPack是用来处理一类特定的文件
  loaders: [
   {
    loader: 'vue-loader',
    options: vueLoaderConfig
   }
  ],
  threadPool: HappyPackThreadPool
 })
]

总结

  • 比较实用的方法: 按需加载,优化loader配置,关闭生产环境的sourceMap,CDN优化。
  • vue-cli已做的优化: 代码压缩,提取公共代码,再优化空间不大。
  • 根据项目实际需要和自身开发水平选择优化方法,必须避免因为优化产生bug。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
兼容FireFox 的 js 日历 支持时间的获取
Mar 04 Javascript
javascript alert乱码的解决方法
Nov 05 Javascript
使用jquery组件qrcode生成二维码及应用指南
Feb 22 Javascript
JavaScript运算符小结
Jun 03 Javascript
Bootstrap导航栏各元素操作方法(表单、按钮、文本)
Dec 28 Javascript
jquery获取点击控件的绝对位置简单实例
Oct 13 Javascript
vuejs开发组件分享之H5图片上传、压缩及拍照旋转的问题处理
Mar 06 Javascript
Vue.js基础学习之class与样式绑定
Mar 20 Javascript
webpack学习笔记之优化缓存、合并、懒加载
Aug 24 Javascript
响应式框架Bootstrap栅格系统的实例
Dec 19 Javascript
Node.js应用设置安全的沙箱环境
Apr 23 Javascript
angularJs提交文本框数据到后台的方法
Oct 08 Javascript
JS+HTML5本地存储Localstorage实现注册登录及验证功能示例
Feb 10 #Javascript
node.js制作一个简单的登录拦截器
Feb 10 #Javascript
使用 Vue-TCB 快速在 Vue 应用中接入云开发的方法
Feb 10 #Javascript
jQuery实现简易QQ聊天框
Feb 10 #jQuery
解决vue-cli@3.xx安装不成功的问题及搭建ts-vue项目
Feb 09 #Javascript
Vue中import from的来源及省略后缀与加载文件夹问题
Feb 09 #Javascript
如何基于javascript实现贪吃蛇游戏
Feb 09 #Javascript
You might like
PHP安装扩展mcrypt以及相关依赖项深入讲解
2021/03/04 PHP
PHP7 其他修改
2021/03/09 PHP
Auntion-TableSort国人写的一个javascript表格排序的东西
2007/11/12 Javascript
jQuery 拖动层(在可视区域范围内)
2012/05/24 Javascript
讨论html与javascript在浏览器中的加载顺序问题
2013/11/27 Javascript
浅谈javascript中的DOM方法
2015/07/16 Javascript
JavaScript的React框架中的JSX语法学习入门教程
2016/03/05 Javascript
微信小程序 wxapp地图 map详解
2016/10/31 Javascript
JavaScript利用正则表达式替换字符串中的内容
2016/12/12 Javascript
AngularJS表格样式简单设置方法示例
2017/03/03 Javascript
关于Angular2 + node接口调试的解决方案
2017/05/28 Javascript
详解使用Vue Router导航钩子与Vuex来实现后退状态保存
2017/09/11 Javascript
vue.js数据绑定操作详解
2018/04/23 Javascript
灵活使用console让js调试更简单的方法步骤
2019/04/23 Javascript
快速对接payjq的个人微信支付接口过程解析
2019/08/15 Javascript
微信小程序如何获取用户头像和昵称
2019/09/23 Javascript
jquery+ajax实现异步上传文件显示进度条
2020/08/17 jQuery
vue axios请求成功却进入catch的原因分析
2020/09/08 Javascript
[59:07]海涛为你详解DOTA2新版本“贤哲秘契”
2014/11/22 DOTA
在matplotlib的图中设置中文标签的方法
2018/12/13 Python
keras CNN卷积核可视化,热度图教程
2020/06/22 Python
如何表示python中的相对路径
2020/07/08 Python
关于python3.9安装wordcloud出错的问题及解决办法
2020/11/02 Python
Tarte Cosmetics官网:美国最受欢迎的化妆品公司之一
2017/08/24 全球购物
意大利时尚精品店:Nugnes 1920
2020/02/10 全球购物
世界上最大的铁人三项商店:Tri UK
2020/11/04 全球购物
环境工程专业自荐信
2014/03/03 职场文书
优秀的应届生自荐信
2014/05/23 职场文书
大学生村官考核材料
2014/05/23 职场文书
学生实习证明模板汇总
2014/09/25 职场文书
群众路线四风问题整改措施
2014/09/27 职场文书
golang 如何用反射reflect操作结构体
2021/04/28 Golang
如何理解及使用Python闭包
2021/06/01 Python
分析并发编程之LongAdder原理
2021/06/29 Java/Android
python​格式化字符串
2022/04/20 Python
Go本地测试解耦任务拆解及沟通详解Go本地测试的思路沟通的重要性总结
2022/06/21 Golang