webpack5从入门到精通

news2024/10/7 8:20:19

前言

webpack是什么?

摘自官网的一段话:webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。
官网链接:https://webpack.docschina.org/concepts/

为什么需要打包程序

在日常的开发中,我们会使用框架(React、Vue),ES6 模块化语法,Less/Sass 等 css 预处理器等语法进行开发。这样的代码要想在浏览器运行必须经过编译成浏览器能识别的 JS、Css 等语法,才能运行,所以我们需要打包工具帮我们做完这些事。除此之外,打包工具还能压缩代码、做兼容性处理、提升代码性能等。

正文

概念

在这里我将webpack为了几个要点,也是webpack核心的几个点

  1. entry(入口)
    需要打包的入口文件,可以为一个入口,也可以为多个入口(有几个入口就有几个输出),Webpack 本身功能比较少,只能处理 js 资源,一旦遇到 css 等其他资源就会报错
  2. output(输出)
    可以通过配置 output 选项,告知 webpack 如何向硬盘写入编译文件。注意,即使可以存在多个 entry 起点,但只能指定一个 output 配置。
  3. loaders(模块解析器)
    loader 用于对模块的源代码进行转换。loader 可以使你在 import 或 “load(加载)” 模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的得力方式。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript 或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS 文件!
  4. Plugins(插件)
    插件 是 webpack 的 支柱 功能。Webpack 自身也是构建于你在 webpack 配置中用到的 相同的插件系统 之上!插件目的在于解决 loader 无法实现的其他事
  5. mode(模式)
    指示 Webpack 使用相应模式的配置。
    development 开发模式:会将 process.env.NODE_ENV 的值设为 development。启用 NameChunksPlugin 和 NameModulesPlugin。特点是能让代码本地调试运行的环境。
    production 生产模式:会将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin。特点是能让代码优化上线运行的环境。

起步

新建文件,创建一个新的项目

npm init -y

下载我们的依赖

npm i webpack webpack-cli -D

构建项目目录文件

webpack_document # 项目根目录(所有指令必须在这个目录运行)
    └── src # 项目源码目录
        ├── js # js文件目录
        │   ├── count.js
        │   └── sum.js
        ├── css # css文件目录
        └── index.js # 项目主文件

创建我们的配置文件webpack.config.js

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        // clean清楚上一次的打包结果
        clean: true,
        // 输出的文件名字
        filename: 'index.js'
    },
    // 解析器
    module: {

    },
    plugins: [],
    mode: 'production'
}

运行指令

npx webpack

观察生成的dist的文件,就是我们打包后的文件了
Webpack 将来都通过 webpack.config.js 文件进行配置,来增强 Webpack 的功能

开发模式介绍

开发模式顾名思义就是我们开发代码时使用的模式。
这个模式下我们主要做两件事:

  • 编译代码,使浏览器能识别运行开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源
  • 代码质量检查,树立代码规范提前检查代码的一些隐患,让代码运行时能更加健壮。提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。

处理样式资源

由于webpack只能处理js、json文件,并不能处理css文件,所以我们需要借助相应loader解析器来增强我们的功能,在webpack的官网中,为我们提供了常用的loader,如果不能满足我们的日常需要,也可以到社区中去寻找想要的loader [webpack官网loader]

处理css资源

下载

// 下载css-loader style-loader
npm i css-loader style-loader -D

说明

  • css-loader:负责将 Css 文件编译成 Webpack 能识别的模块
  • style-loader:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容
    此时样式就会以 Style 标签的形式在页面上生效

配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: 'index.js'
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader"],
            },
        ]
    },
    plugins: [],
    mode: 'production'
}

使用
在src目录下创建我们的css文件,并在index.js中进行引入,然后进行打包,观察我们的dist文件里面的输出结果
为了方便我们观察效果,我们创建我们静态页面,并引入我们打包后dist文件下面的js文件,文件目录结构如下
![在这里插入图片描述](https://img-blog.csdnimg.cn/144dbdcc2fd44e758131b84f535aa8fc.png
页面效果如下:
在这里插入图片描述

处理less资源

下载

// 这里我们前面下载过style-loader 和 css-loader 了,这里就不需要下载
npm i less-loader -D

说明

  • less-loader:负责将 Less 文件编译成 Css 文件

配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: 'index.js'
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader"],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader,再写less-loader
                use: ["style-loader", "css-loader", "less-loader"],
            }
        ]
    },
    plugins: [],
    mode: 'production'
}

使用
在src目录下,创建我们的less文件夹,并生成index.less文件,写入样式,在index.js,引入我们的less文件,然后在pubilc的index.html文件中,创建对应的box文件,执行npx webpack,观察打包后的结果
在这里插入图片描述
页面效果如下:
在这里插入图片描述

处理sass/scss资源

下载

npm i sass-loader sass -D

说明

  • sass-loader:负责将 Sass 文件编译成 css 文件
  • sass:sass-loader 依赖 sass 进行编译

配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: 'index.js'
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader"],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader", "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: ["style-loader", "css-loader", "sass-loader"],
            },
        ]
    },
    plugins: [],
    mode: 'production'
}

