Webpack
本身只能处理 JavaScript
模块,如果要处理其他类型的文件,就需要使用loader
进行转换。
Loader
可以理解为是模块和资源的转换器,它本身是一个函数,接受源文件作为参数,返回转换的结果。这样,我们就可以通过 require
来加载任何类型的模块或文件,比如 CoffeeScript
、 JSX
、 LESS
或图片。
一、loader简介
loader
用于对模块的源代码进行转换。loader
可以使你在import
或 “load
(加载)” 模块时预处理文件。因此,loader
类似于其他构建工具中“任务(task
)”,并提供了处理前端构建步骤的得力方式。loader
可以将文件从不同的语言(如 TypeScript
)转换为 JavaScript
或将内联图像转换为 data URL
。loader
甚至允许你直接在 JavaScript
模块中 import CSS
文件!
1.1 使用 loader
在你的应用程序中,有两种使用 loader
的方式:
- 配置方式(推荐):在
webpack.config.js
文件中指定loader
。 - 内联方式:在每个
import
语句中显式指定loader
。
注意在 webpack v4
版本可以通过 CLI
使用 loader
,但是在 webpack v5
中被弃用。
1.1.1 配置文件方式
module.rules
允许你在 webpack
配置中指定多个 loader
。 这种方式是展示 loader
的一种简明方式,并且有助于使代码变得简洁和易于维护。同时让你对各个 loader
有个全局概览:
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true,
},
},
{ loader: 'sass-loader' },
],
},
],
},
};
loader
从右到左(或从下到上)地取值(evaluate
)/执行(execute
)。在下面的示例中,从 sass-loader
开始执行,然后继续执行 css-loader
,最后以 style-loader
为结束。
1.1.2 内联方式
可以在 import
语句或任何 与 “import
” 方法同等的引用方式 中指定 loader
。使用 !
将资源中的 loader
分开。每个部分都会相对于当前目录解析。
import Styles from 'style-loader!css-loader?modules!./styles.css';
1.2 loader 特性
loader
支持链式调用。链中的每个 loader 会将转换应用在已处理过的资源上。一组链式的 loader 将按照相反的顺序执行。链中的第一个 loader 将其结果(也就是应用过转换后的资源)传递给下一个 loader,依此类推。最后,链中的最后一个loader
,返回 webpack 所期望的 JavaScript。loader
可以是同步的,也可以是异步的。loader
运行在 Node.js 中,并且能够执行任何操作。loader
可以通过options
对象配置(仍然支持使用 query 参数来设置选项,但是这种方式已被废弃)。- 除了常见的通过 package.json 的 main 来将一个 npm 模块导出为 loader,还可以在
module.rules
中使用loader
字段直接引用一个模块。 - 插件(
plugin
)可以为loader
带来更多特性。 loader
能够产生额外的任意文件。
可以通过 loader
的预处理函数,为 JavaScript
生态系统提供更多能力。用户现在可以更加灵活地引入细粒度逻辑,例如:压缩、打包、语言转译(或编译)和 更多其他特性。
1.3 解析 loader
loader
遵循标准 模块解析 规则。多数情况下,loader
将从 模块路径 加载(通常是从 npm install, node_modules
进行加载)。
我们预期 loader
模块导出为一个函数,并且编写为 Node.js
兼容的 JavaScript
。通常使用 npm
进行管理 loader
,但是也可以将应用程序中的文件作为自定义 loader
。
1.4 命名规范
按照约定,loader
通常被命名为 xxx-loader
(例如 json-loader
)
在引用 loader
的时候可以使用全名 json-loader
,或者使用短名 json
。这个命名规则和搜索优先级顺序在 webpack
的 resolveLoader.moduleTemplates api
中定义。
Default: ["*-webpack-loader", "*-web-loader", "*-loader", "*"]
二、css loader的安装和使用
css-loader
会对 @import
和 url()
进行处理,就像 js
解析 import/require()
一样
参考文档:css-loader文档
2.1 安装
- 不指定版本安装:
npm i style-loader css-loader -D
- 指定版本安装:
npm i style-loader@3.3.3 css-loader@6.8.1 -D
i
为install
的简写
D:\A_MyWork\M05.MYCode\vscode\javascript\webpack>npm i style-loader css-loader -D
added 16 packages in 2s
D:\A_MyWork\M05.MYCode\vscode\javascript\webpack>
2.2 配置
修改配置文件:webpack.config.js
,新增module
节点。
test
:表示匹配文件的类型use
:表示对应要调用的loader
;多个loader
的调用顺序是从后往前调用
module.exports = {
module: {
// 定义了不同模块的loader
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
}
]
}
}
2.3 测试
- 在src目录下新建
css
目录,并在css
目录下新建index.css
li {
list-style: none;
}
- 在源代码
index.js
中导入样式
import './css/index.css'
- 执行打包命令
npm run dev
,查看效果
三、 less-loader 的安装和使用
less-loader
是webpack
将 Less
编译为 CSS
的 loader
。
参考链接:中文文档
3.1 安装
- 不指定版本安装:
npm i less-loader less -D
- 指定版本安装:
npm i less-loader@11.1.3 less@4.1.3 -D
D:\A_MyWork\M05.MYCode\vscode\javascript\webpack>npm i less-loader less -D
added 16 packages in 4s
D:\A_MyWork\M05.MYCode\vscode\javascript\webpack>
3.2 配置
修改配置文件:webpack.config.js
,新增module
节点及less
的匹配规则。
module.exports = {
module: {
// 定义了不同模块的loader
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/i,
use: [
// compiles Less to CSS
'style-loader',
'css-loader',
'less-loader',
],
},
]
}
}
3.3 测试
- 在src目录下新建
css
目录,并在css
目录下新建index.less
* {
margin: 0;
padding: 0;
li {
line-height: 30px;
padding-left: 20px;
font-size: 12px;
}
}
- 在源代码index.js中导入样式
import './css/index.less'
- 执行打包命令
npm run dev
,查看效果
3.4 附件
3.4.1 webpack.config.js
// 导入node.js中专门操作路径的模块
const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 创建插件的实例对象
const htmlPlugin = new HtmlWebpackPlugin({
// 指定复制源文件的路径
template:'./src/index.html',
// 指定创建文件的生成路径
filename:'./index.html'
})
module.exports = {
mode:'development',
// 打包入口的文件路径,__dirname表示当前文件的存放路径,即工程路径
entry:path.join(__dirname,'./src/index.js'),
output: {
// 输出文件的存放路径
path: path.join(__dirname,'./dist'),
// 输出文件的名称
filename: 'bundle.js'
},
devServer: {
static: {
directory: path.join(__dirname, "/"),
},
// compress: true,
port: 8080,
host:'127.0.0.1',
open:true
},
plugins:[htmlPlugin],
module: {
// 定义了不同模块的loader
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/i,
use: [
// compiles Less to CSS
'style-loader',
'css-loader',
'less-loader',
],
},
]
}
}
3.4.2 index.js
import $ from 'jquery'
import './css/index.css'
import './css/index.less'
$(function () {
$("li:odd").css('background-color','red')
$("li:even").css('background-color','pink')
})
3.4.3 package.json
{
"name": "webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack serve"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"jquery": "^3.7.0"
},
"devDependencies": {
"css-loader": "^6.8.1",
"html-webpack-plugin": "^5.5.3",
"less": "^4.1.3",
"less-loader": "^11.1.3",
"style-loader": "^3.3.3",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
}
}
四、 url-loader的安装和使用
4.1 Base64图片
base64
编码是一种图片处理格式,通过特定的算法将图片编码成一个长串字符串,在页面上显示的时候,可以用该字符串来代替图片的url
属性。
优点
1、减少一个图片的http请求。网页中使用base64
格式的图片时,不用再请求服务器调用图片资源,减少了服务器访问次数。
2、base64
编码的字符串,更适合不同平台、不同语言的传输;
缺点
1、根据base64
的编码原理,编码后的大小会比原文件大小大1/3
,如果把大图片编码到html/css
中,不仅会造成文件体积增加,影响文件的加载速度,还会增加浏览器对html
或css
文件解析渲染的时间。
2、使用base64
无法直接缓存,要缓存只能缓存包含base64
的文件,比如HTML
或者CSS
,这相比于直接缓存图片的效果要差很多。
3、兼容性的问题,ie8以前的浏览器不支持。一般一些网站的小图标可以使用base64
图片来引入。
base64图片格式格式举例
data:image/png;base64,iVBORw0KGgoAAAANSUh...
4.2 安装
- 不指定版本安装:
npm i url-loader file-loader -D
- 指定版本安装:
npm i url-loader@4.1.1 file-loader@6.2.0 -D
参考文档:url-loader文档
D:\A_MyWork\M05.MYCode\vscode\javascript\webpack>npm i url-loader file-loader -D
added 6 packages in 23s
D:\A_MyWork\M05.MYCode\vscode\javascript\webpack>
4.3 配置
修改配置文件:webpack.config.js
,新增module
节点。配置匹配规则,url-loader?limit=4734
其中?
之后的是loader
的参数项。
limit
用来指定图片的大小,单位是字节(byte
)- 只有
<= limit
大小的图片,才会被转为base64
格式的图片
module.exports = {
module: {
// 定义了不同模块的loader
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/i,
use: [
// compiles Less to CSS
'style-loader',
'css-loader',
'less-loader',
],
},
{
test: /\.(png|jpg|gif)$/,
// 如果loader只有一个,只传递一个字符串即可
use : 'url-loader?limit=4734'
}
]
}
}
4.4 测试
4.4.1 index.js
import $ from 'jquery'
import './css/index.css'
import './css/index.less'
import logo from './images/logo.png'
$(function () {
$("#img").attr("src",logo)
$("li:odd").css('background-color','red')
$("li:even").css('background-color','pink')
})
4.4.2 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- <script src="./index.js"></script> -->
<!-- 加载和引用内存里的bundle.js -->
<!-- <script src="/bundle.js"></script> -->
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
</ul>
<img src="" alt="" id="img"/>
</body>
</html>
4.4.3 执行
- 执行打包命令
npm run dev
,查看效果
五、babel-loader
webpack
只能打包处理一部分高级的javascript
语法,对于那些webpack
无法处理的高级js
语法,需要借助于babel-loader
进行打包处理。
参考文档:
5.1 安装
- 不指定版本安装:
npm i babel-loader @babel/core @babel/plugin-proposal-decorators -D
- 指定版本安装:
npm i babel-loader@9.1.3 @babel/core@7.22.9 @babel/plugin-proposal-decorators@7.22.7 -D
D:\A_MyWork\M05.MYCode\vscode\javascript\webpack>npm i babel-loader @babel/core @babel/plugin-proposal-decorators -D
added 67 packages in 6s
D:\A_MyWork\M05.MYCode\vscode\javascript\webpack>
5.2 配置
修改配置文件:webpack.config.js
,新增module
节点。配置匹配规则.
注意:必须使用exclude
指定排除项,因为node_modules
目录下的第三方包不需要被打包,无需程序员关心,程序员只需要把自己的代码转换即可。
module.exports = {
module: {
// 定义了不同模块的loader
rules: [
{
test: /\.m?js$/,
// 必须使用exclude指定排除项,因为node_modules目录下的第三方包不需要被打包,无需程序员关心,程序员只需要把自己的代码转换即可
exclude: /(node_modules|bower_components)/,
use:'babel-loader'
}
]
}
}
5.3 babel.config.js
在项目根目录下,新建 babel.config.js
配置文件,定义babel
的配置项,可参考网址: @babel/plugin-proposal-decorators文档
module.exports = {
// 声明 babel 可用插件
// 将来,webpack 在调用 babel-loader 的时候,会先加载 plugins 插件来使用
"plugins": [
["@babel/plugin-proposal-decorators", { "version": "legacy" }]
]
}
5.4 测试
- 修改
index.js
,新增如下代码,定义了一个装饰器语法
function info(target) {
target.info = "Person info."
}
@info
class Person{}
console.log(Person.info);
- 执行打包命令
npm run dev
,查看效果