一、前言

对于使用vue开发项目的FE来说,打包上线这个环节相信大家都不陌生。本文主要是介绍如何通过webpack(实践版本:webpack4.16.5)的配置来提高打包构建速度以及减小包的体积。

二、优化策略

css,js,html压缩

使用 optimize-css-assets-webpack-plugin 来压缩css。在webpack4的配置项中,需在optimization下的minimizer对象中去实例化使用。

// 压缩css

const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')

// 在optimization.minimizer中引用

new OptimizeCSSAssetsPlugin()复制代码

使用 MiniCssExtractPlugin来抽离内联css到外联文件 。

// 抽离内联css到外部css文件

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

// 在optimization.minimizer中引用

new MiniCssExtractPlugin({

filename: utils.assetsPath('css/[name].[contenthash:8].css'),

chunkFilename: utils.assetsPath('css/[name].[contenthash:8].css')

})复制代码

使用 uglifyjs-webpack-plugin 来压缩js,重点属性 parallel, 用来开启多进程并行执行js压缩,大大提高构建速度。

//压缩js

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

//在optimization.minimizer中引用

new UglifyJsPlugin({

uglifyOptions: {

warnings: false,

mangle: {

safari10: true

},

compress: {

drop_debugger: false,

drop_console: true, //console

pure_funcs: ['console.log'] // 移除console

},

output:{

// 去掉注释内容

comments: false

}

},

sourceMap: false,

cache: true,

parallel: true

})复制代码

使用 html-webpack-plugin来 压缩 html 代码,并实现自动化注入脚本以及样式文件,对于文件名中包含哈希的Webpack捆绑包尤其有用。

// 压缩html

const HtmlWebpackPlugin = require('html-webpack-plugin')

// 在plugins中引入

new webpack.HtmlWebpackPlugin({ filename:path.resolve(__dirname, '../dist/index.html'),

template: 'index.html', inject: true,

favicon: resolve('favicon.ico'),

title:'标题',

minify: {

removeComments: true,

collapseWhitespace: true,

removeAttributeQuotes: true

} })

复制代码

拆包

webpack4.x中使用splitChunks来进行拆包,抽离第三方依赖库。默认情况下,webpack将会基于以下条件自动分割代码块:

新的代码块被共享或者来自node_modules文件夹

新的代码块大于30kb(在min+giz之前)

按需加载代码块的请求数量应该<=5

页面初始化时加载代码块的请求数量应该<=3

默认配置如下:

splitChunks: {

chunks: "async",

minSize: 30000, // 模块的最小体积

minChunks: 1, // 模块的最小被引用次数

maxAsyncRequests: 5, // 按需加载的最大并行请求数

maxInitialRequests: 3, // 一个入口最大并行请求数

automaticNameDelimiter: '~', // 文件名的连接符

name: true,

cacheGroups: { // 缓存组

vendors: {

test: /[\\/]node_modules[\\/]/,

priority: -10

},

default: {

minChunks: 2,

priority: -20,

reuseExistingChunk: true

}

}

}复制代码

可以通过自定义配置项修改配置,如像这样抽离第三方依赖库(如单独将elementUI打包)

splitChunks: {

chunks: 'all',

cacheGroups: {

lib: {

name: 'chunks-libs',

test: /[\\/]node_modules[\\/]/,

priority: 10,

chunks: 'initial' // 只打包初始时依赖的第三方

},

elementUI: {

name: 'chunk-elementUI', // 单独将 elementUI 拆包

priority: 20, // 权重要大于 libs 和 app 不然会被打包进 libs 或者 app

test: /[\\/]node_modules[\\/]element-ui[\\/]/,

chunks: 'all'

}

}

}复制代码

一般还需配合runtimeChunk使用( runtimeChunk的具体作用 )。在抽取 Webpack 运行时代码的时候,要指定 runtimeChunk 属性:

true

'single'

// optimization.runtimeChunk 具体使用规则 详见

//https://webpack.js.org/configuration/optimization/#optimizationruntimechunk