使用
在src目录下,创建我们的sass文件夹,并生成index.sass 和 index.scss 文件,写入样式,在index.js,引入我们的sass、scss文件,然后在pubilc的index.html文件中,创建对应的box文件,执行npx webpack,观察打包后的结果
在这里插入图片描述
页面效果如下:
在这里插入图片描述

处理 Styl 资源

npm i stylus-loader -D

说明

  • stylus-loader:负责将 Styl 文件编译成 Css 文件

配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: 'index.js'
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader"],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader", "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: ["style-loader", "css-loader", "sass-loader"],
            },
            {
                test: /\.styl$/,
                use: ["style-loader", "css-loader", "stylus-loader"],
            },
        ]
    },
    plugins: [],
    mode: 'production'
}

使用

在src目录下,创建我们的styl文件夹,并生成index.styl 和 index.styl 文件,写入样式,在index.js,引入我们的styl文件,然后在pubilc的index.html文件中,创建对应的box文件,执行npx webpack,观察打包后的结果
在这里插入图片描述
页面效果如下:
在这里插入图片描述

资源模块

以下摘自官网的一段话
资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。
在 webpack 5 之前,通常使用:

raw-loader 将文件导入为字符串
url-loader 将文件作为 data URI 内联到 bundle 中
file-loader 将文件发送到输出目录

资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:

asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。

当在 webpack 5 中使用旧的 assets loader(如 file-loader/url-loader/raw-loader 等)和 asset 模块时,你可能想停止当前 asset 模块的处理,并再次启动处理,这可能会导致 asset 重复,你可以通过将 asset 模块的类型设置为 ‘javascript/auto’ 来解决。

处理图片资源

配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: 'index.js'
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader"],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader", "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: ["style-loader", "css-loader", "sass-loader"],
            },
            {
                test: /\.styl$/,
                use: ["style-loader", "css-loader", "stylus-loader"],
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
            },
        ]
    },
    plugins: [],
    mode: 'production'
}

使用

在src目录下,创建我们的images文件夹,添加图片文件,笔者这里添加了jpe,png,gif三种格式的图片,分别在不同的样式中进行引入,执行npx webpack,观察打包后的结果

此时如果查看 dist 目录的话,会发现多了三张图片资源
因为 Webpack 会将所有打包好的资源输出到 dist 目录下
为什么样式资源没有呢?
因为经过 style-loader 的处理,样式资源打包到 main.js 里面去了,所以没有额外输出出来

在这里插入图片描述

页面效果
在这里插入图片描述

图片资源处理优化

将小于某个大小的图片转化成 data URI 形式(Base64 格式)

优点:减少请求数量
缺点:体积变得更大,但是10kb以下的图片,转换为base64格式的情形下,只有增加1-2kb(所以我们出来10kb以下的)

配置

       {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                }
            },

修改输出资源的名称和路径

我们发现打包完成后,图片直接输出到dist的根目录下了,没有规范起来,我们希望输出到dist的static/images目录下,同时js文件输出到dist的static/js目录下,这样就比较规范了
配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: "static/js/index.js", // 将 js 文件输出到 static/js 目录中
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader"],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader", "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: ["style-loader", "css-loader", "sass-loader"],
            },
            {
                test: /\.styl$/,
                use: ["style-loader", "css-loader", "stylus-loader"],
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                },
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                },
            },
        ]
    },
    plugins: [],
    mode: 'production'
}

使用
通过以上配置后,dist文件输出的文件被规范起来了,这个时候需要修改一下我们index.html的引入路径,打开页面也是同样的效果
在这里插入图片描述

处理字体图标资源

当我们在项目中使用字体图标的时候,我们也希望打包的时候,将这一部分内容进行打包输出
配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: "static/js/index.js", // 将 js 文件输出到 static/js 目录中
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader"],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader", "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: ["style-loader", "css-loader", "sass-loader"],
            },
            {
                test: /\.styl$/,
                use: ["style-loader", "css-loader", "stylus-loader"],
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                },
                // 可以使用 module.generator 在一个地方配置所有生成器的选项
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                },
            },
            {
                test: /\.(ttf|woff2?|svg)$/,
                //  发送一个单独的文件并导出 URL
                type: "asset/resource",
                generator: {
                    filename: "static/media/[hash:8][ext][query]",
                },
            },
        ]
    },
    plugins: [],
    mode: 'production'
}

使用
在src目录下,创建我们的fonts文件夹,在阿里巴巴适量库中下载字体图标(笔者这里为了演示,使用的是font-class的形式),然后引入到fonts文件夹中,在index.js,然后在pubilc的index.html文件中,创建对应的span标签,添加class类名,执行npx webpack,观察打包后的结果
在这里插入图片描述
页面效果
在这里插入图片描述

处理其他资源

开发中可能还存在一些其他资源,如音视频等,我们也一起处理了

就是在处理字体图标资源基础上增加其他文件类型,统一处理即可

配置

    {
        // 如果有其他资源,在这里的正则里面添加即可
        test: /\.(ttf|woff2?|map4|map3|avi)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },

js资源处理

