一看就会的webpack5基础教程

目录
文章目录隐藏
  1. 一、基本配置
  2. 二、项目初始化
  3. 三、处理 HTML 资源
  4. 四、处理样式资源
  5. 4.5、兼容性处理
  6. 五、处理图片资源
  7. 六、处理字体图标资源
  8. 七、处理其他资源
  9. 八、处理 JS 资源
  10. 九、区分环境
  11. 结语

本文是关于 webpack5 基础教程,意在用尽可能简介明了的描述,一是帮助初学者学习,二是给老鸟复习,三是自己巩固知识!话不多说,直接开干!

版本说明: webpack:^5.75.0 webpack-cli:^5.0.1

一、基本配置

在开始使用 Webpack 之前,我们需要对 Webpack 的配置有一定的认识。

1.1、webpack 5 大核心

  • entry(入口)entry是 webpack 打包的入口,即指示 webpack 从哪里开始打包
  • ouput(出口)output是指示 webpack 将打包好的文件输出到哪里去,如何命名等
  • loader(加载器)webpack 本身只能处理 js、json,对于图片、字体等资源,webpack 需要借助 loader 进行解析
  • plugin(插件)plugin扩展 Webpack 的功能
  • mode(模式)mode指示 webpack 使用哪种模式,有两种
    • development(开发模式)
    • production(生产模式)

二、项目初始化

2.1、安装 webpack

(1)创建 learn_webpack5 文件夹,创建子文件夹 src,打开 vscode 终端,输入以下命令:

npm init -y

npm i webpack webpack-cli -D

会生成如下文件:

安装 webpack

(2)src 文件夹下创建 a.js、b.js、index.js 文件。

a.js

//src/a.js
export function printA() {
    console.log('mybj123')
}

b.js

//src/b.js
export function printB() {
    console.log('mybj123.com')
}

index.js

//src/index.js
import { printA } from "./a";
import { printB } from "./b";

function print() {
    printA()
    printB()
}

print()

(3)在根目录下,创建 public/index.html 并初始化。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body></body>
</html>

2.2、编写 webpack 基本配置

在根目录下,创建 webpack/webpack.common.js,并编写如下基本配置:

//webpack/webpack.common.js
const path = require('path')

module.exports = {
    //打包的入口配置
    //相对路径和绝对路径都行
    entry: path.resolve(__dirname, "../src/index.js"),
    //打包文件的出口配置
    output: {
        // path: 文件输出目录,必须是绝对路径
        // path.resolve()方法返回一个绝对路径
        // __dirname 当前文件的文件夹绝对路径
        path: path.resolve(__dirname, '../dist'),
        //输出的文件名
        filename: 'bundle.js',
        //webpack5 版本中,自动清除上一次打包的结果
        clean: true
    },
    //加载器配置
    module: {
        rules: [

        ]
    },
    //插件配置
    plugins: [],
    //模式配置
    mode: 'development'
}

2.3、配置 package.json 脚本命令

打开 package.json,添加下面的命令:

"scripts": {
    "build": "webpack --config ./webpack/webpack.common.js",
 },

在 vscode 终端运行 npm run build,整体目录如下:

webpack 整体目录

三、处理 HTML 资源

html-webpack-plugin 会生成一个 HTML5 文件,在 head 中使用 scrip t 标签引 webpack 生成的 bundle.js

(1)下载 html-webpack-plugin:

npm i html-webpack-plugin -D

(2)在 plugins 中配置 html-webpack-plugin:

const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    //前面的代码...
    plugins: [
        new HtmlWebpackPlugin({
            //输出的路径
            template: path.resolve(__dirname, '../public/index.html'),
            //输出的文件名
            filename: 'index.html'
        })
    ]
}

3)再次执行 npm run build

处理 HTML 资源

(4)打开 dist/index.html,右键,选择运行在浏览器中。f12 打开控制台,选择 network,发现我们打包后的资源都下载下来了。

webpack 打包后资源下载下来了

打开控制台,发现打印了 mybj123、mybj123.com。

控制台打印出来 js 内容

这样我们打包后的 bundle.js 就可以直观的运行在页面上了。