runtimeChunk: true复制代码

Happypack

由于 JavaScript 是单线程模型,在webpack构建过程中,我们需要使用Loader对js,css,图片,字体等文件做转换操作,并且转换的文件数据量也是非常大的,且这些转换操作不能并发处理文件,而是需要一个个文件进行处理,HappyPack的基本原理是将这部分任务分解到多个子进程中去并行处理,子进程处理完成后把结果发送到主进程中,从而减少总的构建时间。(ps:对file-loader和url-loader支持不好,所以这两个loader就不需要换成HappyPack)

Happypack运行机制

Happy使用方式

// 多进程并发执行loader 默认为单线程

const HappyPack = require('happypack')

const os = require('os')// 根据系统的内核数量 指定线程池个数 也可以其他数量

const happyThreadPool = HappyPack.ThreadPool({size: os.cpus().length})//插件中引入

plugins:[

new HappyPack({

// 基础参数设置

id: 'babel', // 上面loader?后面指定的id

loaders: ['babel-loader?cacheDirectory'], // 实际匹配处理的loader 这里加入了缓存控制

threadPool: happyThreadPool,

verbose: true

})

]

// loader处理器中使用 通过id匹配modules: {

test: /\.js$/,

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

exclude: /node_modules/, // 排除不处理的目录

include: [

resolve('src'), resolve('test'),

resolve('mock'),

resolve('node_modules/webpack-dev-server/client')

]

}复制代码

缓存与增量构建

缓存构建 :webpack构建中,一般需要使用许多loader来预处理文件,以babel-loader为例。可以通过设置 cacheDirectory 或 cacheDirectory=true 来达到缓存的目的。

{

test: /\.js$/,

loader: 'babel-loader?cacheDirectory',

exclude: /node_modules/, // 排除不处理的目录

include: [

resolve('src'),

resolve('test'),

resolve('mock'),

resolve('node_modules/webpack-dev-server/client')

]

}复制代码

cacheDirectory对loader转译后的结果进行缓存,之后的webpack进行构建时,都会去尝试读取缓存来避免高耗能的babel重新转译过程。

增量构建 :使用增量构建而不是全量构建有利于构建速度的提升。 全量构建 即每次重新构建都需要重新编译一次(包括未修改部分),而 增量构建 对于未修改的部分不会再重新编译,对于rebuild能够大大提高编译速度。对于开发阶段,可以使用 webpack-dev-server 来达到增量编译的目的,对于生产阶段,可以通过给生成的文件添加 hash (或 chunkhash 或 contenthash )来实现增量构建。

output: {

path: config.build.assetsRoot,

filename: utils.assetsPath('js/[name].[chunkhash:8].js'),

chunkFilename: utils.assetsPath('js/[name].[chunkhash:8].js')

}复制代码

优化模块查找路径

通过配置resolve.modules来告诉webpack解析模块时应该搜索的目录。默认配置采用向上递归搜索的方式去寻找,设置特定搜索目录有助于webpack更快搜索到目标。

resolve: {

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

alias: {

'@': resolve('src')

},

modules: [

resolve('src'),

resolve('node_modules')

]}

}复制代码

DllPlugin和DllReferencePlugin

dll全称为动态链接库,先通过 dllPlugin 生成清单文件(这个文件包含了从 require 和 import 的request到模块 id 的映射),然后通过 DllReferencePlugin 引用该清单文件,将依赖的名称映射到模块的 id 上。这样每次打包时.先去查找清单里中是否已经存在这个依赖,如果已经存在,则不打包,如果还没存在,则需要打包。与通过 externals 的方式引入第三方库类似,dll主要用于那些没有可以在

使用方式

新建一个webpack.dll.conf.js文件,并执行 webpack --config ./build/webpack.dll.conf.js 会在static/js文件夹下生成 dll.vendor.js 以及在根目录下生成 mainfest.json

//webpack.dll.conf.js

const webpack = require('webpack');

const path = require('path');

