Webpack4.0 的相关优化配置

2023-11-02

所谓的优化,也就是引入一些插件,使得代码的体积变小。

1. 删除没有意义的样式

在css文件中有一些没有用到的样式,希望在打包的过程中 删除掉它们。
安装两个插件 cnpm install purgecss-webpack-plugin glob --save-dev

glob库:主要功能是查找匹配的文件

// 查找src文件夹下的所有文件夹的所有文件。
// {nodir: true} 不包含文件夹
/*
	src-- index.js
	   -- index.css
	   -- index.html
	   -- a
	   	  -- index.js
*/
const glob = require('glob')
let paths = glob.sync("./src/**/*",{nodir: true})
/*
[ './src/a/index.js',
  './src/index.css',
  './src/index.html',
  './src/index.js' ]
*/
const glob = require('glob')
// 只要作用是删除没有意义的css。但不能在style标签中删除,只能配合 mini-css-extract-plugin 插件使用,先抽离css再去优化。
const PurgecssWebpackPlugin = require('purgecss-webpack-plugin')

plugins: [
	new PurgecssWebpackPlugin({
		paths: glob.sync("./src/**/*",{nodir: true})
		// glob.sync(["./src/**/*","!x.js"],{nodir: true}) 忽略x.js文件
	})
]

2. 图片优化

安装loader cnpm install image-webpack-loader --save-dev
image-webpack-loader 要配置在 file-loader 之后

module: [
	{
		test: /\.(jpe?g | png | gif)/,
		use: [
			{
				loader: 'file-loader'
			},
			{
				loader: 'image-webpack-loader',
				// options 配置格式固定。
				options: {
					// 对关于一些图片清晰度的设置。
			        mozjpeg: {
			          progressive: true,
			          quality: 65
			        },
			        // optipng.enabled: false will disable optipng
			        optipng: {
			          enabled: false,
			        },
			        pngquant: {
			          quality: [0.65, 0.90],
			          speed: 4
			        },
			        gifsicle: {
			          interlaced: false,
			        },
			        // the webp option will enable WEBP
			        webp: {
			          quality: 75
			        }
			    }
			}
		]
	}
]

3. CDN引入文件加载

这里在index.html中引入了jq的cdn版,可直接使用$,但为了防止因为直接使用 $ 而产生 来源的疑惑,我们需要手动import jquery, 但是的话,这样 webpack 会在 俩个文件中各打包一次jq。所以 我们还需要进行配置。

// index.html
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

// index.js
import $ from 'jquery'; // => 表明来源,但不打包
console.log($)

// webpack.config.js
module.exports = {
	externals: {
        'jquery': '$' // 不去打包代码里的jquery (脱离webpack打包,不被打入bundle中)
    }
}

如果引入的 cnd文件 有点多的话,一个一个的引太麻烦,可以使用 插件 add-asset-html-cdn-webpack-plugin。注意 它是 基于 html-webpack-plugin 的。
但是:我用的时候这个插件不能用,不知道为啥,可能是版本的原因,毕竟是1.0版本。
我们改用webpack-cdn-plugin 代替它,配置也很简单。

// webpack.config.js
let AddCdnPlugin = require('add-asset-html-cdn-webpack-plugin');


plugins: [
	new HtmlWebpackPlugin({
       template: './src/index.html',
       filename: 'index.html'
    }),
    // 添加cnd的插件
    /*
    new AddCdnPlugin(true,{
       'jquery': 'https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'
    })
    */
    new WebpackCdnPlugin({
       modules: [
          {
              name: 'jquery',
              path: 'https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'
          }
       ]
   })
]

4. Tree-Shaking

‘摇晃树’,作用是 去除掉 js 中多余的代码。并且只支持es6,webpack内置的。
es6 import导入语法为静态导入,require为动态导入,所谓动态导入,就是可以在一些判断语句中可以导入。 if(){ require('...') }

tree-shaking 只能在 生产环境下使用。

删除’副作用’代码:在package.json 中添加 sideEffects: false,只要引入的没有用到,就被删除。但是,如果只单纯写 false,那么引入的 import './index.css' 也会被 tree-shaking掉。

// webpack.config.js
optimization: {
  usedExports: true // 使用了哪个模块你说一下。
}

// calc.js

export const add = (a,b) => {
    return a + b + 'add'
}

export const re = (a,b) => {
    return a - b + 're'
}

// test.js
function test(){
    return '123'
}
console.log(test())

export default test

// index.js
import {add} from './ache';