这里有同学可能会问,js 资源 Webpack 不能已经处理了吗,为什么我们还要处理呢?
原因是 Webpack 对 js 处理是有限的,只能编译 js 中 ES 模块化语法,不能编译其他语法,导致 js 不能在 IE 等浏览器运行,所以我们希望做一些兼容性处理。
其次开发中,团队对代码格式是有严格要求的,我们不能由肉眼去检测代码格式,需要使用专业的工具来检测。
针对 js 兼容性处理,我们使用 Babel 来完成
针对代码格式,我们使用 Eslint 来完成
我们先完成 Eslint,检测代码格式无误后,在由 Babel 做代码兼容性处理

ESLint

介绍
简介:可组装的 JavaScript 和 JSX 检查工具。
这句话意思就是:它是用来检测 js 和 jsx 语法的工具,可以配置各项功能
我们使用 Eslint,关键是写 Eslint 配置文件,里面写上各种 rules 规则,将来运行 Eslint 时就会以写的规则对代码进行检查
配置文件
配置文件由很多种写法:

.eslintrc.*:新建文件,位于项目根目录
.eslintrc
.eslintrc.js
.eslintrc.json
区别在于配置格式不一样
package.json 中 eslintConfig:不需要创建文件,在原有文件基础上写
ESLint 会查找和自动读取它们,所以以上配置文件只需要存在一个即可

具体配置
我们以.eslintrc.js为例子进行配置
具体eslint的配置参考官网和规则文档,这里给出相关链接
ESlint规则
ESlint官网

// .eslintrc.js
module.exports = {
    // 继承 Eslint 规则
    extends: ["eslint:recommended"],
    env: {
        node: true, // 启用node中全局变量
        browser: true, // 启用浏览器中全局变量
    },
    parserOptions: {
        ecmaVersion: 6,
        sourceType: "module",
    },
    rules: {
        "no-var": 2, // 不能使用 var 定义变量
    },
};

下载

npm i eslint-webpack-plugin eslint -D

在webpack中使用

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')
const ESLintWebpackPlugin = require("eslint-webpack-plugin");

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: "static/js/index.js", // 将 js 文件输出到 static/js 目录中
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader"],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader", "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: ["style-loader", "css-loader", "sass-loader"],
            },
            {
                test: /\.styl$/,
                use: ["style-loader", "css-loader", "stylus-loader"],
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                },
                // 可以使用 module.generator 在一个地方配置所有生成器的选项
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                },
            },
            {
                test: /\.(ttf|woff2?|svg)$/,
                //  发送一个单独的文件并导出 URL
                type: "asset/resource",
                generator: {
                    filename: "static/media/[hash:8][ext][query]",
                },
            },
        ]
    },
    plugins: [
        new ESLintWebpackPlugin({
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "src"),
        })
    ],
    mode: 'production'
}

vsocde安装eslint插件
安装eslint插件后,配置需要忽略检查的文件

// .eslintignore
# 忽略dist目录下所有文件
dist

Babel

介绍
JavaScript 编译器。
主要用于将 ES6 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中

配置文件

配置文件由很多种写法:

babel.config.*:新建文件,位于项目根目录
babel.config.js
babel.config.json
.babelrc.*:新建文件,位于项目根目录
.babelrc
.babelrc.js
.babelrc.json
package.json 中 babel:不需要创建文件,在原有文件基础上写
Babel 会查找和自动读取它们,所以以上配置文件只需要存在一个即可

具体配置
我们以babel.config.js为例子

// babel.config.js
module.exports = {
    // 预设
    presets: [],
};
presets 预设
简单理解:就是一组 Babel 插件, 扩展 Babel 功能
@babel/preset-env: 一个智能预设,允许您使用最新的 JavaScript。
@babel/preset-react:一个用来编译 React jsx 语法的预设
@babel/preset-typescript:一个用来编译 TypeScript 语法的预设

下载

npm i babel-loader @babel/core @babel/preset-env -D

配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')
const ESLintWebpackPlugin = require("eslint-webpack-plugin");

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: "static/js/index.js", // 将 js 文件输出到 static/js 目录中
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader"],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader", "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: ["style-loader", "css-loader", "sass-loader"],
            },
            {
                test: /\.styl$/,
                use: ["style-loader", "css-loader", "stylus-loader"],
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                },
                // 可以使用 module.generator 在一个地方配置所有生成器的选项
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                },
            },
            {
                test: /\.(ttf|woff2?|svg)$/,
                //  发送一个单独的文件并导出 URL
                type: "asset/resource",
                generator: {
                    filename: "static/media/[hash:8][ext][query]",
                },
            },
            {
                test: /\.js$/,
                exclude: /node_modules/, // 排除node_modules代码不编译
                loader: "babel-loader",
            },
        ]
    },
    plugins: [
        new ESLintWebpackPlugin({
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "src"),
        })
    ],
    mode: 'production'
}

HTML资源处理

在实际的开发工作中,我们希望使用一个html模块,然后将我们打包后的js文件自动引入到html模版中,这样我们开发的时候就不用手动引入或者修改打包后的文件了

插件

下载

npm i html-webpack-plugin -D

