当前位置:首页 > 技术分析 > 正文内容

11个你必须知道的webpack打包优化的方法

ruisui883个月前 (01-26)技术分析32

大家在开发前端项目的时候,随着项目的不断更新迭代以及产品经理的不断提需求,势必会用到各种各样的第三方库,那么我们用到的第三方库越来越多,整体项目的依赖也就会越来越多,整体项目打包的时候体积也就会越来越大,用webpack去build的时候时间也会越长。

这些倒不是最主要的,我们做的一般都是单页面应用,如果随着第三方库越来越多,咱们项目首页的白屏时间也会加长,用户体验感会很差,这是我们不得不面对的一个问题,所以我们要优化webpack的打包方法,具体如何做呢?咱们接着往下看。

一、webpack-bundle-analyzer的使用

webpack-bundle-analyzer是一个工具,它能够将webpack打包后的内容进行扫码并形成一个可视化的界面,在这个界面中我们可以看到打包后项目的依赖项,我们可以从中找到一些我们项目中并不需要的依赖包或者体积较大的依赖包来进行针对性的优化。 以下我们针对Vue框架来进行叙述。

1. vue-cli2

如果你用的是vue脚手架2版本,那么恭喜你,它已经集成了webpack-bundle-analyzer,你只需运行npm run build --report这个命令,就可以看到如下界面。

从上面的图我们可以知道打包的内容有哪些,以及它们的大小,还有各个依赖包的耗时以及总的耗时是多久。

2. vue-cli3

如果你用的是vue脚手架3版本,那你还需要进行如下配置:

首先需要下载依赖:

npm install webpack-bundle-analyzer -D

然后配置webpack.config.js 文件:

const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

plugins:[

new BundleAnalyzerPlugin(),

]

二、进行优化

知道了webpack-bundle-analyzer这个插件给我们带来哪些信息后,我们就可以有针对性的进行优化了,具体如何优化呢?我们从以下几个方面来进行

1. 按需加载

单页面应用是将整个工程作为一个入口打包成一个模块,所以在首页会加载一些没用到的资源,造成首页渲染速度慢,“白屏时间”过长,给用户不好的体验。我们可以从以下几个方面进行按需加载:

  • 路由组件按需加载

const router = [

{

path: '/index',

component: resolve => require.ensure([], () => resolve(require('@/components/index')))

},

{

path: '/login',

component: resolve => require.ensure([], () => resolve(require('@/components/login')))

}

]

  • 按需加载需引入第三方组件或插件

// 引入全部组件

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)

  • 如果只是在个别组件中用到的插件,可以不用在main.js里面引入,而是在组件中按需引入

// 在main.js引入

import Vue from vue

import Vuelidate from 'vuelidate'

Vue.use(Vuelidate)

// 在组件中按需引入

import { Vuelidate } from 'vuelidate'

2. 优化loader的配置

我们可以从如下几个方面对loader进行优化:

  • 优化正则匹配——减少文件查询时间
  • 通过cacheDirectory选项开启缓存——减少再次打包时间
  • 通过 include、exclude 来减少被处理的文件。

module: {

rules: [

{

test: /\.js$/,

loader: 'babel-loader?cacheDirectory',

include: [resolve('src')]

}

]

}

3. 优化文件路径

优化文件路径可以省下搜索文件的时间,这里有两个属性:

  • extension

配置该属性之后可以不用在 require 或是 import 的时候加文件扩展名,会依次尝试添加扩展名进行匹配。

  • alias

通过配置别名可以加快 webpack 查找模块的速度。

resolve: {

extensions: ['.js', '.vue', '.json'],

alias: {

'@': resolve('src'),

}

},

4. 利用IgnorePlugin,避免引入无用模块

比如有些库包含多个国家的语言包(moment.js),我们只需要中文包或者英文报,所以我们需要避免引入不需要的语言包。

plugins:[

//忽略moment下的/locale目录,再手动import locale内部我们需要使用到的语言包

new webpack.IgnorePlugin(/\.\/local/,/moment/)

]

5. 利用noParse,避免重复模块化解析

代码中如果有xx.min.js之类的文件,基本已经采用模块化处理过的,无需在对类似文件进行递归解析处理,会引入进项目