// 在 引入的 test 文件 中 内部 代码自己执行,导入的 test 应该是没用的代码,不过webpack依然认为它是有用的。我们需要手动处理这样的代码。
import test from './test' // 副作用代码,可能开发的时候是无意义的。应该被删。

import './index.css' //  package.json 里 "sideEffects":["**/*.css",...],声明他不是副作用代码。

console.log(add())

5. Scope hoisting

作用域提升,减少作用域。它也是webpack内置的,不需要配。
因为每个模块导出的都是一个函数。

6. DLL打包

在打包的过程中,例如 react,react-dom 每一次webpack都会重新进行打包,我们希望,可以将 react,react-dom 这类固定文件提前打包好,当下一次打包的时候,直接去打包其他的代码即可,react,react-dom 可以直接拿出来用。

webpack默认打包之后的代码形式是这样的:

// module.exports = 'hello world'

(function () {
  return 'hello world'
})()
// 代码是一个自执行函数

// 当我们在 output 配置中 配置 library:xxx,则会把导出的结果赋值给 xxx。
// let xxx = (function(){...})()
// 除了 library 之外,还有 libraryTarget ,根据变量使用的环境来选择你需要的模式,(var,commonjs,commonjs2,...)

以 raect react-dom 为例 ,生成一个只有 react,react-dom 的文件。

// 新建一个webpack.xxx.js (这里以webpack.dll.js为例)
// webapck.dll.js
const path = require('path');

module.exports = {
    mode: 'development',
    entry: ['react','react-dom'],
    output: {
        library: 'react', // 打包后接受自执行函数的名字叫ache
        // libraryTarget: 'commonjs2',
        filename: 'react.dll.js',
        path: path.resolve(__dirname,'dll')
    }
}

// package.json
"ache": "webpack --config ./webpack.dll.js"

然后,配置DLLPlugin插件,生成manifest.json文件。我们叫这个文件为缓存列表,通过这个缓存列表可以找到对应需要的 模块( react, react-dom )

const DLLPlugin = request('webpack').DLLPlugin

const path = require('path');
const DLLPlugin = require('webpack').DllPlugin
module.exports = {
    mode: 'development',
    entry: ['react','react-dom'],
    output: {
        library: 'react', // 打包后接受自执行函数的名字叫ache
        // libraryTarget: 'commonjs2',
        filename: 'react.dll.js',
        path: path.resolve(__dirname,'dll')
    },
    plugins: [
        new DLLPlugin({
            name: 'react', // 暴露函数的名字。这里的name必须要与dll.js中函数名保持一致。
            path: path.resolve(__dirname,'dll/manifest.json') //  manifest.json 文件的绝对路径
        })
    ]
}
// 我本地使用了 import React 语法,需要先去 manifest.json查找,找到后会加载对应的库的名字,可能会引用某个模块,会去dll.js文件查找。

然后,引入DLL引用插件,让在打包的时候去找minifest.json文件。

// webpack.config.js
const DLLReferencePlugin= require('webpack').DLLReferencePlugin;

plugins:[
	new DLLReferencePlugin({
		// 我打包 react ,会先去manifest.json文件中查找,找到后再去找真实的文件(dll.js)。
		manifest: path.resolve(__dirname,'dll/manifest.json')
	}),
	...
]

通过上面以及配置差不多了,但是通过 manifest.json,会去找 name 对应 dll.js文件中的 变量,发现 dll.js文件包 没有被引入,找不到 react。
手动引太麻烦,这时还得需要一个插件:add-asset-html-webpack-plugin
cnpm install add-asset-html-webpack-plugin --save-dev
这个插件 会将 dll.js 文件拷贝到 dist 目录下,然会在自动引入 index.html 中。

// webpack.config.js
const AddAssetHtmlPlugin= require('add-asset-html-webpack-plugin')
plugins: [
	new AddAssetHtmlPlugin({
       filepath: path.resolve(__dirname,'./dll/react.dll.js') // 将该文件拷贝到dist目录下
    }),
    ...
]

一般来说,DLL插件是用在开发环境下的。

7.动态加载

用来实现动态分离文件
import 语法引入。
核心原理是 使用jsonp动态导入需要引入的文件。
import 可以实现代码分割。

// index.js
button.addEventListener('click',() => {
	// 动态导入,类比 路由懒加载 import语法
	import('./ache.js').then(data => {
		console.log(data.add(11,22))
	})
})

给动态引入的文件增加名字

output: {
	filename: 'xxx' // 同步打包的名字
	chunkFilename: '[name].main.js' // 异步打包的名字 name 默认是0,1,2...递增的。
}
import(/* webpackChunkName: "video" */'./video.js').then(data => { // 会把 "video" 传入到 上面 [name] 中。
	console.log(data)
})
// 打包后 video.main.js