配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: "static/js/index.js", // 将 js 文件输出到 static/js 目录中
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader"],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader", "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: ["style-loader", "css-loader", "sass-loader"],
            },
            {
                test: /\.styl$/,
                use: ["style-loader", "css-loader", "stylus-loader"],
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                },
                // 可以使用 module.generator 在一个地方配置所有生成器的选项
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                },
            },
            {
                test: /\.(ttf|woff2?|svg)$/,
                //  发送一个单独的文件并导出 URL
                type: "asset/resource",
                generator: {
                    filename: "static/media/[hash:8][ext][query]",
                },
            },
            {
                test: /\.js$/,
                exclude: /node_modules/, // 排除node_modules代码不编译
                loader: "babel-loader",
            },
        ]
    },
    plugins: [
        new ESLintWebpackPlugin({
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "src"),
        }),
        new HtmlWebpackPlugin({
            // 以 public/index.html 为模板创建文件
            // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
            template: path.resolve(__dirname, "public/index.html"),
        })
    ],
    mode: 'production'
}

css资源处理

Css 文件目前被打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式
这样对于网站来说,会出现闪屏现象,用户体验不好
我们应该是单独的 Css 文件,通过 link 标签加载性能才好

提取css为单独文件

下载插件

npm i mini-css-extract-plugin -D

配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: "static/js/index.js", // 将 js 文件输出到 static/js 目录中
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: [MiniCssExtractPlugin.loader, "css-loader"],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
            },
            {
                test: /\.styl$/,
                use: [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"],
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                },
                // 可以使用 module.generator 在一个地方配置所有生成器的选项
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                },
            },
            {
                test: /\.(ttf|woff2?|svg)$/,
                //  发送一个单独的文件并导出 URL
                type: "asset/resource",
                generator: {
                    filename: "static/media/[hash:8][ext][query]",
                },
            },
            {
                test: /\.js$/,
                exclude: /node_modules/, // 排除node_modules代码不编译
                loader: "babel-loader",
            },
        ]
    },
    plugins: [
        new ESLintWebpackPlugin({
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "src"),
        }),
        new HtmlWebpackPlugin({
            // 以 public/index.html 为模板创建文件
            // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
            template: path.resolve(__dirname, "public/index.html"),
        }),
        // 提取css成单独文件
        new MiniCssExtractPlugin({
            // 定义输出文件名和目录
            filename: "static/css/index.css",
        }),
    ],
    mode: 'production'
}

css兼容性处理

下载

npm i postcss-loader postcss postcss-preset-env -D

配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: "static/js/index.js", // 将 js 文件输出到 static/js 目录中
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: [MiniCssExtractPlugin.loader, "css-loader", {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: [
                                "postcss-preset-env", // 能解决大多数样式兼容性问题
                            ],
                        },
                    },
                }],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: [MiniCssExtractPlugin.loader, "css-loader", {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: [
                                "postcss-preset-env", // 能解决大多数样式兼容性问题
                            ],
                        },
                    },
                },
                    "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: [MiniCssExtractPlugin.loader, "css-loader",
                {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: [
                                "postcss-preset-env", // 能解决大多数样式兼容性问题
                            ],
                        },
                    },
                },
                    "sass-loader"],
            },
            {
                test: /\.styl$/,
                use: [MiniCssExtractPlugin.loader, "css-loader",
                {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: [
                                "postcss-preset-env", // 能解决大多数样式兼容性问题
                            ],
                        },
                    },
                },
                    "stylus-loader"],
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                },
                // 可以使用 module.generator 在一个地方配置所有生成器的选项
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                },
            },
            {
                test: /\.(ttf|woff2?|svg)$/,
                //  发送一个单独的文件并导出 URL
                type: "asset/resource",
                generator: {
                    filename: "static/media/[hash:8][ext][query]",
                },
            },
            {
                test: /\.js$/,
                exclude: /node_modules/, // 排除node_modules代码不编译
                loader: "babel-loader",
            },
        ]
    },
    plugins: [
        new ESLintWebpackPlugin({
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "src"),
        }),
        new HtmlWebpackPlugin({
            // 以 public/index.html 为模板创建文件
            // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
            template: path.resolve(__dirname, "public/index.html"),
        }),
        // 提取css成单独文件
        new MiniCssExtractPlugin({
            // 定义输出文件名和目录
            filename: "static/css/index.css",
        }),
    ],
    mode: 'production'
}

配置需要兼容的浏览器列表

// package.json
 "browserslist": [
    "last 2 version",
    "> 1%",
    "not dead"
  ]
}

css压缩

下载

npm i css-minimizer-webpack-plugin -D