module: {

noParse: [/xx\.min\.js$/]

}

6. happyPack 多进程打包

在整个 Webpack 构建流程中,最耗时的流程可能就是 Loader 对文件的转换操作了,因为要转换的文件数据巨多,而且这些转换操作都只能一个个挨着处理。HappyPack 的核心原理就是把这部分任务分解到多个进程去并行处理,从而减少了总的构建时间。

rules: [

{

test: /\.js$/,

//把对.js文件的处理转交给id为babel的HappyPack实例

use: ['happypack/loader?id=babel'],

include: srcPath

}

],

plugins: [

new HappyPack({

//用唯一的标识符id来代表当前的HappyPack是用来处理一类特定的文件

id: 'babel',

//如何处理.js文件,用法和loader配置中一样

loaders: ['babel-loader?cacheDirectory']

})

]

7. 热更新

相信大家对热更新肯定不陌生,即改完代码,浏览器无需刷新,新代码生效,状态保留。

entry: {

index: [

'webpack-dev-server/client?http://localhost:8080/',

'webpack/hot/dev-server',

path.join(srcPath, 'index.js')

],

other: path.join(srcPath, 'other.js')

}

plugins: [

new HotModuleReplacementPlugin()

]

devServer: {

xxx: 'xx'

hot: true //开启热更新

}

配置完后,修改样式,热更新生效了,但修改js,热更新没有生效,接下来还需要在js中设置允许热更新监听的模块。

if(module.hot){

module.hot.accept(['xxx文件名'], () => {

//在注册了热更新的js文件修改后,才会进行热更新

})

}

8. 生产环境关闭 sourceMap

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

9. 代码压缩

uglifyJsPlugin 是 vue-cli 默认使用的压缩代码方式,用来对js文件进行压缩,从而减小js文件的大小,加速load速度。它使用的是单线程压缩代码,打包时间较慢,所以可以在开发环境将其关闭,生产环境部署时再把它打开。

plugins: [

new UglifyJsPlugin({

uglifyOptions: {

compress: {

warnings: false

}

},

sourceMap: true,

parallel: true

})

]

我们还可以使用ParallelUglifyPlugin 开启多个子进程,把对多个文件压缩的工作分别给多个子进程去完成,每个子进程其实还是通过 UglifyJS 去压缩代码,但是变成了并行执行。

ParallelUglifyPlugin 还可以缓存压缩后的结果,下次遇到一样的输入时直接从缓存中获取压缩后的结果并返回。

plugins: [

new ParallelUglifyPlugin({

//cacheDir 用于配置缓存存放的目录路径。

cacheDir: '.cache/',

sourceMap: true,

uglifyJS: {

output: {

comments: false

},

compress: {

warnings: false

}

}

})

]

10. DllPlugin

这是在一个额外的独立的 webpack 设置中创建一个只有 dll 的 bundle(dll-only-bundle)。这个插件会生成一个名为 manifest.json 的文件,这个文件是用来让 DLLReferencePlugin 映射到相关的依赖上去的。使用步骤如下:

在build下创建 webpack.dll.config.js

const path = require('path')

const webpack = require('webpack')

module.exports = {

entry: {

vendor: [

'vue-router',

'vuex',

'vue/dist/vue.common.js',

'vue/dist/vue.js',

'vue-loader/lib/component-normalizer.js',

'vue',

'axios',

'echarts'

]

},

output: {

path: path.resolve('./dist'),

filename: '[name].dll.js',

library: '[name]_library'

},

plugins: [

new webpack.DllPlugin({

path: path.resolve('./dist', '[name]-manifest.json'),

name: '[name]_library'

}),

// 建议加上代码压缩插件,否则dll包会比较大。

new webpack.optimize.UglifyJsPlugin({

compress: {

warnings: false

}

})

]

}

在 webpack.prod.conf.js 的 plugin 后面加入配置

new webpack.DllReferencePlugin({

manifest: require('../dist/vendor-manifest.json')

})

package.json文件中添加快捷命令(build:dll)

"scripts": {

"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",

"start": "npm run dev",

"lint": "eslint --ext .js,.vue src",

"build": "node build/build.js",

"build:dll": "webpack --config build/webpack.dll.conf.js"

}