8. 打包文件分析工具

8.1 多入口

// webpack.config.js
{	// entry 有三种写法:字符串,数组,对象
	entry: {
		'a': './a.js',
		'b': './b.js'
	}
}

plugins: [
	new HtmlWebpackPlugin({
		template: './src/index.html',
		filename: 'index.html',
		chunks: ['a'] //要引入打包后的 'a' 代码块。
	}),
	new HtmlWebpackPlugin({
		template: './src/index.html',
		filename: 'login.html',
		chunks: ['b'], // 如果是 ['b','a'],我们希望 login.html中是按照 这个数组的顺序引进的,但是webpack是按照entry的顺序引入的,所以 我们要配置 chunkSortMode。
		chunkSortMode: 'manual' // 手动按照我的顺序来执行
	})
]

8.2 分析依赖

按装 cnpm install webpack-bundle-analyzer --save-dev 可视化分析工具。
多用在生产环境下,并且可以帮助我们将第三方包进行分离。
会自动生成一个8888端口。

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

plugins: [
	env !== 'development' && new BundleAnalyzerPlugin()
].filter(Boolean)

9. 第三方模块的抽离

当遇到类似于 react react-dom 这样较大的库时,需要抽离打包。可以使用下面属性。
dllPlugin 不要和 splitchunks 共同使用。

// webpack.config.js
optimization: {
            splitChunks: {
            	// chunk: initial 只操作同步的 ;all所有的;async异步的。
                chunks: 'async', // 默认支持异步代码分割 import()
                minSize: 30000, // 文件超过30K 我就回抽离它
                maxSize: 0,
                minChunks: 1, // 最少模板引用一次才抽离
                maxAsyncRequests: 30, // 最多5个请求
                maxInitialRequests: 30, // 最多首屏加载30个请求
                automaticNameDelimiter: '~', // xxx~a~b
                enforceSizeThreshold: 50000,
                automaticNameMaxLength: 30,  // 最长名字大小
                cacheGroups: { // 缓存组, cacheGroups内配置优先级高于外部配置
                    // react: {
                    //     test: /[\\/]node_modules[\\/]\/react|react-dom/, // 要抽离的模块
                    //     priority: 1 // 优先级
                    // },
                    defaultVendors: {
                        test: /[\\/]node_modules[\\/]/,
                        priority: -10
                    },
                    default: { // common~a~b
                        minChunks: 2,
                        priority: -20,
                        reuseExistingChunk: true
                    }
                }
            }
        }

// a.js
import ('jquary') // 异步
import React from 'react' // 同步

10. 费时分析

测试当前打包的速度

const SpeedMeasureWebpackPlugin = require('speed-measure-webpack-plugin');
const smw = new SpeedMeasureWebpackPlugin () //在外面new

