# webpack 简介

官方说,webpack is a static module bundler for modern JavaScript applications.

翻译过来:webpack 是一个静态的模块化打包工具,为现代的 JavaScript 应用程序;

  • 我们来对上面的解释进行拆解: p 打包 bundler:webpack 可以将帮助我们进行打包,所以它是一个打包工具
  • 静态的 static:这样表述的原因是我们最终可以将代码打包成最终的静态资源(部署到静态服务器);
  • 模块化 module:webpack 默认支持各种模块化开发,ES Module、CommonJS、AMD 等;
  • 现代的 modern:我们前端说过,正是因为现代前端开发面临各种各样的问题,才催生了 webpack 的出现和发展;

# 基础安装

# webpack 和 webpack-cli

webpack 是执行打包的本体,它原生只支持打包 JavascriptJson 文件,若需要打包如 htmlcssimage 等资源则要安装相应的 loader

webpack-cli 是调用 webpack 的一种手段。通常我们调用 webpack 都是直接在命令行里调用的,而这正是 webpack-cli 的功劳。如果没有安装 webpack-cli 那么我们将不能直接从命令行里读取参数。它起到的是一个传递命令行参数到 webpack 中的功能。实际上,当我们使用 Vue 或 React 的脚手架时,我们并没有安装 webpack-cli 这个东西。Vue 有 vue-cli 而 React 有 creat-react-app ,它们替代了 webpack-cli 传递命令行参数到 webpack 的功能。

# 安装

# 全局安装 webpack5 和 webpack-cli4
npm install -g webpack@5 webpack-cli@4

# 局部安装
npm install -D webpack@5 webpack-cli@4

# 基础使用

当我们直接使用 webpack 命令时,调用的是我们全局安装的 webpack

如果我们需要使用当前项目中的 webpack 版本打包项目,有三种方式分别是:

第一种直接找到本地安装路径,调用

# 直接找到node_modules/.bin下的webpack文件打包
node_modules\.bin\webpack

第二种使用 npx

# 使用npx,npx可以自动去node_modules文件夹下寻找文件
npx webpack

第三种在配置文件 package.json 中配置命令,该方法最常用

// 在配置文件 package.json 的 "script" 里的配置命令
"scripts": {
    "build": "webpack" //package.json 会优先在本地 node_modules 中寻找,若找不到则会往上查找全局环境下的 webpack
}
# 调用scripts里的命令
npm run build

# 配置 package.json

当我们使用 webpack 打包文件时,它会默认从当前目录下找到 src 文件夹下的 index.js 。所有引入或关联到 index.js 里的资源都会被 webpack 打包,否则不会被打包。

默认打包的文件会生成在当前目录的 dist 文件夹下,名称为 main.js

image-20220503175000507

在通常情况下,webpack 需要打包的项目是非常复杂的,并且我们需要一系列的配置来满足要求,默认配置必然是不可以的。

我们可以在根目录下创建一个 webpack.config.js 文件,来作为 webpack 的配置文件:

// 需求:将入口文件改为 main.js ,输出文件改为 bundle.js
// 方法一 常用方法
// webpack.config.js
const path = require('path');
// 导出配置信息
module.exports = {
	entry: "./scr/main.js", // 入口文件更改为 main.js
    output: {
		filename: "bundle.js", // 输出文件的名称更改为 bundle.js
         path: path.resolve(__dirname,"./dist")
    }
}
# 方法二
npx webpack --entry ./src/main.js --output-path ./build

默认情况下 webpackwebpack.config.js 里读取配置,当我需要更改 webpack 读取配置的文件时,可以通过 --config 来指定配置文件

# 指定 wk.config.js 为 webpack 的配置文件
webpack --config wk.config.js

或者通过 package.json 指定

// package.json
"scripts": {
    "build": "webpack --config wk.config.js"
}

# 配置 Loader

开头我们说过, webpack 原生只支持打包 javascript 文件和 json 文件。当我们需要打包其它资源时,就要配置相应的 loader 来支持,否则会报错。

# css-loader

使用 loader 前我们需要安装好 loader 。安装 css-loader

npm install css-loader -D

使用 loader 通常有三种方式,分别是:

  • 内联方式
  • cli 方式
  • 配置文件方式

# 内联方式

内联方式就是在引入的样式前加上使用的 loader,并且使用 ! 分割每个 loader 。这种方式只能作用在当前文件下,若其它文件下也引入了 css 文件则需要再次配置。所以不常使用。

//index.js 中引入 css 文件并使用 css-loader 和 style-loader
import "style-loader!css-loader../css/index.css" // 在路径前面加上 loader 名称

# cli 方式

webpack5 的文档中已经没有了 --module-bind 命令,所以 webpack5 不支持该模式。具体配置方式可查找 webpack4 官方文档

# 配置文件方式

该方式是最常见的 loader 使用方式。其意思是在我们的 webpack.config.js 文件中写明配置信息。在该文件暴露的对象中,使用 module.rules 来配置 loader

// webpack.config.js
const path = require('path');
// 导出配置信息
module.exports = {
	entry: "./scr/main.js",
    output: {
		filename: "bundle.js",
         path: path.resolve(__dirname,"./dist")
    }
    module: {
    	rules: [ //rules 属性对应的值是一个数组:[Rule] 。数组中存放的是一个个的 Rule,Rule 是一个对象,对象中可以设置多个属性:
    		{
    			test: /\.css$/, // 用于对 resource(资源)进行匹配的,通常会设置成正则表达式
    			//loader:"css-loader" // 写法一
    			//use: ["css-loader"] // 写法二
    			// 写法三
    			use: [ // 对应的值时一个数组:[UseEntry] 。UseEntry 是一个对象,可以通过对象的属性来设置一些其他属性:
    				{loader:"css-loader",options:'xxx'} // 完整写法,options 可以对 css-loader 传入参数
					// 若无需传参则可简写为写法二
					// 若处理该文件仅使用一个 loader,可简写为写法一
    			]
                //loader:'css-loader' 写法四。 loader 属性: Rule.use: [{loader} ] 的简写。
			}
		]
	}
}

