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 相关文章推荐
srcElement表格样式
Sep 03 Javascript
根据一段代码浅谈Javascript闭包
Dec 14 Javascript
jquery动态调整div大小使其宽度始终为浏览器宽度
Jun 06 Javascript
bootstrap table 服务器端分页例子分享
Feb 10 Javascript
基于jQuery实现表格的查看修改删除
Aug 01 Javascript
js中小数向上取整数,向下取整数,四舍五入取整数的实现(必看篇)
Feb 13 Javascript
angularjs实现猜数字大小功能
May 20 Javascript
JavaScript模板引擎实现原理实例详解
Dec 14 Javascript
JavaScript数组特性与实践应用深入详解
Dec 30 Javascript
微信小程序实用代码段(收藏版)
Dec 17 Javascript
纯JS开发baguetteBox.js响应式画廊插件
Jun 28 Javascript
基于JavaScript实现省市联动效果
Jun 22 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 和 XML: 使用expat函数(二)
2006/10/09 PHP
php中几种常见安全设置详解
2010/04/06 PHP
php短址转换实现方法
2015/02/25 PHP
PHP连接MySQL数据的操作要点
2015/03/20 PHP
Mootools 1.2教程 事件处理
2009/09/15 Javascript
jQuery中的val()示例应用
2014/02/26 Javascript
JavaScript中String.prototype用法实例
2015/05/20 Javascript
谈谈JavaScript中function多重理解
2015/08/28 Javascript
javascript经典特效分享 手风琴、轮播图、图片滑动
2016/09/14 Javascript
微信小程序 form组件详解
2016/10/25 Javascript
JQuery学习总结【二】
2016/12/01 Javascript
Javascript中 带名 匿名 箭头函数的重要区别(推荐)
2017/01/29 Javascript
canvas实现图像放大镜
2017/02/06 Javascript
Vue动态实现评分效果
2017/05/24 Javascript
JavaScript实现无刷新上传预览图片功能
2017/08/02 Javascript
javascript+jQuery实现360开机时间显示效果
2017/11/03 jQuery
Vue2 模板template的四种写法总结
2018/02/23 Javascript
微信小程序实现多行文字超出部分省略号显示功能
2019/10/23 Javascript
vue.js的简单自动求和计算实例
2019/11/08 Javascript
解决vue 子组件修改父组件传来的props值报错问题
2019/11/09 Javascript
AngularJs的$http发送POST请求,php无法接收Post的数据问题及解决方案
2020/08/13 Javascript
获取Django项目的全部url方法详解
2017/10/26 Python
python3利用Dlib19.7实现人脸68个特征点标定
2018/02/26 Python
在NumPy中创建空数组/矩阵的方法
2018/06/15 Python
基于logstash实现日志文件同步elasticsearch
2020/08/06 Python
关于python scrapy中添加cookie踩坑记录
2020/11/17 Python
咖啡为什么会有酸味?你喝到的咖啡為什麼是酸的?
2021/03/17 冲泡冲煮
一个基于canvas的移动端图片编辑器的实现
2020/10/28 HTML / CSS
戴尔荷兰官方网站:Dell荷兰
2020/10/04 全球购物
求职者怎样写自荐信
2014/04/13 职场文书
大学英语专业求职信
2014/06/21 职场文书
2014年污水处理厂工作总结
2014/12/19 职场文书
一年级小学生评语大全
2014/12/25 职场文书
小学体育教学随笔
2015/08/14 职场文书
pyqt5蒙版遮罩mask,setmask的使用
2021/06/11 Python
CPU不支持Windows11系统怎么办
2021/11/21 数码科技