四、处理样式资源

接下来我们学习使用 Webpack 如何处理 Css、Less、Sass、Scss、Styl 样式资源。

Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源。

4.1、处理 CSS 样式

(1)下载 css-loader、style-loader

npm i css-loader style-loader -D
  • css-loader:帮助 webpack 解析 css,包括 @import 和 url();
  • style-loader:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容。

(2)配置

// webpack/webpack.common.js
module.exports = {
    //前面的代码...
    module: {
        rules: [
            {
                test: /\.css$/, //匹配以 css 结尾的文件
                use: ["style-loader", "css-loader"], //从右向左解析
            },
        ]
    },
    //后面的代码...
}

(3)创建 src/styles/a.css,写入样式:

body{
    background-color: rgb(255, 85, 0);
}

在 src/index.js 中引入 a.css:

import './styles/a.css'

(4)执行 npm run build 后,重新在浏览器运行 dist/index.html,发现样式已经生效。

css-loader 处理 CSS 样式

4.2、处理 Less 样式

(1)下载 less-loader

npm i less-loader -D

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

(2)配置

// webpack/webpack.common.js
module.exports = {
    //前面的代码...
    module: {
        rules: [
            {
                test: /\.css$/, //匹配以 css 结尾的文件
                use: ["style-loader", "css-loader"], //从右向左解析
            },
            {
                test: /\.less$/, //匹配以 less 结尾的文件
                use: ["style-loader", "css-loader", "less-loader"], //从右向左解析
            },
        ]
    },
    //后面的代码...
}

(3)创建 src/styles/b.less,写入样式:

div{
    width: 200px;
    height: 200px;
    background-color: rgb(85, 0, 255);
    span{
        color: white;
    }
}

(4)打开 public/index.html,添加一个 div 和 span。

<div>
  <span> mybj123.com </span>
</div>

(5)打开 src/index.js,引入 b.less:

import './styles/b.less';

(6)执行 npm run build 后,页面如下:

less-loader 处理 Less 样式

4.3、处理 Sass、Scss 样式

(1)下载 sass-loader、sass

npm i sass-loader sass -D

(2)配置

// webpack/webpack.common.js
module.exports = {
    //前面的代码...
    module: {
        rules: [
            {
                test: /\.css$/, //匹配以 css 结尾的文件
                use: ["style-loader", "css-loader"], //从右向左解析
            },
            {
                test: /\.less$/, //匹配以 less 结尾的文件
                use: ["style-loader", "css-loader", "less-loader"], 
            },
            {
                test: /.s[ac]ss$/,//匹配以 sass、scss 结尾的文件
                use: ["style-loader", "css-loader", "sass-loader"],
            },
        ]
    },
    //后面的代码...
}

3)创建 src/styles/c.scss,写入样式:

$blue: rgb(255, 0, 187);
.box2{
    width: 300px;
    height: 300px;
    background-color: $blue;
}

(4)打开 public/index.html,添加一个 div.box2

<div class="box2"></div>

(5)打开 src/index.js,引入 c.scss。

import './styles/c.scss';

(6)执行 npm run build,页面如下:

sass-loader 处理 Sass、Scss 样式

4.4、抽取 CSS 到单独的文件

我们发现上面的打包结果,head 标签中有 3 个 style 标签,如果在 src/index.js 里面引入的样式资源越多,则打包后的 style 标签就越多,这个时候我们希望把所有的 CSS 都提取到一个单独的文件中,减少 DOM 的操作,我们需要使用 mini-css-extract-plugin

(1)下载 mini-css-extract-plugin

npm i mini-css-extract-plugin -D

(2)配置

// webpack/webpack.common.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
    //前面的代码...
    module: {
        rules: [
            {
                test: /\.css$/,
                //将 style-loader 换成 MiniCssExtractPlugin.loader
                use: [MiniCssExtractPlugin.loader, "css-loader"], 
            },
            {
                test: /\.less$/, //匹配以 less 结尾的文件
                use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
            },
            {
                test: /\.s[ac]ss$/,
                use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
            },
        ]
    },
    plugins: [
        //前面的代码...
        
        // 提取 css 成单独文件
        new MiniCssExtractPlugin({
           // 定义输出文件名和目录
           filename: "asset/css/main.css",
        }),
    ]
}