const vendors = [ 'vue', 'vue-router', 'vuex', 'axios'];

module.exports = {

output: {

path: path.resolve(__dirname, '../static/js'),

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

},

entry: { vendor: vendors, },

plugins: [

new webpack.DllPlugin({

path: 'manifest.json',

name: '[name]',

context: __dirname

})

]

}复制代码

在项目配置文件(如webpack.base.conf.js)中通过DllRe引入

// build/webpack.base.conf.js

const manifest = require('../manifest.json')

// 插件中引入

plugins: [

new webpack.DllReferencePlugin({

mainfest

})

]复制代码

然后在index.html手动引入该文件

复制代码

externals配合cdn加载第三方库

externals的作用是从打包的bundle文件中排除依赖。通俗点讲,就是在项目中通过import引入的依赖在打包的时候不会打包到bundle包中去,而是通过script的方式去访问这些依赖。与Dll不同的是,要去维护cdn

// build/webpack.base.conf.js

// externals 对象中的 key代表第三方依赖名(同package.json包中依赖名)

// value代表暴露给外部使用的别名 这里element-ui的别名为ELEMENT

module.exports ={

externals: {

'vue':'Vue',

'vue-router':'VueRouter',

'axios':'axios',

'vuex':'Vuex',

'element-ui':'ELEMENT'

}

}复制代码

在index.html文件中通过cdn方式引入

// head中引入

// body中引入

复制代码

在相关文件中移除相关引入的依赖

// main.js

//通过cdn的方式注释相关依赖

// import Vue from "vue";

// import ElementUI from "element-ui";

// Vue.use(ElementUI);

// store/index.js

// 注释掉vuex import引入方式

// import Vue from 'vue';

// import Vuex from 'vuex';

// Vue.use(Vuex);

// router/router.js

// 注释掉vue-router

// import Vue from 'vue';

// import Router from 'vue-router';

//使用externals中vue-router暴露的全局对象名VueRouter进行实例化

const router = new VueRouter({

mode: "history",

scrollBehavior: () => ({y: 0}),

routes: [otherRouter, ...constantRouterMap]

});复制代码

分析工具

查看 webpack 打包后所有组件与组件间的依赖关系,可以通过打包分析 工具 来实现。

webpack-bundle-analyzer

webpack-bundle-analyzer是一个webpack打包分析插件,它将打包的依赖关系以树形图的方式呈现,直观方便。

plugins:[

new BundleAnalyzerPlugin({

analyzerPort: 8080,

generateStatsFile: false

})

]复制代码

在插件配置项中引入并通过 cnpm run build --report 来生成可视化分析图,效果图如下:

官方分析工具

webpack提供的一个官方工具,可查看你的项目版本信息,有多少modules,多少chunks,中间有多少错误信息、有多少警告,各个模块之间的依赖关系等。

使用方式

首先通过 webpack --config ./build/webpack.prod.conf.js --json > stats.json 生成 json 文件(ps:如果使用了Happypack,需删除该json文件前两行,否则不是标准的json),然后通过官网分析工具地址将该文件上传,如图所示:

具体分析结果可以通过点击相应的模块查看详情。

总结

webpack优化并没有一个通用方案,这里我只是列出了我使用过的一些策略,具体业务需具体分析,对症下药。希望本文能帮助到一些有需要的小伙伴~