配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: "static/js/index.js", // 将 js 文件输出到 static/js 目录中
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: [MiniCssExtractPlugin.loader, "css-loader", {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: [
                                "postcss-preset-env", // 能解决大多数样式兼容性问题
                            ],
                        },
                    },
                }],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: [MiniCssExtractPlugin.loader, "css-loader", {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: [
                                "postcss-preset-env", // 能解决大多数样式兼容性问题
                            ],
                        },
                    },
                },
                    "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: [MiniCssExtractPlugin.loader, "css-loader",
                {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: [
                                "postcss-preset-env", // 能解决大多数样式兼容性问题
                            ],
                        },
                    },
                },
                    "sass-loader"],
            },
            {
                test: /\.styl$/,
                use: [MiniCssExtractPlugin.loader, "css-loader",
                {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: [
                                "postcss-preset-env", // 能解决大多数样式兼容性问题
                            ],
                        },
                    },
                },
                    "stylus-loader"],
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                },
                // 可以使用 module.generator 在一个地方配置所有生成器的选项
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                },
            },
            {
                test: /\.(ttf|woff2?|svg)$/,
                //  发送一个单独的文件并导出 URL
                type: "asset/resource",
                generator: {
                    filename: "static/media/[hash:8][ext][query]",
                },
            },
            {
                test: /\.js$/,
                exclude: /node_modules/, // 排除node_modules代码不编译
                loader: "babel-loader",
            },
        ]
    },
    plugins: [
        new ESLintWebpackPlugin({
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "src"),
        }),
        new HtmlWebpackPlugin({
            // 以 public/index.html 为模板创建文件
            // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
            template: path.resolve(__dirname, "public/index.html"),
        }),
        // 提取css成单独文件
        new MiniCssExtractPlugin({
            // 定义输出文件名和目录
            filename: "static/css/index.css",
        }),
        new CssMinimizerPlugin()
    ],
    mode: 'production'
}

合并样式处理配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
    return [
        MiniCssExtractPlugin.loader,
        "css-loader",
        {
            loader: "postcss-loader",
            options: {
                postcssOptions: {
                    plugins: [
                        "postcss-preset-env", // 能解决大多数样式兼容性问题
                    ],
                },
            },
        },
        preProcessor,
    ].filter(Boolean);
};

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: "static/js/index.js", // 将 js 文件输出到 static/js 目录中
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: getStyleLoaders(),
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: getStyleLoaders("less-loader"),
            },
            {
                test: /\.s[ac]ss$/,
                use: getStyleLoaders("sass-loader"),
            },
            {
                test: /\.styl$/,
                use: getStyleLoaders("stylus-loader"),
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                },
                // 可以使用 module.generator 在一个地方配置所有生成器的选项
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                },
            },
            {
                test: /\.(ttf|woff2?|svg)$/,
                //  发送一个单独的文件并导出 URL
                type: "asset/resource",
                generator: {
                    filename: "static/media/[hash:8][ext][query]",
                },
            },
            {
                test: /\.js$/,
                exclude: /node_modules/, // 排除node_modules代码不编译
                loader: "babel-loader",
            },
        ]
    },
    plugins: [
        new ESLintWebpackPlugin({
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "src"),
        }),
        new HtmlWebpackPlugin({
            // 以 public/index.html 为模板创建文件
            // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
            template: path.resolve(__dirname, "public/index.html"),
        }),
        // 提取css成单独文件
        new MiniCssExtractPlugin({
            // 定义输出文件名和目录
            filename: "static/css/index.css",
        }),
        new CssMinimizerPlugin()
    ],
    mode: 'production'
}

开发服务器&自动化

在我们的日常开发中我们希望我改了代码后,会自动更新我们更改后的内容,而不用每次打包后才能看到效果,所以webpack提供了一个devServer的配置
下载

npm i webpack-dev-server -D

配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        clean: true,
        filename: "static/js/index.js", // 将 js 文件输出到 static/js 目录中
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader"],
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: ["style-loader", "css-loader", "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: ["style-loader", "css-loader", "sass-loader"],
            },
            {
                test: /\.styl$/,
                use: ["style-loader", "css-loader", "stylus-loader"],
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                },
                // 可以使用 module.generator 在一个地方配置所有生成器的选项
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                },
            },
            {
                test: /\.(ttf|woff2?|svg)$/,
                //  发送一个单独的文件并导出 URL
                type: "asset/resource",
                generator: {
                    filename: "static/media/[hash:8][ext][query]",
                },
            },
            {
                test: /\.js$/,
                exclude: /node_modules/, // 排除node_modules代码不编译
                loader: "babel-loader",
            },
        ]
    },
    plugins: [
        new ESLintWebpackPlugin({
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "src"),
        }),
        new HtmlWebpackPlugin({
            // 以 public/index.html 为模板创建文件
            // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
            template: path.resolve(__dirname, "public/index.html"),
        })
    ],
    // 开发服务器
    devServer: {
        host: "localhost", // 启动服务器域名
        port: "3000", // 启动服务器端口号
        open: true, // 是否自动打开浏览器
    },
    mode: 'production'
}

运行

npx webpack serve

并且当你使用开发服务器时,所有代码都会在内存中编译打包,并不会输出到 dist 目录下。
开发时我们只关心代码能运行,有效果即可,至于代码被编译成什么样子,我们并不需要知道。

开发模式与生产模式

在我们日常开发中,我们总是希望我们开发完成后,今天一系列打包优化,性能提升到最好,所以webpack这里也给我们提供了使用不同的配置文件进行配置

开发模式

