Webpack
本身只能处理 JavaScript
模块,如果要处理其他类型的文件,就需要使用loader
进行转换。
Loader
可以理解为是模块和资源的转换器,它本身是一个函数,接受源文件作为参数,返回转换的结果。这样,我们就可以通过 require
来加载任何类型的模块或文件,比如 CoffeeScript
、 JSX
、 LESS
或图片。
一、loader简介
loader
用于对模块的源代码进行转换。loader
可以使你在import
或 “load
(加载)” 模块时预处理文件。因此,loader
类似于其他构建工具中“任务(task
)”,并提供了处理前端构建步骤的得力方式。loader
可以将文件从不同的语言(如 TypeScript
)转换为 JavaScript
或将内联图像转换为 data URL
。loader
甚至允许你直接在 JavaScript
模块中 import CSS
文件!
在你的应用程序中,有两种使用 loader
的方式:
webpack.config.js
文件中指定 loader
。import
语句中显式指定 loader
。注意在 webpack v4
版本可以通过 CLI
使用 loader
,但是在 webpack v5
中被弃用。
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
为结束。
可以在 import
语句或任何 与 “import
” 方法同等的引用方式 中指定 loader
。使用 !
将资源中的 loader
分开。每个部分都会相对于当前目录解析。
import Styles from 'style-loader!css-loader?modules!./styles.css';
loader
支持链式调用。链中的每个 loader 会将转换应用在已处理过的资源上。一组链式的 loader 将按照相反的顺序执行。链中的第一个 loader 将其结果(也就是应用过转换后的资源)传递给下一个 loader,依此类推。最后,链中的最后一个 loader
,返回 webpack 所期望的 JavaScript。loader
可以是同步的,也可以是异步的。loader
运行在 Node.js 中,并且能够执行任何操作。loader
可以通过 options
对象配置(仍然支持使用 query 参数来设置选项,但是这种方式已被废弃)。module.rules
中使用 loader
字段直接引用一个模块。plugin
)可以为loader
带来更多特性。loader
能够产生额外的任意文件。可以通过 loader
的预处理函数,为 JavaScript
生态系统提供更多能力。用户现在可以更加灵活地引入细粒度逻辑,例如:压缩、打包、语言转译(或编译)和 更多其他特性。
loader
遵循标准 模块解析 规则。多数情况下,loader
将从 模块路径 加载(通常是从 npm install, node_modules
进行加载)。
我们预期 loader
模块导出为一个函数,并且编写为 Node.js
兼容的 JavaScript
。通常使用 npm
进行管理 loader
,但是也可以将应用程序中的文件作为自定义 loader
。
按照约定,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文档
npm i style-loader css-loader -D
npm i [email protected] [email protected] -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>
修改配置文件:webpack.config.js
,新增module
节点。
test
:表示匹配文件的类型use
:表示对应要调用的loader
;多个loader
的调用顺序是从后往前调用module.exports = {
module: {
// 定义了不同模块的loader
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
}
]
}
}
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
。
参考链接:中文文档
npm i less-loader less -D
npm i [email protected] [email protected] -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>
修改配置文件: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',
],
},
]
}
}
css
目录,并在css
目录下新建index.less
* {
margin: 0;
padding: 0;
li {
line-height: 30px;
padding-left: 20px;
font-size: 12px;
}
}
import './css/index.less'
npm run dev
,查看效果// 导入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',
],
},
]
}
}
import $ from 'jquery'
import './css/index.css'
import './css/index.less'
$(function () {
$("li:odd").css('background-color','red')
$("li:even").css('background-color','pink')
})
{
"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的安装和使用
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...
npm i url-loader file-loader -D
npm i [email protected] [email protected] -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>
修改配置文件: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'
}
]
}
}
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')
})
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<ul>
<li>1li>
<li>2li>
<li>3li>
<li>4li>
<li>5li>
<li>6li>
<li>7li>
<li>8li>
<li>9li>
ul>
<img src="" alt="" id="img"/>
body>
html>
npm run dev
,查看效果五、babel-loader
webpack
只能打包处理一部分高级的javascript
语法,对于那些webpack
无法处理的高级js
语法,需要借助于babel-loader
进行打包处理。
参考文档:
npm i babel-loader @babel/core @babel/plugin-proposal-decorators -D
npm i [email protected] @babel/[email protected] @babel/[email protected] -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>
修改配置文件: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'
}
]
}
}
在项目根目录下,新建 babel.config.js
配置文件,定义babel
的配置项,可参考网址: @babel/plugin-proposal-decorators文档
module.exports = {
// 声明 babel 可用插件
// 将来,webpack 在调用 babel-loader 的时候,会先加载 plugins 插件来使用
"plugins": [
["@babel/plugin-proposal-decorators", { "version": "legacy" }]
]
}
index.js
,新增如下代码,定义了一个装饰器语法function info(target) {
target.info = "Person info."
}
@info
class Person{}
console.log(Person.info);
npm run dev
,查看效果