html 打包优化,Webpack打包优化相关推荐

  1. webpack打包优化(webpack打包优化 文件大小)

    webpack 打包怎么优化的 解决webpack打包的文件体积过大的问题: 确实,每次打包从入口开始,会parse所有的依赖,多的时候竟然打包一次要2秒多,简直不能忍.然而,有几个解决方案,最有效的 ...

  2. 利用HappyPack优化webpack打包速度

    2019独角兽企业重金招聘Python工程师标准>>> 由于运行在 Node.js 之上的 Webpack 是单线程模型的,所以Webpack 需要处理的事情需要一件一件的做,不能多 ...

  3. webpack打包vue反编译_2020年你必须知道的webpack打包优化方法

    本文字数:3534字 预计阅读时间:10分钟 随着我们的项目项目越做越大,引入的第三方库会越来越多,打包的依赖也越来越多,每次 build 的时间越来越长,打包出来的文件会越来越大.最糟糕的是单页面应 ...

  4. (六)构建优化(揭开webpack性能优化的内幕)

    构建优化 webpack的优化配置[了解这些优化配置才敢说会用webpack] Tree-shaking JS压缩 作用域提升 Babel的优化配置 webpack的依赖优化 noParse(不解析) ...

  5. 五分钟学会前端打包工具webpack

    可以做的事情 代码转换.文件优化.代码分割.模块合并.自动刷新.代码校验.自动发布 最终目的 webpack的基本配置 webpack的高级配置 webpack的优化策略 ast抽象语法树 webpa ...

  6. webpack打包 - webpack篇

    @TOC# 什么是 webpack? 本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler).当 webpack 处理应用程序时,它会递归地 ...

  7. 【Webpack 性能优化系列(1) - HMR 热模块替换】

    webpack系列文章: [Webpack 性能优化系列(9) - 多进程打包]极大的提升项目打包构建速度!!! [Webpack 性能优化系列(8) - PWA]使用渐进式网络应用程序为我们的项目添 ...

  8. 使用webpack打包的后,公共请求路径的配置问题

    在我们公司,和后台接接口时,公共的请求路径我们是单独抽出来的,放在一个独立的public.js中,在public.js中存入那个公共变量 公共变量是这样 在其他地方使用ajax时,我们就这样使用 这种 ...

  9. webpack打包css

    webpack打包 1.打包css 2.打包逻辑 1-1.webpack打包css逻辑 3.打包css 4.打包成独立的css文件 5.添加样式前缀 6.格式校验 7.压缩css 8.我们为什么要用这 ...

最新文章

  1. 【camera】自动泊车-基于深度学习的视觉车位检测项目(课程设计--训练代码、测试代码、部署demo)(2)
  2. XLT格式化XML那点事(C#代码中的问题解决)(二)
  3. html5伸缩效果,【HTML5】Jquery打造竖向伸缩/展开菜单
  4. 200 行代码实现一个滑动验证码
  5. signature=4c9125bac76ec40553ba356eaca47964,2008 SEM Honorary Members Conversations
  6. MySQL之Handler_read_*查看索引使用情况
  7. ip_conntrack 模块的作用
  8. un8.21:用html实现增删改查功能(代码篇)。
  9. 基于Echarts的图表绘制
  10. Linux DMA 内dwc_prep_slave_sg函数与device_prep_dma_cyclic函数
  11. 带有en的单词有哪些_英语前缀大全en:开头是EN的单词有哪些
  12. 微吼直播 html5,微吼直播jssdk接入指引.pdf
  13. 公众号搜题题库接口使用方法
  14. 三点运算符(三点语法)
  15. python时间戳datetime取出年、月、日、时
  16. 别羡慕苹果的小部件了,安卓也有!
  17. 【Kawasaki川崎机器人码垛程序】CP180L-AC01
  18. 社会治理网格化新华三移动IT助江西铺设综合治理“一张网”
  19. 给通信专业研究生——安心完成培养,你不是在劣势下和计算机学生抢饭碗来的
  20. C++数据结构——小明的通讯录(哈希表线性探测法)

热门文章

  1. springboot上传文件MultipartFile.transferTo()
  2. 给PyQt5 exe程序设置自启动(Windows)
  3. flask如何查询mysql_python3-flask-4查询mysql
  4. Java编程需要必须掌握哪些基础知识?
  5. InnovMetric PolyWorks Metrology Suite 2021 IR2
  6. Android二维码名片生成扫码识别
  7. detectron2如何使用模型
  8. 使用KiCad插件,将PCB焊接可视化
  9. mysql的乘号_乘号怎么输入(公式的乘号怎么输入)
  10. 使用Python+opencv进行图像处理(一) | 视觉入门