Webpack 入门篇

218 阅读6分钟

引言

一直在听说 webpack,但一直也只是听说,前段时间刚好没事便学习了一下,今天离学习 webpack 有一小段时间了,刚好整理整理一些知识点,就当对之前学习的巩固与之后查阅更为方便

Webpack 入门篇包括了对使用 Webpack 的前置准备、Webpack 的基本介绍和 Webpack 基础配置的讲解

前置准备

依赖环境

在学习 Webpack 之前,需要将其需要的环境准备好,即 node

初始化项目

在安装完 node 之后,就可以初始化项目了。用自己喜欢的软件工具(IDEA 或者 VSCode)创建一个空文件夹,然后打开软件内的终端,初始化项目。以下命令二选一:

# 一步一步初始化
npm init

# 直接使用默认配置一次性初始化
npm init -y

为什么需要 Webpack

项目初始化完成了,便可以正式开始 Webpack 配置的学习了。但是为了能让后面的知识便于理解,所以这里也对 Webpack 做一些简单的介绍:

好了,到这,可能会有一些疑惑,JavaScript 资源还需要处理?

是的,JavaScript 是需要进行一定的加工处理,但这不是必须的,如果你的 js 代码很简单,就一个文件,完全不会存在这样的问题的。但是,当你的代码逻辑变得复杂,文件之间需要互相依赖,在这种需求下写出的代码,咱们的浏览器还能读的懂吗?还可以给你正常运行吗?答案是不行。还有便是 ES6 的一些语法糖,我们用起来是方便了,可是直接抛给浏览器它就傻了呀,不认识呀。所以,我们写的 js 代码在特定的情况下是需要被处理的,因此便诞生了 Webpack

到这,我们知道 Webpack 可以处理 JavaScript,也知道 JavaScript 需要被处理。那其他的资源呢?Webpack 可以处理吗?

答案是 Webpack 并不能直接处理其他的资源文件,它只能用来处理 JavaScript 资源,但是直接的不行,咱们可以配置呀,因此处理其它资源我们需要安装对应的处理器和插件

可能又会有疑问了,那为什么 Webpack 不把所有这些资源的处理都弄好?

额,这个我也不是很清楚,但是细想一下,每一个工具都有它的主要职责,js 资源使用量大,所以就以它为核心了吧,而对于其他的资源那就需要处理哪个就自己配置吧。让自己的项目能更轻便、灵活吧

基础配置

最开始我们已经初始化了一个空项目,现在因为要使用 Webpack,所以需要安装一下它的依赖

npm i -D webpack webpack-cli webpack-dev-server

安装好依赖之后就可以开始了, Webpack 配置是写在 webpack.config 配置文件的,位置可以随意,名字对了就行,使用时找到对应位置使用即可

# 打包,文件路径是配置的 output 输出文件的路径
npx webpack --config {webpack.config.js 路径}
# 运行
npx webpack serve --config {webpack.config.js 路径}

对于 Webpack 基础配置,只要掌握 5 大核心概念:entry、output、loader、plugins、mode 即可

entry

入口文件的配置,可以配置多个入口文件。下面是配置了 2 个入口文件的例子:

entry: { 
    app: "./src/app.js", 
    admin: "./src/admin.js", 
}

output

这是与入口文件对应的输出文件的配置,一个入口文件只能对应一个输出文件。对于单入口文件,直接写明输出文件的输出位置即可:

output: { 
    path: path.resolve(__dirname, "dist"), 
    filename: "static/js/main.js", 
}

对于多入口文件,则使用[name],它在输出文件名中是一个占位符,表示入口的名称

output: { 
    path: path.resolve(__dirname, "dist"), 
    filename: "[name].js", 
}

path.resolve,path 是 NodeJS 中的一个模块,专门用来处理路径的,resolve 是 path 模块下一个用来拼接路径的方法

loader

处理器的配置会与前面的入口文件和输出文件配置不同,因为它需要下载对应的处理器了。可以用处理器来处理样式资源图片资源字体图标资源音视频资源

首先,应该知道 loader 配置的写法:

module: {
    rules: [
        {
            test: /\.xxx$/, 
            use: 'xxx-loader'
        }
    ],
}

样式资源

处理的样式资源有多种,包括:css、less、sass、scss、stylus。

下面直接列出处理各个样式资源的规则:

{
    test: /\.css$/i,
    use: ["style-loader", "css-loader"],
},
{
    test: /\.less$/i,
    use: ["style-loader", "css-loader", "less-loader"],
},
{
    test: /\.s[ac]ss$/i,
    use: ["style-loader", "css-loader", "sass-loader"],
},
{
    test: /\.styl$/,
    use: ["style-loader", "css-loader", "stylus-loader"],
},

当然,也是需要安装相应依赖的:

# css
npm i -D style-loader css-loader

# less、sass、stylus
npm i -D less-loader sass-loader stylus-loader

图片资源、字体图标资源、音视频资源

