品牌 资讯 搭配 材料 时尚 热点 行业 首饰 玉石 行情

【webpack系列】从基础配置到掌握进阶用法_天天聚看点

2023-06-25 11:18:54 来源:博客园
前言

本篇文章将介绍一些webpack的进阶用法,演示内容继承自上一篇文章的内容,所以没看过上一篇文章的建议先学习上一篇内容再阅读此篇内容,会更有利于此篇的学习~


(资料图片仅供参考)

文件指纹

文件指纹指的是打包输出的文件名后缀,一般用来做版本管理、缓存等

webpack的指纹策略有三种:hashchunkhashcontenthash,它们之间最主要的区别就是每种hash影响的范围不同。

占位符

webpack提供占位符用于将特定信息附加在打包输出的文件上

名称含义
[ext]资源后缀名
[id]文件标识符
[name]文件名称
[path]文件的相对路径
[folder]文件所在的文件夹
[hash]模块标识符的 hash,默认是 md5 生成
[chunkhash]chunk 内容的 hash,默认是 md5 生成
[contenthash]文件内容的 hash,默认是 md5 生成
[query]文件的 query,例如,文件名 ? 后面的字符串
[emoji]一个随机的指代文件内容的 emoji

我们可以使用特定的语法,对 hashchunkhashcontenthash进行切片:[chunkhash:4],像 8c4cbfdb91ff93f3f3c5这样的哈希会最后会变为 8c4c

hash

与整个项目的构建有关,只要项目内文件有修改,整个项目构建的hash值就会改变

我们使用多入口打包来体验一下:

// webpack.config.jsmodule.exports = {  entry: {         main: "./src/main.js",        index: "./src/index.js"    },    output: {        filename: "[name].[hash:6].js",        path: __dirname + "/dist",        clean: true    },  // ...}

此时我们使用了占位符来设置文件指纹[name].[hash:6].js代表的是文件名+6位hash

此时我们执行npm run build,看打包出来的内容如下:

此时两个js文件的hash都是207495

我们修改一下index.js的内容,再打包一次

我们会发现此时两个js文件的hash都变成了9f0e2d

chunkhash

chunkhash 是和 webpack 打包的模块相关,每一个 entry 作为一个模块,会产生不同的 Chunkhash 值,文件改变时只会影响当前chunk组的hash值

我们再来看看chunkhash

// webpack.config.jsmodule.exports = {  entry: {         main: "./src/main.js",        index: "./src/index.js"    },    output: {        filename: "[name].[chunkhash:6].js",        path: __dirname + "/dist",        clean: true    },  // ...}

还是延用上面的例子,这次我们只修改main.js文件内容

修改前两个文件的hash值如下:

修改后:

此时只有main.js的打包产物的hash发生了变化

contenthash

contenthash 是和根据文件内容相关,单个文件发生变化,只会引起此文件的hash值

这里我们使用miniCssExtractPlugin将CSS内容提取成文件,并为它设置contenthash

// webpack.config.jsconst miniCssExtractPlugin = require("mini-css-extract-plugin")module.exports = {  entry: {         main: "./src/main.js",        index: "./src/index.js"    },    output: {        filename: "[name].[contenthash:6].js",        path: __dirname + "/dist",        clean: true    },  mudole: {    rules: [      {        test: /\.css$/,        use: [miniCssExtractPlugin.loader, "css-loader"]      },      // ...    ]  },  plugins: [    // ...    new miniCssExtractPlugin({            filename: "css/[name].[contenthash:6].css"        }),  ]  // ...}

然后打包看一下此时的hash:

我们修改index.css内容再打包一次

此时只有index.css的打包产物hash值发生了变化。

根据不同的文件类型一般选择不同的文件指纹策略,通常情况下:

JS文件采用[chunkhash]文件指纹策略CSS文件采用[contenthash]文件指纹策略图片资源采用[hash]文件指纹策略代码压缩压缩JS

目前最成熟的JavaScript代码压缩工具是UglifyJS,它能够分析JavaScript语法树,理解代码含义,从而能做到诸如去掉无效代码、去掉日志输出代码、缩短变量名等优化。但很遗憾的是UglifyJS不再维护,并且它不支持 ES6 + 。