# style-loader

当我们把 css 文件打包好后,css 文件并不会生效。此时我们还需要使用 style-loader 将打包好的 css 插入页面。安装 style-loader

npm install style-loader -D

配置 style-loader 。这里需要注意的是,使用多个 loader 处理同一个资源时, loader 的调用顺序是从后往前的。所以 loader 的顺序需要将 style-loader 放在最后。配置书写如下:

// webpack.config.js
module: {
	rules: [
        {
            test: /\.css$/,
            use: [
                {loader: "style-loader"}, // 然后再插入页面
                {loader: "css-loader"} // 先将 css 文件解析打包
            ]
        }
    ]
}

# less-loader

打包 less 文件的步骤也和上面的文件同理,但是 less-loader 本身并不能处理 less 文件,所以安装时还需要另外安装 less 处理工具, less-loader 仅仅只是调用了 less 处理工具而已。安装 less 处理工具和 less-loader

npm install less -D  # 安装less处理工具
npm install less-loader -D # 安装less-loader

配置 less-loader

// webpack.config.js
module: {
    rules: [
        {
            test: /\.css$/,
            use: [
                {loader: "style-loader"},
                {loader: "css-loader"},
                {loader: "less-loader"}
            ]
        }
    ]
}

# browserslist

开发中我们经常需要去处理浏览器兼容性问题,我们不可能针对每个浏览器一个一个去配置兼容性。通常的做法是根据浏览器的市场占有率去选择性兼容。在开发中有专门的工具如 autoprofixerPostCsspostcss-preset-env 去帮助我们自动生成兼容代码,而这里我们首先要解决的是关于浏览器的市场占有率等信息如何自动获取。 browserslist 就是帮助我们获取浏览器占有率,指定要配置哪些浏览器的工具。它可以让我们在不同的前端工具之间,共享目标浏览器和 Node.js 版本的配置。

安装 browserslist

npm install browserslist -D

配置 browserslist 。配置它有两种方式,一是通过 package.json ,二是单独编写 .browserslistrc 文件配置当有该文件时会默认读取该文件中的配置。

package.json 配置:

"browserslist": [
    "last 2 version",
    "not dead",
    "> 1%"
]

我们还可以通过编辑 .browserslistrc 文件去配置:

last 2 version
not dead
> 1%

Browserslist 编写规则:

  • defaults:Browserslist 的默认浏览器(> 0.5%, last 2 versions, Firefox ESR, not dead)
  • 5%:通过全局使用情况统计信息选择的浏览器版本。 >=,< 和 <= 工作过
    • 5% in US:使用美国使用情况统计信息。它接受两个字母的国家 / 地区代
    • 5% in alt-AS:使用亚洲地区使用情况统计信息。有关所有区域代码的列表,请参见 caniuse-lite/data/regions
    • 5% in my stats:使用自定义用法数据
    • 5% in browserslist-config-mycompany stats:使用 来自的自定义使用情况数据 browserslist-config-mycompany/browserslist-stats.json
    • cover 99.5%:提供覆盖率的最受欢迎的浏览器
    • cover 99.5% in US:与上述相同,但国家 / 地区代码由两个字母组成
    • cover 99.5% in my stats:使用自定义用法数据。
  • dead:24 个月内没有官方支持或更新的浏览器
  • last 2 versions:每个浏览器的最后 2 个大版本
    • last 2 Chrome versions:最近 2 个版本的 Chrome 浏览器
    • last 2 major versions 或 last 2 iOS major versions:最近 2 个主要版本的所有次要 / 补丁版本
  • node 10 和 node 10.4:选择最新的 Node.js10.x.x 或 10.4.x 版本
  • current node:Browserslist 现在使用的 Node.js 版本
  • maintained node versions:所有 Node.js 版本,仍由 Node.js Foundation 维护
  • iOS 7:直接使用 iOS 浏览器版本 7
    • Firefox > 20:Firefox 的版本高于 20 >=,< 并且 <= 也可以使用。它也可以与 Node.js 一起使用
    • ie 6-8:选择一个包含范围的版本
    • Firefox ESR:最新的 [Firefox ESR] 版本
    • PhantomJS 2.1 和 PhantomJS 1.9:选择类似于 PhantomJS 运行时的 Safari 版本
  • extends browserslist-config-mycompany:从 browserslist-config-mycompanynpm 包中查询
  • supports es6-module:支持特定功能的浏览器。 es6-module 这是 “我可以使用” 页面 feat 的 URL 上的参数。有关所有可用功能的列表,请参见 。caniuse- lite/data/features
  • browserslist config:在 Browserslist 配置中定义的浏览器。在差异服务中很有用,可用于修改用户的配置,例如 browserslist config and supports es6-module
  • since 2015 或 last 2 years:自 2015 年以来发布的所有版本(since 2015-03 以及 since 2015-03-10)
  • unreleased versions 或 unreleased Chrome versions:Alpha 和 Beta 版本
  • not ie <= 8:排除先前查询选择的浏览器

根据上述编写规则,我们编写了多个条件之后,多个条件之间是什么关系呢?

image-20220507105656473

刚刚我们在 .browserslistrc 中书写的规则没有添加关键字,默认为 or 的关系