适用于dev环境,配合devServe配置,进行开发,并自动实现代码更新,所有代码都会在内存中编译打包,并不会输出到 dist 目录下。

生产模式

生产模式是开发完成代码后,我们需要得到代码将来部署上线。
这个模式下我们主要对代码进行优化,让其运行性能更好。
优化主要从两个角度出发:

  • 优化代码运行性能
  • 优化代码打包速度

使用

我们分别准备两个配置文件来放不同的配置,分别对应开发模式和生产模式

目录配置

├── webpack-document (项目根目录)
    ├── config (Webpack配置文件目录)
    │    ├── webpack.dev.js(开发模式配置文件)
    │    └── webpack.prod.js(生产模式配置文件)
    ├── node_modules (下载包存放目录)
    ├── src (项目源码目录,除了html其他都在src里面)
    │    └── 略
    ├── public (项目html文件)
    │    └── index.html
    ├── .eslintrc.js(Eslint配置文件)
    ├── babel.config.js(Babel配置文件)
    └── package.json (包的依赖管理配置文件)

生产不同的webpack配置,并做里面的绝对路径进行相应的修改

webpack.dev.js配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
    return [
        MiniCssExtractPlugin.loader,
        "css-loader",
        {
            loader: "postcss-loader",
            options: {
                postcssOptions: {
                    plugins: [
                        "postcss-preset-env", // 能解决大多数样式兼容性问题
                    ],
                },
            },
        },
        preProcessor,
    ].filter(Boolean);
};
module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        path: undefined, // 开发模式没有输出,不需要指定输出目录
        filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
        // clean: true, // 开发模式没有输出,不需要清空输出结果
    },
    // Performance 这些选项可以控制 webpack 如何通知「资源(asset)和入口起点超过指定文件限制」。
    performance: {
        hints: false
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: getStyleLoaders(),
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: getStyleLoaders("less-loader"),
            },
            {
                test: /\.s[ac]ss$/,
                use: getStyleLoaders("sass-loader"),
            },
            {
                test: /\.styl$/,
                use: getStyleLoaders("stylus-loader"),
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                },
                // 可以使用 module.generator 在一个地方配置所有生成器的选项
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                },
            },
            {
                test: /\.(ttf|woff2?|svg)$/,
                //  发送一个单独的文件并导出 URL
                type: "asset/resource",
                generator: {
                    filename: "static/media/[hash:8][ext][query]",
                },
            },
            {
                test: /\.js$/,
                exclude: /node_modules/, // 排除node_modules代码不编译
                loader: "babel-loader",
            },
        ]
    },
    plugins: [
        new ESLintWebpackPlugin({
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "../src"),
        }),
        new HtmlWebpackPlugin({
            // 以 public/index.html 为模板创建文件
            // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
            template: path.resolve(__dirname, "../public/index.html"),
        }),
        // 提取css成单独文件
        new MiniCssExtractPlugin({
            // 定义输出文件名和目录
            filename: "static/css/index.css",
        }),
        new CssMinimizerPlugin()
    ],
    // 开发服务器
    devServer: {
        host: "localhost", // 启动服务器域名
        port: "3000", // 启动服务器端口号
        open: true, // 是否自动打开浏览器
    },
    mode: 'development'
}

webpack.prod.js配置

// path 为 Node.js的核心模块,专门用来处理文件路径
const path = require('path')
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
    return [
        MiniCssExtractPlugin.loader,
        "css-loader",
        {
            loader: "postcss-loader",
            options: {
                postcssOptions: {
                    plugins: [
                        "postcss-preset-env", // 能解决大多数样式兼容性问题
                    ],
                },
            },
        },
        preProcessor,
    ].filter(Boolean);
};
module.exports = {
    // 入口
    entry: {
        // 需要一个相对路径
        index: './src/index.js'
    },
    // 输出
    output: {
        // 需要一个绝对路径
        path: path.resolve(__dirname, '../dist'),
        clean: true,
        filename: "static/js/index.js", // 将 js 文件输出到 static/js 目录中
    },
    // Performance 这些选项可以控制 webpack 如何通知「资源(asset)和入口起点超过指定文件限制」。
    performance: {
        hints: false
    },
    // 解析器 
    module: {
        rules: [
            {
                test: /\.css$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: getStyleLoaders(),
            },
            {
                // 正则匹配所有已.less文件结尾的文件
                test: /\.less$/,
                // loader的执行顺序是从右往左的,所以这里先写style-loader,再写css-loader
                // 如果只使用一个loader的话,可以使用loader属性代替use,如下
                // loader:"style-loader"
                use: getStyleLoaders("less-loader"),
            },
            {
                test: /\.s[ac]ss$/,
                use: getStyleLoaders("sass-loader"),
            },
            {
                test: /\.styl$/,
                use: getStyleLoaders("stylus-loader"),
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                // 类似于 module.generator,你可以用 module.parser 在一个地方配置所有解析器的选项。
                parser: {
                    // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
                    dataUrlCondition: {
                        maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                    }
                },
                // 可以使用 module.generator 在一个地方配置所有生成器的选项
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash值取8位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的query参数
                    filename: "static/imgs/[hash:8][ext][query]",
                },
            },
            {
                test: /\.(ttf|woff2?|svg)$/,
                //  发送一个单独的文件并导出 URL
                type: "asset/resource",
                generator: {
                    filename: "static/media/[hash:8][ext][query]",
                },
            },
            {
                test: /\.js$/,
                exclude: /node_modules/, // 排除node_modules代码不编译
                loader: "babel-loader",
            },
        ]
    },
    plugins: [
        new ESLintWebpackPlugin({
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "../src"),
        }),
        new HtmlWebpackPlugin({
            // 以 public/index.html 为模板创建文件
            // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
            template: path.resolve(__dirname, "../public/index.html"),
        }),
        // 提取css成单独文件
        new MiniCssExtractPlugin({
            // 定义输出文件名和目录
            filename: "static/css/index.css",
        }),
        new CssMinimizerPlugin()
    ],
    // 开发服务器
    // devServer: {
    //     host: "localhost", // 启动服务器域名
    //     port: "3000", // 启动服务器端口号
    //     open: true, // 是否自动打开浏览器
    // },
    mode: 'production'
}