现在推荐使用的是Terser,它在 UglifyJS 基础上增加了 ES6 语法支持,并重构代码解析、压缩算法,使得执行效率与压缩率都有较大提升,并且Webpack5.0 后默认使用 Terser 作为 JavaScript 代码压缩器

简单实用:

// webpack.config.jsmodule.exports = {  //...  optimization: {    minimize: true  }}

需要注意的是在生产模式中构建时,Terser压缩是默认开启的

当然它也允许你通过提供一个或多个定制过的TerserPlugin实例,覆盖默认的压缩工具,实现更精细的压缩功能

// webpack.config.jsconst TerserPlugin = require("terser-webpack-plugin");module.exports = {  //...  optimization: {    minimize: true,    minimizer: [      new TerserPlugin({        parallel: true,        terserOptions: {          // https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions        },      })    ]  }}

在Webpack4中 默认使用 uglifyjs-webpack-plugin压缩代码,也可以通过 minimizer数组替换为 Terser 插件

压缩CSS

CSS代码同样也可以使用webpack来进行压缩,比较常见的CSS压缩工具有:cssnanocss-minimizer-webpack-plugin

对于 webpack5 或更高版本,官方推荐使用 CssMinimizerWebpackPlugin,该插件是使用 cssnano优化和压缩 CSS,支持缓存和并发模式下运行。

安装:

npm i css-minimizer-webpack-plugin

配置:

// webpack.config.jsconst CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); // 用压缩cssconst MiniCssExtractPlugin = require("mini-css-extract-plugin");  // 用来提取css成单独的文件module.exports = {  //...  module: {    rules: [      {        test: /.css$/,        // 注意,MiniCssExtractPlugin.loader 与 style-loader不能同时使用        use: [MiniCssExtractPlugin.loader, "css-loader"],      },    ],  },  optimization: {    minimize: true,    minimizer: [      // Webpack5 之后,约定使用 "..." 字面量保留默认 minimizer 配置      "...",      new CssMinimizerPlugin(),    ],  },  plugins: [new MiniCssExtractPlugin()],};

⚠️这里需要注意的是需要使用 mini-css-extract-plugin将 CSS 代码抽取为单独的 CSS 产物文件,这样才能命中 css-minimizer-webpack-plugin默认的 test逻辑。

压缩HTML

我们之前使用的html-webpack-plugin,它除了可以生成html模版,也可以用来对html进行压缩。

htmlWebpackPlugin常见参数

template:模板的路径,默认会去寻找 src/index.ejs是否存在。

filename:输出文件的名称,默认为 index.html

inject:是否将资源注入到模版中,默认为 true

minify:压缩参数。在生产模式下(production),默认为 true;否则,默认为false

// webpack.config.jsmodule.exports = {  // ...  plugins: [    // ...    new HtmlWebpackPlugin({            template: "./public/index.html",            filename: "index.html",            minify: true        }),  ]}

生成的 HTML 将使用 html-minifier-terser和以下选项进行压缩,所以它实际上的压缩功能其实是html-minifier-terser来实现的,更多配置可以查看这个工具文档

{  collapseWhitespace: true,  keepClosingSlash: true,  removeComments: true,  removeRedundantAttributes: true,  removeScriptTypeAttributes: true,  removeStyleLinkTypeAttributes: true,  useShortDoctype: true}
禁止生成LICENSE文件

经过上面这些配置后,我发现了一个奇怪的问题,那就是每个bundle产物都多了一个同名的LICENSE.txt文件,打开一看里面都是一些注释内容。

为什么会生成这些文件,带着疑惑我去翻了下官方文档,Webpack5 默认压缩代码工具为terser-webpack-plugin,那就先从它入手吧。

在它的配置中找到了extractComments参数,默认值为true,表示将注释剥离到单独的文件中。

如果我们不想要,直接关掉该配置就行了

