1.概念

  1. [webpack5地址](https://webpack.docschina.org/)<br /> [从 v4 升级到 v5迁移](https://webpack.docschina.org/migrate/5/)

webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。可以将所有资源(包括Javascript,图像,字体和CSS等)打包后置于依赖关系中,构建成一个 依赖图(dependency graph)。将 Es Module 、 CommonJs 的语法处理成浏览器可以运行的代码,然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容image.png

  • Entry: 指定webpack开始构建的入口模块,从该模块开始构建并计算出直接或间接依赖的模块或者库。
  • Output:告诉webpack如何命名输出的文件以及输出的目录
  • Module: 模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
  • Chunk:coding split(代码分割)的产物,我们可以对一些代码打包成一个单独的chunk,比如某些公共模块,去重,更好的利用缓存。或者按需加载某些功能模块,优化加载时间。在webpack3及以前我们都利用CommonsChunkPlugin将一些公共代码分割成一个chunk,实现单独加载。在webpack4 中CommonsChunkPlugin被废弃,使用SplitChunksPlugin
  • Loader:模块转换器,用于把模块原内容按照需求转换成新内容。
  • Plugin:扩展插件,在 Webpack 构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件的发生,在特定时机做对应的事情。

mode
开发模式:能让代码本地调试的环境会将process.env.NODE_ENV = development.
生产模式:能让代码优化上线运行的环境。process.env.NODE_ENV = production.

webpack 的构建流程是什么

webpack5 - 图2

  • 初始化参数:解析webpack配置参数,合并shell传入和webpack.config.js文件配置的参数,形成最后的配置结果;
  • 开始编译:上一步得到的参数初始化compiler对象,注册所有配置的插件,插件监听webpack构建生命周期的事件节点,做出相应的反应,执行对象的run方法开始执行编译;
  • 确定入口:从配置的entry入口,开始解析文件构建AST语法树,找出依赖,递归下去;
  • 编译模块:递归中根据文件类型和loader配置,调用所有配置的loader对文件进行转换,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;
  • 完成模块编译并输出:递归完事后,得到每个文件结果,包含每个模块以及他们之间的依赖关系,根据entry或 码块chunk;
  • 输出完成:输出所有的chunk到文件系统

    webpack 打包是hash码是如何生成的

    1.webpack生态中存在多种计算hash的方式

  • hash

  • chunkhash
  • contenthash

hash代表每次webpack编译中生成的hash值,所有使用这种方式的文件hash都相同。每次构建都会使webpack计算新的hash。chunkhash基于入口文件及其关联的chunk形成,某个文件的改动只会影响与它有关联的chunk的hash值,不会影响其他文件contenthash根据文件内容创建。当文件内容发生变化时,contenthash发生变化

2.避免相同随机值

  • webpack在计算hash后分割chunk。产生相同随机值可能是因为这些文件属于同一个chunk,可以将某个文件提到独立的chunk(如放入entry)

2.Webpack5与webpack4的区别

1、Tree Shaking(树摇)

webpack4

作用: 如果我们的项目中引入了 lodash 包,但是我只有了其中的一个方法。其他没有用到的方法是不是冗余的?此时 tree-shaking 就可以把没有用的那些东西剔除掉,来减少最终的bundle体积。
usedExports : true, 标记没有用的叶子
minimize: true, 摇掉那些没有用的叶子

  1. // webpack.config.js中
  2. module.exports = {
  3. optimization: {
  4. usedExports: true, //只导出被使用的模块
  5. minimize : true // 启动压缩
  6. }
  7. }

由于 tree shaking 只支持 esmodule ,如果你打包出来的是 commonjs,此时 tree-shaking 就失效了。不过当前大家都用的是 vue,react 等框架,他们都是用 babel-loader 编译,以下配置就能够保证他一定是 esmodule
webpack5 - 图3

webpack5

webpack5的 mode=“production” 自动开启 tree-shaking

  • webpack5 以前,tree-shaking 比较简单,主要是找import进来的变量是否在这个模块内出现过,出现过则不剔除,不出现过则剔除。并且用于 esModule 中
  • webpack5,可以进行根据作用域之间的关系进行优化。比如:
    • a.js 中到处了两个方法 a 和 b,在 index.js 中引入了 a.js 到处的 a 方法,没有引用 b 方法。那么 webpack4 打包出来的结果包含了 index.js 和 a.js 的内容,包含了没有用到的 b 方法。但是 webpack5 的 treeshaking,会进行作用域分析,打包结果只有 index 和 a 文件中的 a 方法,没有用到的 b 方法是不会被打包进来的。
  • 所以:webpack4 的 treeshaking 是关注 import 了某个库的什么模块,那么我就打包什么;webpack5 更精细化,直接分析到哪些变量有效地用到了,那么我就打包哪些变量。

2、压缩代码

2.1 webpack4

webpack4 上需要下载安装 terser-webpack-plugin 插件,并且需要以下配置:

  1. const TerserPlugin = require('terser-webpack-plugin')
  2. module.exports = {
  3. // ...other config
  4. optimization: {
  5. minimize: !isDev,
  6. minimizer: [
  7. new TerserPlugin({
  8. extractComments: false,
  9. terserOptions: {
  10. compress: {
  11. pure_funcs: ['console.log']
  12. }
  13. }
  14. }) ]
  15. }

2.2 webpack5

内部本身就自带 js 压缩功能,他内置了 terser-webpack-plugin 插件,我们不用再下载安装。而且在 mode=“production” 的时候会自动开启 js 压缩功能。
如果你要在开发环境使用,就用下面:

  1. // webpack.config.js中
  2. module.exports = {
  3. optimization: {
  4. usedExports: true, //只导出被使用的模块
  5. minimize : true // 启动压缩
  6. }
  7. }

3、webpack 缓存

3.1 webpack4 缓存配置

支持缓存在内存中
npm install hard-source-webpack-plugin -D

  1. const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
  2. module.exports = {
  3. plugins: [
  4. // 其它 plugin...
  5. new HardSourceWebpackPlugin(),
  6. ] }

3.2 webpack5 缓存配置

webpack5 内部内置了 cache 缓存机制。直接配置即可。
cache 会在开发模式下被设置成 type: memory 而且会在生产模式把cache 给禁用掉。

  1. // webpack.config.js
  2. module.exports= {
  3. // 使用持久化缓存
  4. cache: {
  5. type: 'filesystem'
  6. cacheDirectory: path.join(__dirname, 'node_modules/.cac/webpack')
  7. }
  8. }

type 的可选值为: memory 使用内容缓存,filesystem 使用文件缓存。
当 type=filesystem的时候设置cacheDirectory才生效。用于设置你需要的东西缓存放在哪里

  • webpack会缓存生成的webpack模块和chunk,来改善构建速度
  • 缓存在webpack5中默认开启,缓存默认是在内存里,但可以对cache进行设置
  • webpack 追踪了每个模块的依赖,并创建了文件系统快照。此快照会与真实文件系统进行比较,当检测到差异时,将触发对应模块的重新构建

4、对loader的优化

webpack 4 加载资源需要用不同的 loader

  • raw-loader 将文件导入为字符串
  • url-loader 将文件作为 data url 内联到 bundle文件中(加载图片与file-loader区别在可以配置是否转换base64URI,优点在于可以减少http请求)
  • file-loader 将文件发送到输出目录中

webpack5 - 图4
webpack5 的资源模块类型替换 loader

  • asset/resource 替换 file-loader(发送单独文件)
  • asset/inline 替换 url-loader (导出 url)
  • asset/source 替换 raw-loader(导出源代码)
  • asset

webpack5 - 图5
webpack5

5、启动服务的差别

1.webpack4 启动服务

通过 webpack-dev-server 启动服务

2.webpack5 启动服务

内置使用 webpack serve 启动,但是他的日志不是很好,所以一般都加都喜欢用 webpack-dev-server 优化。

6.devtool的差别

sourceMap需要在 webpack.config.js里面直接配置 devtool 就可以实现了。而 devtool有很多个选项值,不同的选项值,不同的选项产生的 .map 文件不同,打包速度不同。
一般情况下,我们一般在开发环境配置用“cheap-eval-module-source-map”,在生产环境用‘none’。
devtool在webpack4和webpack5上也是有区别的
v4: devtool: ‘cheap-eval-module-source-map’
v5: devtool: ‘eval-cheap-module-source-map’
接下来,我们稍微总结一下:

devtool build rebuild 显示代码 SourceMap 文件 描述
(none) 很快 很快 无法定位错误
eval 很快(cache) 编译后 定位到文件
source-map 很慢 很慢 源代码 定位到行列
eval-source-map 很慢 一般(cache) 编译后 有(dataUrl) 定位到行列
eval-cheap-source-map 一般 快(cache) 编译后 有(dataUrl) 定位到行
eval-cheap-module-source-map 快(cache) 源代码 有(dataUrl) 定位到行
inline-source-map 很慢 很慢 源代码 有(dataUrl) 定位到行列
hidden-source-map 很慢 很慢 源代码 无法定位错误
nosource-source-map 很慢 很慢 源代码 定位到文件

对照一下校验规则 ^(inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map$ 分析一下关键字

关键字 描述
inline 代码内通过 dataUrl 形式引入 SourceMap
hidden 生成 SourceMap 文件,但不使用
eval eval(…) 形式执行代码,通过 dataUrl 形式引入 SourceMap
nosources 不生成 SourceMap
cheap 只需要定位到行信息,不需要列信息
module 展示源代码中的错误位置

官方:https://webpack.js.org/configuration/devtool/

7.热更新差别

热更新原理:其实是自己开启了express应用,添加了对webpack编译的监听,添加了和浏览器的websocket长连接,当文件变化触发webpack进行编译并完成后,会通过sokcet消息告诉浏览器准备刷新。而为了减少刷新的代价,就是不用刷新网页,而是刷新某个模块,webpack-dev-server可以支持热更新,通过生成 文件的hash值来比对需要更新的模块,浏览器再进行热替换

webpack4设置
webpack5 - 图6
webpack5 设置
如果你使用的是bable6,按照上述设置,你会发现热更新无效,需要添加配置:

  1. module.hot.accept('需要热启动的文件',(source)=>{
  2. //自定义热启动
  3. })

3.webpack5 打包优化

webpack从主要配置(entry、output、resolve、module、performance、externals、module、plugins,其他)进行优化

oneOf

每个不同类型的文件在loader转换时,会遍历module中rules中所有loader,即使已经匹配到某个规则了也会继续向下匹配。而如果将规则放在 oneOf 属性中,则一旦匹配到某个规则后,就停止匹配了

  1. rules:[
  2. {
  3. test: /\.js$/,
  4. exclude: /node_modules/,
  5. loader: "eslint-loader",
  6. },
  7. {
  8. // 以下loader一种文件只会匹配一个
  9. oneOf: [
  10. // 不能有两个配置处理同一种类型文件,如果有,另外一个规则要放到外面。
  11. {
  12. test: /\.js$/,
  13. exclude: /node_modules/,
  14. use: [
  15. {
  16. loader: "babel-loader",
  17. },
  18. ],
  19. },
  20. {
  21. test: /\.css$/,
  22. use: [
  23. "style-loader",
  24. "css-loader",
  25. ],
  26. },
  27. ],
  28. },
  29. ]

使用新增cache属性,缓存进行优化(推荐)

通过配置 webpack 持久化缓存cache: filesystem,来缓存生成的 webpack 模块和 chunk,改善构建速度。
简单来说,通过 cache: filesystem 可以将构建过程的 webpack 模板进行缓存,大幅提升二次构建速度、打包速度,当构建突然中断,二次进行构建时,可以直接从缓存中拉取,可提速 90% 左右。

  1. module.exports = {
  2. cache: {
  3. type: 'filesystem', // 使用文件缓存
  4. },
  5. }

module 部分优化

  • include和exclude:排除不需要处理loader文件(exclude优先include)

    1. rules: [
    2. {
    3. test: /.ext$/,
    4. include: path.resolve('src'),
    5. },
    6. ],

    压缩

  • optimize-css-assets-webpack-plugin(推荐):对进行css压缩

    1. module.exports = {
    2. optimization: {
    3. minimize: true,
    4. minimizer: [
    5. new OptimizeCSSAssetsPlugin({
    6. assetNameRegExp: /\.css$/,
    7. safe: true,
    8. cache: true,
    9. parallel: true,
    10. discardComments: {
    11. removeAll: true,
    12. },
    13. }),
    14. ],
    15. },
    16. };

    其他优化项

  • 使用mode属性

  • purgecss-webpack-plugin : 进行CSS文件进行Tree-Shaking (推荐,css文件可能会有大幅降低)
  • esbuild-loader: 相比babel-loader速度更快

    4.webpack5 如何编写plugin

    webpack 插件由以下组成:

  • 一个 JavaScript 命名函数。

  • 在插件函数的 prototype 上定义一个 apply 方法。
  • 指定一个绑定到 webpack 自身的事件钩子
  • 处理 webpack 内部实例的特定数据。
  • 功能完成后调用 webpack 提供的回调。

  • webpack本质是一个事件流机制,核心模块:tabable(Sync + Async)Hooks 构造出 === Compiler(编译) + Compiletion(创建bundles)

  • compiler对象代表了完整的webpack环境配置。这个对象在启动webpack时被一次性建立,并配置好所有可操作的设置,包括options、loader和plugin。当在webpack环境中应用一插件时,插件将收到此compiler对象的引用。可以使用它来访问webpack的主环境
  • compilation对象代表了一次资源版本构建。当运行webpack开发环境中间件时,每当检测到一个文件变化,就会创建一个新的compilation,从而生成一个新的编译资源。一个compilation对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态的信息。compilation对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用
  • 创建一个插件函数,在其prototype上定义apply方法,指定一个webpack自身的事件钩子
  • 函数内部处理webpack内部实例的特定数据
  • 处理完成后,调用webpack提供的回调函数
  1. class MyPlugin {
  2. apply(compiler) {
  3. console.log("MyPlugin 启动");
  4. // emit钩子的执行时机是:输出打包好的资源文件 asset 到 output 目录之前执行。
  5. compiler.hooks.afterCompile.tap("MyPlugin", (compilation) => {
  6. // compilation.assets => 获取dist目录的所有生成的资源文件信息,例如:bundle.js
  7. // console.info('compilation.assets',compilation.assets)
  8. for (const name in compilation.assets) {
  9. // 获取到资源的内容,例如:bundle.js里面的内容
  10. // 判断文件是否为index.html文件
  11. if (name === "index.html") {
  12. // 替换掉script文件中的注释
  13. const contents = compilation.assets[name].source();
  14. const newContents = contents.replace(
  15. /<script [^>]*src=['"]([^'"]+)[^>]*>/gi,
  16. function (match, capture) {
  17. return `<script src="${capture}?${new Date().getTime()}"> `;
  18. }
  19. );
  20. const withoutComments = `${newContents}`;
  21. // 覆盖原有内容
  22. compilation.assets[name] = {
  23. source: () => withoutComments, // 新的内容
  24. size: () => withoutComments.length, // 内容的大小,webpack必须的方法
  25. };
  26. }
  27. }
  28. });
  29. }
  30. }
  31. module.exports = MyPlugin;

https://www.webpackjs.com/contribute/writing-a-plugin/#compiler-%E5%92%8C-compilation

4.webpack5 与其他打包工具的区别

image.png

#一、模块化工具

模块化是一种处理复杂系统分解为更好的可管理模块的方式
可以用来分割,组织和打包应用。每个模块完成一个特定的子功能,所有的模块按某种方法组装起来,成为一个整体(bundle)
在前端领域中,并非只有webpack这一款优秀的模块打包工具,还有其他类似的工具,例如Rollup、Parcel、snowpack,以及最近风头无两的Vite
通过这些模块打包工具,能够提高我们的开发效率,减少开发成本
这里没有提及gulp、grunt是因为它们只是定义为构建工具,不能类比

#Rollup

Rollup 是一款 ES Modules 打包器,从作用上来看,Rollup 与 Webpack 非常类似。不过相比于 Webpack,Rollup要小巧的多
现在很多我们熟知的库都都使用它进行打包,比如:Vue、React和three.js等
举个例子:

  1. // ./src/messages.js
  2. export default {
  3. hi: 'Hey Guys, I am zce~'
  4. }
  5. // ./src/logger.js
  6. export const log = msg => {
  7. console.log('---------- INFO ----------')
  8. console.log(msg)
  9. console.log('--------------------------')
  10. }
  11. export const error = msg => {
  12. console.error('---------- ERROR ----------')
  13. console.error(msg)
  14. console.error('---------------------------')
  15. }
  16. // ./src/index.js
  17. import { log } from './logger'
  18. import messages from './messages'
  19. log(messages.hi)

然后通过rollup进行打包

打包结果如下图image.png
可以看到,代码非常简洁,完成不像webpack那样存在大量引导代码和模块函数
并且error方法由于没有被使用,输出的结果中并无error方法,可以看到,rollup默认开始Tree-shaking 优化输出结果
优点:

  • 代码效率更简洁、效率更高
  • 默认支持 Tree-shaking

缺点:
加载其他类型的资源文件或者支持导入 CommonJS 模块,又或是编译 ES 新特性,这些额外的需求 Rollup需要使用插件去完成

综合来看,rollup并不适合开发应用使用,因为需要使用第三方模块,而目前第三方模块大多数使用CommonJs方式导出成员,并且rollup不支持HMR,使开发效率降低
但是在用于打包JavaScript 库时,rollup比 webpack 更有优势,因为其打包出来的代码更小、更快,其存在的缺点可以忽略

#Parcel

Parcel ,是一款完全零配置的前端打包器,它提供了 “傻瓜式” 的使用体验,只需了解简单的命令,就能构建前端应用程序
Parcel 跟 Webpack 一样都支持以任意类型文件作为打包入口,但建议使用HTML文件作为入口,该HTML文件像平时一样正常编写代码、引用资源。如下所示:

  1. <!-- ./src/index.html -->
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>Parcel Tutorials</title>
  7. </head>
  8. <body>
  9. <script src="main.js"></script>
  10. </body>
  11. </html>

main.js文件通过ES Moudle方法导入其他模块成员

  1. // ./src/main.js
  2. import { log } from './logger'
  3. log('hello parcel')
  4. // ./src/logger.js
  5. export const log = msg => {
  6. console.log('---------- INFO ----------')
  7. console.log(msg)
  8. }

运行之后,使用命令打包
npx parcel src/index.html

执行命令后,Parcel不仅打包了应用,同时也启动了一个开发服务器,跟webpack Dev Server一样
跟webpack类似,也支持模块热替换,但用法更简单
同时,Parcel有个十分好用的功能:支持自动安装依赖,像webpack开发阶段突然使用安装某个第三方依赖,必然会终止dev server然后安装再启动。而Parcel则免了这繁琐的工作流程
同时,Parcel能够零配置加载其他类型的资源文件,无须像webpack那样配置对应的loader
打包命令如下:
npx parcel src/index.html

由于打包过程是多进程同时工作,构建速度会比Webpack 快,输出文件也会被压缩,并且样式代码也会被单独提取到单个文件中
image.png
可以感受到,Parcel给开发者一种很大的自由度,只管去实现业务代码,其他事情用Parcel解决

#Vite

vite ,是一种新型前端构建工具,能够显著提升前端开发体验
它主要由两部分组成:

  • 一个开发服务器,它基于 原生 ES 模块 提供了丰富的内建功能,如速度快到惊人的 [模块热更新HMR
  • 一套构建指令,它使用 Rollup打包你的代码,并且它是预配置的,可以输出用于生产环境的优化过的静态资源

其作用类似webpack+ webpack-dev-server,其特点如下:

  • 快速的冷启动
  • 即时的模块热更新
  • 真正的按需编译

vite会直接启动开发服务器,不需要进行打包操作,也就意味着不需要分析模块的依赖、不需要编译,因此启动速度非常快
利用现代浏览器支持ES Module的特性,当浏览器请求某个模块的时候,再根据需要对模块的内容进行编译,这种方式大大缩短了编译时间
原理图如下所示:
image.png
在热模块HMR方面,当修改一个模块的时候,仅需让浏览器重新请求该模块即可,无须像webpack那样需要把该模块的相关依赖模块全部编译一次,效率更高

#webpack

相比上述的模块化工具,webpack大而全,很多常用的功能做到开箱即用。有两大最核心的特点:一切皆模块按需加载
与其他构建工具相比,有如下优势:

  • 智能解析:对 CommonJS 、 AMD 、ES6 的语法做了兼容
  • 万物模块:对 js、css、图片等资源文件都支持打包
  • 开箱即用:HRM、Tree-shaking等功能
  • 代码分割:可以将代码切割成不同的 chunk,实现按需加载,降低了初始化时间
  • 插件系统,具有强大的 Plugin 接口,具有更好的灵活性和扩展性
  • 易于调试:支持 SourceUrls 和 SourceMaps
  • 快速运行:webpack 使用异步 IO 并具有多级缓存,这使得 webpack 很快且在增量编译上更加快
  • 生态环境好:社区更丰富,出现的问题更容易解决
  1. /**、webpack 多环境配置 webpack merge*/
  2. const { resolve } = require("path");
  3. /**生成html,并把打包的js插入 */
  4. const HtmlWebpackPlugin = require("html-webpack-plugin");
  5. /**css单独提取*/
  6. const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  7. /**css压缩*/
  8. const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
  9. /**html压缩*/
  10. const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
  11. /**eslint*/
  12. const ESLintPlugin = require("eslint-webpack-plugin");
  13. const commonCss = [MiniCssExtractPlugin.loader, "css-loader"];
  14. const isProMode = process.env.NODE_ENV !== "production";
  15. console.log("isProMode", process.env.NODE_ENV);
  16. module.exports = {
  17. /**模式 development或者production */
  18. mode: "development",
  19. target: "web",
  20. /**入口文件 */
  21. // entry: ["./src/index.js", "./src/index.html"],
  22. entry: {
  23. index: "./src/index.js",
  24. app: {
  25. dependOn: "index",
  26. import: "./src/app.js",
  27. },
  28. },
  29. /**输出文件 */
  30. output: {
  31. filename: "[name].[hash:8].js",
  32. path: resolve(__dirname, "dist"),
  33. /**清除了dist 代替了html-clean-plugin */
  34. clean: true,
  35. },
  36. /**模块loader */
  37. module: {
  38. rules: [
  39. /**将 css-loader转换并插入js style-loader将js中的css通过style插入*/
  40. // test: /\.css$/i,
  41. // use: ["style-loader", "css-loader"],
  42. {
  43. test: /\.css$/,
  44. use: [
  45. // MiniCssExtractPlugin.loader的作用就是把css-loader处理好的样式资源(js文件内),单独提取出来 成为css样式文件
  46. //生产环境下使用,开发环境还是推荐使用style-loader
  47. isProMode ? MiniCssExtractPlugin.loader : "style-loader",
  48. "css-loader",
  49. {
  50. //css的兼容性处理
  51. loader: "postcss-loader",
  52. options: {
  53. /**设置 PostCSS 选项与插件*/
  54. postcssOptions: {
  55. plugins: [["postcss-preset-env"]],
  56. // 如果你在 JS 文件中编写样式,请使用 postcss-js parser,并且添加 execute 选项。
  57. // parser: "postcss-js",
  58. // execute: true,
  59. },
  60. },
  61. },
  62. ],
  63. },
  64. {
  65. test: /\.less$/,
  66. use: [
  67. isProMode ? MiniCssExtractPlugin.loader : "style-loader",
  68. "css-loader",
  69. "less-loader",
  70. ],
  71. },
  72. {
  73. test: /\.m?js$/,
  74. exclude: /(node_modules|bower_components)/,
  75. use: {
  76. loader: "babel-loader",
  77. options: {
  78. presets: ["@babel/preset-env"],
  79. },
  80. },
  81. },
  82. /**处理图片文件*/
  83. {
  84. test: /\.(jpg|png|jpeg|gif)$/,
  85. loader: "asset/inline",
  86. options: {
  87. /**图片文件大小*/
  88. limit: 10 * 1024,
  89. /**node是command打包 关闭esModule打包*/
  90. esModule: false,
  91. /**文件名称*/
  92. name: "[name][hash:8][ext]",
  93. },
  94. },
  95. /**处理html中图片文件*/
  96. {
  97. test: /\.html$/,
  98. loader: "html-loader",
  99. },
  100. /**处理文件的路径并输出文件到输出目录 */
  101. // {
  102. // exclude: /\.(html|jpg|png|jpeg|gif|less|css)$/,
  103. // loader: "asset",
  104. // },
  105. ],
  106. },
  107. plugins: [
  108. /**以哪个html作为模板进入打包*/
  109. new HtmlWebpackPlugin({
  110. template: "./src/index.html",
  111. }),
  112. /**提取js里面的文件到css文件*/
  113. new MiniCssExtractPlugin({
  114. filename: "css/[name].css",
  115. }),
  116. new ESLintPlugin(),
  117. ],
  118. optimization: {
  119. minimize: true,
  120. minimizer: [
  121. // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
  122. new CssMinimizerPlugin(),
  123. new HtmlMinimizerPlugin(),
  124. ],
  125. },
  126. /**本地服务器*/
  127. devServer: {
  128. /**监听打包的文件夹*/
  129. static: {
  130. directory: resolve(__dirname, "dist"),
  131. },
  132. /**热更新 会造成html改变不更新 所以将入口增加html*/
  133. hot: true,
  134. port: 8080,
  135. /**压缩文件*/
  136. compress: true,
  137. open: true,
  138. watchFiles: ["./src/index.html"],
  139. },
  140. };