package.json配置

{
  "name": "webpack_document",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  // 为了方便运行不同模式的指令,我们将指令定义在 package.json 中 scripts 里面
  "scripts": {
    "start": "npx webpack serve --config ./config/webpack.dev.js",
    "dev": "npx webpack serve --config ./config/webpack.dev.js",
    "build": "npx webpack --config ./config/webpack.prod.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.20.12",
    "@babel/preset-env": "^7.20.2",
    "babel-loader": "^9.1.2",
    "css-loader": "^6.7.3",
    "eslint": "^8.33.0",
    "eslint-webpack-plugin": "^3.2.0",
    "html-webpack-plugin": "^5.5.0",
    "less-loader": "^11.1.0",
    "sass": "^1.58.0",
    "sass-loader": "^13.2.0",
    "style-loader": "^3.3.1",
    "stylus-loader": "^7.1.0",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1",
    "webpack-dev-server": "^4.11.1"
  }
}

开发模式:npm start 或 npm run dev
生产模式:npm run build

基础总结

如果你学习到这里,恭喜你现在已经是一个webpack小能手了

两种开发模式
开发模式:代码能编译自动化运行
生产模式:代码编译优化输出
Webpack 基本功能
开发模式:可以编译 ES Module 语法
生产模式:可以编译 ES Module 语法,压缩 js 代码
Webpack 配置文件
5 个核心概念
entry
output
loader
plugins
mode
devServer 配置
Webpack 脚本指令用法
webpack 直接打包输出
webpack serve 启动开发服务器,内存编译打包没有输出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/195630.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[oeasy]python0072_修改字体前景颜色_foreground_color_font