(3)执行 npm run build

抽取 CSS 到单独的文件

(4)页面运行结果如下:

head 下没有 style 标签了 多了 main.css

4.5、兼容性处理

某些样式可能并不兼容低版本浏览器,所以需要对 css 进行兼容性处理 。

(1)下载 postcss-loader postcss postcss-preset-env

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

(2)配置

// 由于需要对 css、less、sass 都进行兼容性处理,所以我们先合并一下样式的配置
const getStyleLoaders = (preProcessor) => {
  return [
    MiniCssExtractPlugin.loader,
    "css-loader",
    //在 css-loader 后,配置 postcss-loader
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: [
            "postcss-preset-env", // 能解决大多数样式兼容性问题
          ],
        },
      },
    },
    preProcessor,
  ].filter(Boolean);
};

module.exports = {
    module: {
        rules: [
            {
                // 用来匹配 .css 结尾的文件
                test: /.css$/,
                // use 数组里面 Loader 执行顺序是从右到左
                use: getStyleLoaders(),
            },
            {
                test: /.less$/,
                use: getStyleLoaders("less-loader"),
            },
            {
                test: /.s[ac]ss$/,
                use: getStyleLoaders("sass-loader"),
            }
        ]
    }
}

(3)在 package.json 新增 browserslist 配置

"browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
 },

(4)在 src/styles/b.less 中添加样式

div{
    width: 200px;
    height: 200px;
    background-color: rgb(85, 0, 255);
    span{
        color: white;
        transform: rotate(45deg); /* 这个属性会产生浏览器内核前缀如 -webkit*/
    }
}

(5)执行 npm run build,查看 dist/assets/css/main.css

兼容性处理

4.6、压缩 CSS

打包后的文件体积越小,浏览器加载资源的速度就越快,当项目很大时,压缩文件体积是非常有必要的,接下来我们压缩打包后 CSS 文件的体积。

(1)下载 css-minimizer-webpack-plugin

npm i css-minimizer-webpack-plugin -D

(2)配置

//webpack/webpack.common.js
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
    //前面的代码...
    
    plugins: [
        // css 压缩
        new CssMinimizerPlugin(),
    ]
}

(3)执行 npm run build,发现 dist/assets/css/main.css 的代码被压缩了。

css 代码压缩

五、处理图片资源

过去在 Webpack4 时,我们处理图片资源通过 file-loader 和 url-loader 进行处理。

现在 Webpack5 已经将两个 Loader 功能内置到 Webpack 里了,我们只需要简单配置即可处理图片资源。

(1)配置

module.exports = {
    module: {
        rules: [
            //前面的代码
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                parser: {
                  dataUrlCondition: {
                    // 小于 10kb 的图片会被 base64 处理
                    // 优点:减少请求数量
                    // 缺点:体积更大
                    maxSize: 10 * 1024
                  }
                },
                generator: {
                  // 将图片文件输出到 asset/imgs 目录中
                  // 将图片文件命名 [hash:8][ext][query]
                  // [hash:8]: hash 值取 8 位
                  // [ext]: 使用之前的文件扩展名
                  // [query]: 添加之前的 query 参数
                  filename: "asset/imgs/[hash:8][ext][query]",
                },
            },
        ]
    }
}

(2)添加图片 创建 src/assets/img 文件夹,在该文件夹下添加三张图片(素材自己随便找)。

(3)使用图片。首先,我们先在 src/public/index.html 中添加两个 div。

<div class="box3"></div>
<div class="box4"></div>

然后,在 src/styles/b.less 中,写入下面的样式:

.box2{
    background-image: url("../asset/img/1.jpeg");
    background-size: cover;
}
.box3{
    background-image: url("../asset/img/2.png");
    background-size: cover;
}
.box4{
    background-image: url("../asset/img/3.gif");
    background-size: cover;
}

最后,执行打包命令 npm run build,观察结果。