过去在 Webpack4 时,我们处理图片资源通过 file-loader 和 url-loader 进行处理,但是 Webpack5 已经将两个 Loader 功能内置到 Webpack 里,因此不需要再下载 loader了,只需要简单配置即可处理图片资源

{
    test: /\.(png|jpe?g|gif|webp)$/,
    type: "asset",
}

上面只是对图片的简单处理,还可以对图片资源进行一些优化,比如下于多少 KB 转为 base64 码。可能还会有提到图片压缩,这个会在后面的高级配置提到

{
    test: /.(png|jpe?g|gif|webp)$/,
    type: "asset",
    parser: {
      dataUrlCondition: {
        maxSize: 10 * 1024 // 小于10kb的图片会被 base64 处理
      }
    }
}

字体图标和音视频也是文件资源,因此处理方法和图片资源处理类似:

{
    test: /\.(ttf|woff2?|map4|map3|avi)$/,
    type: "asset/resource",
    generator: {
      filename: "static/media/[hash:8][ext][query]",
    },
}

plugins

loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量

plugin 可以用来处理 js 和 html 的资源

问题来了,js 资源不是 Webpack 已经处理好了?咋又需要处理了?

问的好,前面也提到过工具开发都是有一个主要目的,但随着技术的发展,在开发 Webpack 时也不能料到之后的 js 语法会发展成哪样,因此它能做的只是兼容它那是的 js,但后面的它就管不到了,只能自己配置处理了

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

这里主要介绍两个处理 js 的插件:Babel 和 Eslint

  • 针对 js 兼容性处理,我们使用 Babel 来完成
  • 针对代码格式,我们使用 Eslint 来完成

在开发时,可以按照先完成 Eslint 检测,代码格式无误后,在由 Babel 做代码兼容性处理。当然,个人开发可以跳过 Eslint 检测,因为有时候很烦人

处理 js 资源

Eslint

首先,在 Webpack 配置文件引入 Eslint 插件,然后使用插件:

const ESLintWebpackPlugin = require("eslint-webpack-plugin");

plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "src"),
    }),
]

完成了上面的操作,就需要去写 Eslint 的配置了,它也有自己的配置文件,还有很多种写法:

  • .eslintrc.*:新建文件,位于项目根目录
    • .eslintrc
    • .eslintrc.js
    • .eslintrc.json
    • 区别在于配置格式不一样
  • package.json 中 eslintConfig:不需要创建文件,在原有文件基础上写

ESLint 会查找和自动读取它们,所以以上配置文件只需要存在一个即可

基础的 ESLint 配置文件:

module.exports = {
    // 继承 Eslint 规则
    extends: ["eslint:recommended"],
    env: {
      node: true,
      browser: true,
    },
    parserOptions: {
      ecmaVersion: 6,
      sourceType: "module",
    },
    rules: {
      "no-var": 2,
    },
};

这里 extends 继承的直接是 Eslint 的规则,这里还可以继承 React -- react-app 、Vue -- plugin:vue/vue3-essential 规则

.eslintignore文件可以添加需要忽略检查的文件目录

同样,需要安装使用的依赖:

npm i -D eslint eslint-webpack-plugin
Babel

Babel 的使用和 Eslint 有些不太一样了,它是通过处理器实现的:

{
    test: /.js$/,
    exclude: /node_modules/, // 排除node_modules代码不编译
    loader: "babel-loader",
}

完成了上面的操作,就需要去写 Babel 的配置了,它也有自己的配置文件,还有很多种写法:

  • babel.config.*:新建文件,位于项目根目录
    • babel.config.js
    • babel.config.json
  • .babelrc.*:新建文件,位于项目根目录
    • .babelrc
    • .babelrc.js
    • .babelrc.json
  • package.json 中 babel:不需要创建文件,在原有文件基础上写

Babel 会查找和自动读取它们,所以以上配置文件只需要存在一个即可

基础的 Babel 配置文件:

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

同样,需要安装使用的依赖:

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

处理 html 资源

对打包生成的 html 的处理配置,使用此插件可以指定模板,即打包后的 html 与模板的格式一致

const HtmlWebpackPlugin = require("html-webpack-plugin");

plugins: [
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "public/index.html"),
    }),
],

同样,需要安装使用的依赖:

npm i -D html-webpack-plugin

mode

developmentproduction 两个环境二选一

mode: "development"

结语

这是一篇关于入门 Webpack 的基本配置的讲解。可以用于配置 Webpack 时用来查阅,因为它包括了基础配置代码

如果想了解一些关于 Webpack 的高级配置,可以转到 Webpack 进阶篇

最后附上 Webpack 配置文件的结构,配置内容直接往里面套即可:

module.exports = {
  entry: "",
  output: {
    path: "",
    filename: "",
  },
  module: {
    rules: [
      {
        test: /\.xxx$/i,
        use: [],
      },
    ],
  },
  plugins: [],
  mode: "",
};