// 将我们的打包代码包起来
module.exports = env => {
	return smv.wrap({
		mode: env,
		entry: ...
		output: ...
	})
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Webpack4.0 的相关优化配置 的相关文章

随机推荐

  • TensorFlow入门 - 变量(Variables)

    训练模型时 需要使用变量 Variables 保存和更新参数 Variables是包含张量 tensor 的内存缓冲 变量必须要先被初始化 initialize 而且可以在训练时和训练后保存 save 到磁盘中 之后可以再恢复 restor
  • 科普:PCI-E插槽都有哪些样子?

    主板上的扩展插槽曾经是多种多样的 例如曾经非常流行的组合就是PCI插槽搭配AGP插槽 其中AGP插槽主要用在显卡上 而PCI插槽的用途则更广一些 不仅有用在显卡上 还能用于扩展其它设备 如网卡 声卡 调制解调器等等 这两种插槽曾经共同为广大
  • RSYNC介绍 、备份、自动备份 脚本编写

    RSYNC 简介 rsync 是一个远程同步 是一个开源的快速安全高效的异地备份工具 可以在不同的主机之间镜像同步整个目录树 支持增量备份 有保持链接和权限功能 且采用优化的同步算法 传输前执行压缩 因此非常适合异地备份 镜像服务等应用 也
  • linux虚拟机开放端口号,虚拟机centos7开放端口

    1 先查看防火墙是否开启的状态 以及开放端口的情况 systemctl status firewalld service 查看防火墙开启还是关闭 sudo firewall cmd list all 可以查看端口开放情况 firewall
  • 超简单制作多系统启动U盘教程

    超简单制作多系统启动U盘教程 文章目录 超简单制作多系统启动U盘教程 前言 基本配置 配置PE系统 配置其他操作系统 前言 这两天心血来潮 本来想用Win to go做一个windows便携系统 B站教程无意间发现Ventoy软件 可谓功能
  • 套接字多种可选项

    Windows平台 WSADATA wsaData int iResult WSAStartup MAKEWORD 2 2 wsaData if iResult NO ERROR printf Error at WSAStartup n C
  • 虚拟机centos6.4网络连接设置--桥接设置

    Windows 本机虚拟网卡设置 虚拟机安装完成之后 在 本机网络设置里面出现 两个网卡VMware Network Adapter VMnet1和VMware Network Adapter Vmnet8 联网用Vmnet8 设置连接网络
  • PHP Smarty如何进行调试和错误处理?

    欢迎来到PHP Smarty的世界 如果你在这里寻求如何调试和错误处理的方法 那么我可以向你保证 我们会让这个过程尽可能的有趣和轻松 首先 让我们先来谈谈调试 在Smarty中 你可以使用以下几种方法来进行调试 使用Smarty的debug
  • Centos7 安装MongoDB5

    1 mongodb安装 MongoDB的下载网址 Download MongoDB Community Server MongoDB 下载完安装包之后上传到系统 然后解压 tar xf mongodb linux x86 64 rhel80
  • 灰色预测GM(1,1)代码

    目录 1 一项初始序列X0 2 累加序列 生成新序列 3 紧邻均值生成序列 4 求相关参数 5 由第四步求出参数 6 生成预测模型 7 累减还原 得原始数列的灰色预测值 8 模型检验 9 可视化 结果分析 1 一项初始序列X0 import
  • 数据库事务

    事务 TRANSACTION 是作为单个逻辑工作单元执行的一系列操作 这些操作作为一个整体一起向 系统提交 要么都执行 要么都不执行 事务是一个不可分割的工作逻辑单元 事务必须具备以下四个属性 简称 ACID 属性 原子性 Atomicit
  • 解决Could not connect to Redis at 39.101.74.81:6379: ConnectinectionException: Failed to create socket

    1 修改redis conf文件 1 注释掉原先的 bind 127 0 0 1 2 将protected mode yes 修改为no 2 查看是否开启6379端口号 firewall cmd list ports 没开启的话开启 fir
  • 从DB Browser for SQLite导出.csv文件

    如何从 db数据库文件中导出某个表的 csv文件 一般的 后台收集的日志保存在数据库中 查找日志时候需要打开 db文件的数据库 使用DB Browser for SQLite这个软件可以打开和查看数据库表以及数据 使用DB Browser
  • Golang笔记:使用ssh包作为客户端与SSH服务器交互

    文章目录 目的 基础说明 使用演示 单次通讯 连续通讯 远程终端 总结 目的 Golang中可以使用 golang org x crypto ssh 包作为SSH客户端或者SSH服务使用 这篇文章将简单记录下作为客户端使用的一些内容 Pac
  • form表单的提交

    基于html 语言的form表单的提交 1 表单属性设置 标签 表示表单标签 定义整体的表单区域 action属性 设置表单数据提交地址 method属性 设置表单提交的方式 一般有 GET 方式和 POST 方式 不区分大小写 2 表单元
  • Ubuntu中Tango Control的Pogo无法加载的解决办法

    文章目录 环境 步骤 卸载java ubuntu 安装指定版本jdk 重新编译测试 参考 在 自定义Tango Control设备服务在Ubuntu中的测试 中发现 pogo经常出现加载不出来的情况 但是偶尔会有一次可以打开 https b
  • Python:回文日期问题

    每日一题 目录 每日一题 文章目录 前言 一 题目描述 二 输入描述 三 输出描述 1 引入库 2 执行结果 datetime模块的用法 flag的用法 replace 方法 参数 总结 前言 本文章重点讲述回文日期问题 在其中介绍用到的函
  • C语言钟表【改进版】

    改进版源代码 include
  • 边缘计算物联网网关在机械加工行业中的效用分享

    随着工业4 0的推进 物联网技术正在逐渐渗透到各个行业领域 机械加工行业作为制造业的基础领域之一 其生产过程的自动化 智能化水平直接影响到产品质量和生产效率 边缘计算物联网网关作为物联网技术的重要组成部分 在机械加工行业中发挥着越来越重要的
  • Webpack4.0 的相关优化配置

    所谓的优化 也就是引入一些插件 使得代码的体积变小 1 删除没有意义的样式 在css文件中有一些没有用到的样式 希望在打包的过程中 删除掉它们 安装两个插件 cnpm install purgecss webpack plugin glob