首先,图片资源被打包到了 dist/asset/imgs 目录中,并且只有两张图片,分别是 2.png 和 3.gif 打包后的输出。

图片资源被打包

而 1.jpeg 没有,是因为 1.jpeg 小于 10kb 的图片,所以被处理为了 base64 格式 打开页面,我们发现:

处理图片资源 处理图片资源

至此,我们完成了对图片资源的处理。

六、处理字体图标资源

字体图标资源的处理和图片资源的处理方式类似,这里直接上配置,不再赘述。

(1)配置

module.exports = {
    module: {
        rules: [
            {
                test: /\.(ttf|woff2?)$/,
                type: "asset/resource",
                generator: {
                  // 将字体图标文件输出到 asset/fonts 目录中
                  // 将字体图标命名 [hash:8][ext][query]
                  // [hash:8]: hash 值取 8 位
                  // [ext]: 使用之前的文件扩展名
                  // [query]: 添加之前的 query 参数
                  filename: "asset/fonts/[hash:8][ext][query]",
                },
            },
        ]
    }
}

(2)在阿里巴巴矢量库,选择想要的图标添加到购物车,统一下载到本地(不会的童鞋可以自行百度,这里不过多赘述)

(3)将 iconfont.ttf、 iconfont.woff、 iconfont.woff2 添加到 src/asset/fonts, 将 iconfont.css 添加到 src/asset/styles(这要注意修改 iconfont.css 中引入字体的路径,否则打包会报错)。

处理字体图标资源

(4)使用字体图标,在 src/index.js 中引入字体图标:

//src/index.js
import './styles/iconfont.css'

(5)在 src/public/index.html 中,使用字体图标:

<i class="iconfont icon-kechengguanli"></i>
<i class="iconfont icon-dianyingzhuanziguanli"></i>

(6)执行 npm run build,打开页面

字体图标展示

至此,图标字体资源的处理完毕

七、处理其他资源

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

module.exports = {
    module: {
        rules: [
            {
                test: /\.(map4|map3|avi)$/,
                type: "asset/resource",
                generator: {
                  filename: "asset/media/[hash:8][ext][query]",
                },
            },
        ]
    }
}

八、处理 JS 资源

Webpack 对 js 处理是有限的,只能编译 js 中 ES 模块化语法,不能编译其他语法,导致 js 不能在 IE 等浏览器运行,所以我们希望做一些兼容性处理,我们使用 Babel 来完成

(1)下载相关的包

npm i @babel/core babel-loader @babel/preset-env @babel/plugin-transform-runtime -D

其中:

  • @babel/core:babel 核心库;
  • babel-loader:处理 JS 的插件;
  • @babel/preset-env:将 ES6 向后兼容;
  • @babel/plugin-transform-runtime:处理 async,await、import() 等语法关键字的帮助函数。

(2)根目录下,创建 babel.config.js 文件:

module.exports = {
    presets: ["@babel/preset-env"],
};

(3)webpack.common.js 中配置:

module.exports = {
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                exclude: /node_modules/, // 排除 node_modules 代码不编译
                loader: "babel-loader",
            },
        ]
    }
}

(4)在 src/public/index.html 中:

<button>使用 es6 箭头函数</button>
<script>
  document.querySelector('button').onclick = () => {
    console.log('使用 es6 箭头函数')
  }
</script>

(5)执行 npm run build,打开页面,点击按钮后,窗口控制台的输出结果。

处理 js 资源

九、区分环境

实际开发中,我们一般将 webpack 配置分为 webpack.common.js(公共配置)、webpack.config.dev.js (开发环境) 和 webpack.config.prod.js (生产环境),将配置的代码合并,避免重复代码。

(1)npm i webpack-merge -D

(2)创建 src/webpack/webpack.config.dev.jssrc/webpack/webpack.config.prod.js,并分别对不同环境进行配置。

  • 开发环境 webpack.config.dev.js

(1)npm i webpack-dev-server -D

(2)配置

const path = require("path");