module.exports = {  // ...  optimization: {        minimize: true,        minimizer: [            new cssMinimizerPlugin(),            new terserPlugin({                extractComments: false,  // 关闭注释剥离功能            }),            "..."        ]    },}
CSS增强(autoprefixer)

前端最头疼的问题莫过于处理兼容性,因为前端的运行环境并不固定,可以在各种浏览器以及各种webview中运行,并且每个浏览器厂商对CSS的写法也各不相同,这就势必会导致出现一些问题。

比如为了兼容各种浏览器内核,圆角属性应该这样写:

.container {  -moz-border-radius: 16px;  -webkit-border-radius: 16px;  -o-border-radius: 16px;  border-radius: 16px;}

试想一下如果在开发中需要你这样写,那是不是太不合理了?

我们一般都会通过webpack配置插件来帮我们解决这个问题,处理CSS我们首先会想到postcss,没错webpack也有使用postcss处理CSS的loader --- postcss-loader,然后我们还需要使用postcss的插件autoprefixer来帮我们自动添加浏览器前缀。

安装:

npm i postcss postcss-loader autoprefixer

修改配置:

// webpack.config.jsmodule.exports = {  // ...  module: {    rules: [      //...      {        test: /\.css$/,        use: [miniCssExtractPlugin.loader,               "css-loader",               {                loader: "postcss-loader",                options: {                  postcssOptions: {                    plugins: ["autoprefixer"]                  }                }              }]      },    ]  }  //...}

⚠️这里需要注意的是,如果你想自定义转换的规则,最好是将 autoprefixer 的 browsers选项替换为 browserslist配置。在 package.json或。Browserslistrc文件。使用 browsers选项可能导致错误,并且browserslist配置可以用于 babel、 autoprefixer、 postcss-norize 等工具。

比如package.json中配置browserslist:

// package.json{  //...  "browserslist": [    "last 10 Chrome versions",    "last 5 Firefox versions",    "Safari >= 6",     "ie> 8"  ] }

此时我们打包的CSS的产物就会自动添加浏览器前缀

静态资源拷贝

假如我们需要在html中引用一些不需要打包处理的资源,比如下面这种情况

index.html中引入了一些日志的工具函数,这时候我们直接跑起来会发现这个文件直接404了,这是怎么回事?

首先我们写的路径肯定是没问题的,问题在于我们打包后这个utils文件肯定是不在这个位置了,所以会报404

所以这里我们需要使用copy-webpack-plugin将文件拷贝至dist目录下

// webpack.config.jsconst copyWebpackPlugin = require("copy-webpack-plugin")module.exports = {  // ...  plugins: [    new copyWebpackPlugin({      patterns: [        {from: "module", to: __dirname + "/dist/module/"}      ]    }),  ]}

此时再打包,我们会发现dist目录下已经有了module/utils.js,并且页面也不会再报404了

sourcemap

SourceMap 就是一个信息文件,里面储存着代码的位置信息。这种文件主要用于开发调试,现在代码都会经过压缩混淆,这样报错提示会很难定位代码。通过 SourceMap 能快速定位到源代码,并进行调试。

比如我们没有开启sourcemap,然后开发过程中报错了,它的报错信息是这样的:

定位过去是打包后的内容,这样的话对我们排查报错非常不方便。

当我们开启sourcemap,再来看看这个同样的报错是怎样的:

// webpack.config.jsmodule.exports = {  // ...  devtool: "eval-cheap-module-source-map",}

此时的报错指向就非常清晰了~

关键字

devtool的值有20多种,并且都是由以下七种关键字的一个或多个组成

eval关键字

devtool值包含 eval时,生成的模块代码会被包裹进一段 eval函数中,且模块的 Sourcemap 信息通过 //# sourceURL直接挂载在模块代码内

source-map关键字

devtool包含 source-map时,Webpack 才会生成 Sourcemap 内容

cheap关键字

devtool包含 cheap时,生成的 Sourcemap 内容会抛弃维度的信息,这就意味着浏览器只能映射到代码行维度

module关键字

module关键字只在 cheap场景下生效,例如 cheap-module-source-mapeval-cheap-module-source-map。当 devtool包含 cheap时,Webpack 根据 module关键字判断按 loader 联调处理结果作为 source,还是按处理之前的代码作为 source

nosources关键字

devtool包含 nosources时,生成的 Sourcemap 内容中不包含源码内容 —— 即 sourcesContent字段

inline关键字

devtool包含 inline时,Webpack 会将 Sourcemap 内容编码为 Base64 DataURL,直接追加到产物文件中

hidden关键字

通常,产物中必须携带 //# sourceMappingURL=指令,浏览器才能正确找到 Sourcemap 文件,当 devtool包含 hidden时,编译产物中不包含 //# sourceMappingURL=指令

devtool的值以及各自的功能可以在webpack文档上查看

如何选择对于开发环境,适合使用:eval:速度极快,但只能看到原始文件结构,看不到打包前的代码内容;cheap-eval-source-map:速度比较快,可以看到打包前的代码内容,但看不到 loader 处理之前的源码;cheap-module-eval-source-map:速度比较快,可以看到 loader 处理之前的源码,不过定位不到列级别;eval-source-map:初次编译较慢,但定位精度最高;对于生产环境,则适合使用:source-map:信息最完整,但安全性最低,外部用户可轻易获取到压缩、混淆之前的源码,慎重使用;hidden-source-map:信息较完整,安全性较低,外部用户获取到 .map文件地址时依然可以拿到源码,慎重使用;nosources-source-map:源码信息缺失,但安全性较高,需要配合 Sentry 等工具实现完整的 Sourcemap 映射。解决跨域

在开发过程中,我们势必会遇到跨域问题,对于本地开发我们一般可以通过配置代理来解决

我们先来简单写一个接口:

const express = require("express")const app = express()app.get("/api/getInfo", (req, res) => {    res.json({        code: 200,        data: {            name: "nanjiu",            age: 18        }    })})app.listen(3000, () => {    console.log("服务已启动~")})

然后把服务跑起来,再到vue项目中去调用

const getInfo = async () => {    try {        const res = await axios.get("http://localhost:3000/api/getInfo")        console.log(res)    } catch(err) {        console.log(err)    }}

这时候你会发现接口调用跨域了

配置代理

接着我们再来通过webpack配置代理解决跨域问题,由于我们本地使用了webpack-dev-server,所以我们可以直接通过它来配置

// webpack.config.jsmodule.exports = {  // ...  devServer: {    hot: true,    open: true,    proxy: {      "/api": "http://localhost:3000"    }  }}

这个时候我们的接口请求就正常了

由于篇幅问题,这篇文章就介绍到这里了,后面会接着更新webpack更多高级用法。

如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者,文章公众号首发,关注 前端南玖第一时间获取最新文章~

标签:

(责任编辑:)

相关文章

【webpack系列】从基础配置到掌握进阶用法_天天聚看点

​theme:fancyhighlight:atelier-dune-dark 前言本篇文章将介绍一些`web

2023-06-25 11:18:54

2023安徽池州市网络安全应急指挥中心招聘笔试成绩公告_天天热消息

​根据《2023年池州市网络安全应急指挥中心公开招聘工作人员公告》规定,

2023-06-25 10:54:00

永川:念好“多快好”三字经 打造营商环境最优区

​营商环境就是生产力,企业服务就是竞争力。近年来,永川区以打造营商环

2023-06-25 10:39:20

2023年6月25日麦芽糊精价格最新行情预测

​中国报告大厅2023年6月25日麦芽糊精价格最新走势监测显示:济南卓越化

2023-06-25 10:07:24

当前观点:妈妈情绪好 孩子能量足

​在一个家庭中,妈妈的情绪在很大程度上决定家庭的氛围和温度,对孩子的

2023-06-25 09:38:25

瓜果丰收 乐了萌娃

​近日,浙江省丽水市缙云县新区实验幼儿园的小朋友们在菜园里采摘瓜果。

2023-06-25 09:12:06

当前看点!建业地产:暂停向所有境外债权人进行支付

​建业地产:暂停向所有境外债权人进行支付

2023-06-25 08:49:00

环球时讯:破皮的伤口擦什么药愈合的快_破皮的伤口怎么处理

​1、首先你去药店买点酒精棉,和红药水也叫红汞,棉签,芦荟胶 先用酒精棉

2023-06-25 07:51:03

微资讯!张文宏:新冠仍奥密克戎,疫苗有作用

​6月23日,上海市科协青年科技论坛暨“FirstTalk”青年讲坛在上海举行。

2023-06-25 06:53:35

普里戈任称停止行进,调转方向返回营地 每日速读

​(总台记者王斌)​​​白俄罗斯总统府此前刚刚证实,24日,俄罗斯总统

2023-06-25 05:37:40

每日视讯:去沙特或美国?罗马诺:格列兹曼计划继续为马竞效力,他无意离队

​近日有媒体报道称,利雅得胜利有意引进格列兹曼,且和球员经纪人有过会

2023-06-25 02:53:11

家泰中央新风系统_关于家泰中央新风系统介绍 天天播报

​1、家泰中央新风系统。2、是一款通风换气系统。3、由高效风机、进风口

2023-06-25 00:59:52

当前观点:端午假期文旅消费场景丰富 市场活力进一步激发

​央广网北京6月24日消息据中央广播电视总台中国之声《新闻和报纸摘要》

2023-06-24 21:58:42

快消息!超搞笑网名五个字要谐音的那种_最新版好玩的谐音梗网名210个 比较搞笑幽默的网名

​比较幽默的人都会给自己取一个比较搞笑的网名,所以今天小编收集整理了

2023-06-24 20:53:28

关于高中生新学期学习计划 每日观点

​中生新学期学习计划篇1新学期开始了。对于刚升入高中的同学们来说要尽

2023-06-24 19:46:54

有机污染物化学·上册_对于有机污染物化学·上册简单介绍

​1、《有机污染物化学·上册》是科学出版社出版的图书。2、作者是王连生

2023-06-24 18:42:14

成都金熊猫中心_介绍下成都熊猫金卡 当前快讯

​想必现在有很多小伙伴对于介绍下成都熊猫金卡方面的知识都比较想要了解

2023-06-24 17:58:05

全球滚动:收腹带什么时候开始用_减肥用收腹带有用吗

​1 何时开始使用腹带:考虑到剖宫产产妇腹部伤口的原因,建议开始使用腹

2023-06-24 16:36:25

比较好养的陆龟品种_好养的陆龟有哪些品种_热文

​什么种类的乌龟好?河北省任丘市网友“小英云”最佳回答:1 赫尔曼乌龟

2023-06-24 15:47:08

眼尾下垂怎么调整_眼尾下垂怎么变上翘-全球观点

​1、所以线雕吸收后眼尾会再次下垂。一般线雕的效果可以持续半年左右,

2023-06-24 14:49:24

焦点热议:有人用过羽西的“白玲珑”系列吗_怎么样

​想必现在有很多小伙伴对于有人用过羽西的“白玲珑”系列吗怎么样方面的

2023-06-24 13:44:46

收方是什么意思

​1、收方全称工程收方,就是收工程量。2、因为工程中涉及最多的工程量单

2023-06-24 12:34:10

王德海烈士_王海青 革命烈士

​王海青,1911年生于山西省芮城县杨家庄村。他本姓杨,在幼儿时期即给王

2023-06-24 11:41:54

【环球财经】日本核心CPI连续21个月同比上升

​日本总务省23日公布的数据显示,日本5月去除生鲜食品后的核心消费价格

2023-06-24 10:45:09

他们把16岁少年背到山顶 全球时快讯

​他们把16岁少年背到山顶阳新,每一天的太阳都是新的,而在黄石阳新县,

2023-06-24 10:03:46

全国最大咖啡生豆分拨中心启用 昆山咖啡全产业链要素集聚

​“专门为咖啡生豆设计温度和湿度的恒温仓,能够最大限度地缩减生豆风味

2023-06-24 09:18:27

当前观察:都去干高技术,那谁去干技工?

​道远自迩我简单给几个建议:1 取消中考分流,改6+3九年制义务教育,为5

2023-06-24 08:32:49

婚后赌债离婚后要夫妻共同承担吗

​婚后赌债离婚后不需要夫妻共同承担,一般赌债属于个人债务,由个人承担

2023-06-24 07:20:17

精彩看点:手机信号差是手机哪里坏了(手机信号差)

​来为大家解答以上问题,手机信号差是手机哪里坏了,手机信号差很多人还

2023-06-24 06:11:27

苹果扩大的自修计划 iPhone14也可以了

​苹果公司正在扩大其自助维修计划,以涵盖其更多的最新设备,并在此过程

2023-06-24 05:33:22