生产环境打包的时候先npm run build:dll命令会在打包目录下生成 vendor-manifest.json 文件与 vendor.dll.js 文件。然后npm run build生产其他文件。

根目录下的入口index.html加入引用

<script type="text/javascript" src="./vendor.dll.js"></script>

11. CDN优化

CDN 的全称是 Content Delivery Network,即内容分发网络。CDN 是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN 的关键技术主要有内容存储和分发技术。

随着项目越做越大,依赖的第三方 npm 包越来越多,构建之后的文件也会越来越大。再加上又是单页应用,这就会导致在网速较慢或者服务器带宽有限的情况出现长时间的白屏。此时我们可以使用CDN的方法,优化网络加载速度。

将 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" />

</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>

在 webpack.config.js 配置文件

module.exports = {

···

externals: {

'vue': 'Vue',

'vuex': 'Vuex',

'vue-router': 'VueRouter',

'element-ui': 'ELEMENT',

'Axios':'axios'

}

},

卸载依赖的 npm 包

npm uninstall axios element-ui vue vue-router vuex

修改 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)

})

总结

大致我们需要优化的地方就这么多,那么咱们来总结一下这些方法:

  • 如果说单论实用的话,这些方法是可行的:按需加载,优化 loader 配置,关闭生产环境的 sourceMap,CDN 优化。
  • 脚手架已经帮我们做的优化是代码压缩,我们也可以根据自身需要进行相关配置优化。
  • 不论是哪些优化,都应该以不影响业务代码为前提。
    至此,webpack的打包优化就结束了,相信认真阅读的你一定有所收获。

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/561.html

标签: 卸载npm包
分享给朋友:

“11个你必须知道的webpack打包优化的方法” 的相关文章

「2022」打算跳槽涨薪,必问面试题及答案——VUE篇

1、为什么选择VUE,解决了什么问题?vue.js 正如官网所说的,是一套构建用户界面的渐进式框架。与其它重量级框架不同的是,vue 被设计为可以自底向上逐层应用。vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另外一方面,当与现代化工具链以及各种支持类库结合使用时,vu...

代码管理-9-gitlab的使用和设置

gitlab使用1、外观设置完成后保存,返回登录页面查看关于注册,有些公司是不允许打开的,,有些人数非常多的公司就需要打开注册的功能,让人员自己注册,我们来给他特定的权限就可以,毕竟人非常多的时候还由我们来给她们注册就非常不现实了,工作量会很大2、自动注册3、组&用户&项目创建组设置组名称、描述等创...

摄影后期必看 | PS插件camera raw 16.4教程 | 范围蒙版

范围蒙版Camera Raw 【蒙版】模块中提供了三个范围蒙版工具,可以通过特定的范围来创建蒙版。此次新增的【范围蒙版】大大加强了acr插件对局部调整的能力。点击下拉小箭头可以看到【颜色范围】,可用于快速选择想要编辑的颜色。快捷键:Shift + C【明亮度范围】,可用于快速选择想要调整的明亮度。快...

佳能 EOS R8 深度评测

佳能 EOS R8 的定位是入门级全画幅无反光镜可换镜头相机。尽管在产品阵容中处于这一位置,R8 仍然是一个强大的相机,配备了先进的 R6 II 同款成像传感器、快速处理器和令人难以置信的自动对焦系统,体积小、重量轻、价格低。这款相机是发烧友、旅行者、家庭以及任何想要全画幅传感器相机的人的绝佳选择。...

Python中的11 种数组算法

1. 创建数组 创建数组意味着留出一个连续的内存块来存储相同类型的元素。在大多数语言中,您可以在创建数组时指定数组的大小。假设您正在书架上整理一组书籍,并且您需要为正好 10 本书预留空间。功能架上的每个空间都对应于数组中的一个索引。# Example in Python arr = [1, 2,...

一起学Vue:路由(vue-router)

前言学习vue-router就要先了解路由是什么?前端路由的实现原理?vue-router如何使用?等等这些问题,就是本篇要探讨的主要问题。vue-router是什么路由是什么?大概有两种说法:从路由的用途上来解释路由就是指随着浏览器地址栏的变化,展示给用户的页面也不相同。从路由的实现原理上来解释路...