module.exports = {
  mode: "development",
  devServer: {
    hot: true, //热更新
    open: true, //编译完自动打开浏览器
    compress: true, //开启 gzip 压缩
    port: 3000, //开启端口号
    //托管的静态资源文件
    //可通过数组的方式托管多个静态资源文件
    static: {
      directory: path.join(__dirname, "../public"),
    },
  },
};
  • 生产环境 webpack.config.prod.js
module.exports = {
  mode: "production",
  output: {
    clean: true
  }
};

(3)打开 package.json,写下命令

{
    //...其他代码
    "scripts": {
        "build": "webpack --config ./webpack/webpack.common.js --env production",
        "serve": "webpack serve --config ./webpack/webpack.common.js --env development"
      },
}

(4)修改 src/webpack/webpack.common.js 中的配置

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

//合并配置的插件
const { merge } = require("webpack-merge");
//引入生产环境和开发环境的配置
const prodConfig = require("./webpack.config.prod");
const devConfig = require("./webpack.config.dev");

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

const commonConfig = {
    //打包的入口配置
    //相对路径和绝对路径都行
    entry: path.resolve(__dirname, "../src/index.js"),
    //打包文件的出口配置
    output: {
        // path: 文件输出目录,必须是绝对路径
        // path.resolve()方法返回一个绝对路径
        // __dirname 当前文件的文件夹绝对路径
        path: path.resolve(__dirname, '../dist'),
        //输出的文件名
        filename: 'bundle.js',
    },
    //加载器配置
    module: {
        rules: [
            {
                test: /\.css$/,
                use: getStyleLoaders(),
            },
            {
                test: /\.less$/, //匹配以 less 结尾的文件
                use: getStyleLoaders("less-loader"),
            },
            {
                test: /\.s[ac]ss$/,
                use: getStyleLoaders("sass-loader"),
            },
            {
                test: /\.(png|jpe?g|gif|webp)$/,
                type: "asset",
                parser: {
                    dataUrlCondition: {
                      // 小于 10kb 的图片会被 base64 处理
                      // 优点:减少请求数量
                      // 缺点:体积更大
                      maxSize: 10 * 1024
                    }
                },
                generator: {
                    // 将图片文件输出到 static/imgs 目录中
                    // 将图片文件命名 [hash:8][ext][query]
                    // [hash:8]: hash 值取 8 位
                    // [ext]: 使用之前的文件扩展名
                    // [query]: 添加之前的 query 参数
                    filename: "asset/imgs/[hash:8][ext][query]",
                },
            },
            {
                test: /\.(ttf|woff2?)$/,
                type: "asset/resource",
                generator: {
                  filename: "asset/fonts/[hash:8][ext][query]",
                },
            },
            {
                test: /(\.jsx|\.js)$/,
                exclude: /node_modules/, // 排除 node_modules 代码不编译
                loader: "babel-loader",
            },
        ]
    },
    //插件配置
    plugins: [
        new HtmlWebpackPlugin({
            //输出的路径
            template: path.resolve(__dirname, '../public/index.html'),
            //输出的文件名
            filename: 'index.html'
        }),
        // 提取 css 成单独文件
        new MiniCssExtractPlugin({
            // 定义输出文件名和目录
            filename: "asset/css/main.css",
        }),
        // css 压缩
        new CssMinimizerPlugin(),
    ],
}

module.exports = function(env) {
    //env.production 用于获取 终端命令行中 
    const isProduction = env.production;
    process.env.NODE_ENV = isProduction ? "production": "development";
  
    const config = isProduction ? prodConfig : devConfig;
    const mergeConfig = merge(commonConfig, config);
  
    return mergeConfig;
  };

(5)运行 npm run serve 查看开发环境:

开发环境

打开 localhost:3000,

打开页面访问

然后,我们去更改 src/a.js 中的输出,然后保存:

//src/a.js
export function printA() {
    console.log('webpack')
}

发现页面进行了热更新,由 mybj123 变为 webpack。

热更新

至此,webpack 的环境分离已经完成。

结语

以上就是全部关于 webpack5 基础配置的教程,希望能帮助初学者学习及参考,以及让老鸟巩固基础。

「点点赞赏,手留余香」

1

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » 一看就会的webpack5基础教程

发表回复