修改颜色 回忆上次内容 m 可以改变字体样式 0-9 之间设置的都是字体效果0 重置为默认1 变亮2 变暗3 斜体4 下划线5 慢闪6 快闪7 前景背景互换8 隐藏9 中划线 叠加效果 \33[1;3moeasy;分割 取消效果 21 取消 122 取消 223 取消 3一直到 290 是全部取消,回到默认 最…

静态链接库与动态链接库

静态链接库与动态链接库的区别 静态链接库:在项目中引用了库函数,编译时链接器会将引用的函数代码或变量,链接到可执行文件里,和可执行程序组装在一起 动态链接库:在编译阶段不参与链接,不会和可执行文件…

【Unity】流式播放远端音频:WAV格式音频篇(一)

先了解一下wav的格式: 参考1:【音频】WAV 格式详解_tyustli的博客-CSDN博客_wav文件格式详解wav 文件支持多种不同的比特率、采样率、多声道音频。WAV 文件格式是 Microsoft 的 RIFF 规范的一个子集,用于存储多媒体文件。RIFF(res…

git-secret:在 Git 存储库中加密和存储密钥(上)

目前市面上已经存在许多较为成熟的密钥管理产品,比如 HashiCorp Vault,AWS Secrets Manager 以及 GCP Secret Manager。由于这些产品需要集成和维护等服务,因此在项目中引入会增加一定成本和开销。阅读本文,将带你了解如何在 Dock…

numpy数值差分

文章目录diffediff1ddiff diff是numpy中用于求差分的函数&#xff0c;函数定义为 diff(a, n1, axis-1, prepend<no value>, append<no value>)其中a为数组&#xff0c;n为差分的阶数&#xff0c;axis为求导对应的坐标轴&#xff0c;默认-1表示最后一个轴。 例如…

提分必练,中创教育PMP全真模拟题分享

湖南中创教育每日五题分享来啦&#xff0c;“日日行&#xff0c;不怕千万里&#xff1b;常常做&#xff0c;不怕千万事。”&#xff0c;每日五题我们练起来&#xff01; 1、一个建筑项目所在的地区即将进入台风季节&#xff0c;恶劣的天气会严重影响项目的进度。高层管理者要求…

Java poi之word文本替换

目录结构前言文档准备引入Maven依赖代码块替换结果验证孤勇者替换结果对比青鸟替换结果对比前言 应公司需求&#xff0c;需实现以下功能 word文本内容的替换&#xff1b;word文本内容的提取&#xff1b;word文档中图片的提取存放 此文章将使用Apache POI实现Word文档中文本内…

【C++】揭开“引用”的庐山真面目

目录 一、引用的概念 二、引用的应用 1.特性 2.使用场景 2.1 引用作为函数参数 2.2 引用作为函数返回值 三、引用的权限问题 四、引用和指针的区别 一、引用的概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟…

【数据结构之二叉树简介·顺序存储·应用:堆·堆排序·TOPK问题】

​ &#x1f57a;作者&#xff1a; 迷茫的启明星 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f383;相关文章 【数据结构从0到1之树的初识】 &#x1f3c7;家人们&#xff0c;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64…

Kotlin SharedFlowStateFlow 热流到底有多热?

前言 协程系列文章&#xff1a; 一个小故事讲明白进程、线程、Kotlin 协程到底啥关系&#xff1f;少年&#xff0c;你可知 Kotlin 协程最初的样子&#xff1f;讲真&#xff0c;Kotlin 协程的挂起/恢复没那么神秘(故事篇)讲真&#xff0c;Kotlin 协程的挂起/恢复没那么神秘(原理…

50条必背JAVA知识点(二)

16.强制类型转换&#xff1a;将容量大的数据类型转换为容量小的数据类型&#xff0c;但可能造成精度降低或溢出。 17.字符串不能直接转换为基本类型&#xff0c;但通过基本类型对应的包装类则可以实现把字符串转换成基本类型。 18.计算机底层都以二进制补码的方式来存储数据。…

将现实问题转换为编程问题

将现实问题转换为编程问题需要转换思维&#xff0c;不过孰能生巧&#xff0c;见多了就自然懂如何做了&#xff0c;所以动起手来是决没错的。1.猜名次问题改进一&#xff1a;改进二&#xff1a;改进三&#xff1a;2.猜凶手问题总结&#xff1a;1.猜名次问题 每个选手都说了两句话…

深入浅出学习透析Nginx服务器的架构分析及原理分析「底层技术原理+运作架构机制」

Nginx再次回顾 也许你已经忘记了Nginx是做什么的&#xff1f;我来再次给你夯实一下概念。 多协议反向代理 Nginx是个高性能的Web和反向代理服务器及HTTP服务器&#xff0c;它能反向代理HTTP&#xff0c;HTTPS和邮件相关(SMTP&#xff0c;POP3&#xff0c;IMAP)的协议链接&am…

四十、Kubernetes1.25中安全认证详解

1、访问控制概述Kubernetes作为一个分布式集群的管理工具&#xff0c;保证集群的安全性是其一个重要的任务。所谓的安全性其实就是保证对Kubernetes的各种客户端进行认证和鉴权操作。客户端在Kubernetes集群中&#xff0c;客户端通常有两类&#xff1a;User Account&#xff1a…

视频剪辑必备的6个免费素材库~

视频剪辑必备素材&#xff0c;那自然是视频、配乐、音效啦&#xff0c;但最重要的还是内容&#xff0c;这些素材只是点缀。 那要如何获取素材&#xff1f;很多朋友应该都知道&#xff0c;网上很多素材版权不明确&#xff0c;使用不当就会造成侵权&#xff0c;找素材成为了一大…

电脑重装系统装不了如何解决

重装系统装不了如何解决&#xff1f;当电脑出现故障时&#xff0c;大部分人都会选择重装系统来解决这个问题&#xff0c;但是有人出现系统重装不了&#xff0c;下面小编就来为大家解决系统重装不了的问题。 工具/原料&#xff1a; 系统版本&#xff1a;win7 品牌型号&#xff…

为什么 B 站的弹幕可以不挡人物?

那天在 B 站看视频的时候&#xff0c;偶然发现当字幕遇到人物的时候就被裁切了&#xff0c;不会挡住人物&#xff0c;觉得很神奇&#xff0c;于是决定一探究竟。 高端的效果&#xff0c;往往只需要采用最朴素的实现方式&#xff0c;忙碌了两个小时&#xff0c;陈师傅打开了 F1…

Spring Boot(二):第一种导入依赖方式的实战案例

文章目录 第一种导入依赖方式的实战案例 一、导入依赖 二、依赖传递结构图 三、开发案例代码 第一种导入依赖方式的实战案例 一、导入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0…

Android开发——HOOK技术【解析】

1. 什么是 Hook Hook 英文翻译过来就是「钩子」的意思&#xff0c;那我们在什么时候使用这个「钩子」呢&#xff1f;在 Android 操作系统中系统维护着自己的一套事件分发机制。应用程序&#xff0c;包括应用触发事件和后台逻辑处理&#xff0c;也是根据事件流程一步步地向下执…

前端算法之二分查找

在数组中查找指定元素,如果存在就返回它的位置,如果不存在,就返回-1。 这是一道非常经典的算法题&#xff0c;考的就是二分查找算法&#xff0c;首先分析二分查找的思路&#xff1a; 假设一个数组为 [3,5,19,22,25,33,45,47,57,66,71,78]&#xff08;已经从小到大排好序&…