file-loader、url-loader实现
废话不多说,下面开始实现自己的 file-loader 和 style-loader。
1. 准备工作
基本环境请参考之前的文章《babel-loader实现》,下面着重介绍一下改动部分。
根目录下新建 images 文件夹,并放入名为 logo.jpg 的图片用于测试。
mkdir images
loaders 文件夹下新建 file-loader.js、url-loader.js 文件。
删除已经存在的 a.js 文件,删除 index.js 的无用逻辑。
cd loaders && touch file-loader.js && touch url-loader.js
index.js 新增如下代码。
/**
* @file 入口文件
* @module src/index
* @version 0.1.1
* @author yueluo <yueluo.yang@qq.com>
* @time 2020-06-27
*/
/**
* @requires images/logo 测试图片
*/
import logo from '../images/logo.jpg';
// 创建IMG标签
const img = document.createElement('img');
// 为IMG标签设置引用路径
img.src = logo;
// 添加IMG标签到body元素中
document.body.appendChild(img);
dist 目录中新建 index.html 文件,并引入打包后的 bundle.js 文件。
cd dist && touch index.html
当前目录结构如下。
2. file-loader实现
(1)修改webpack.config.js文件
增加匹配图片的规则,并指明使用的 loader 为 file-loader。
/**
* @file webapck配置文件
* @module webpack.config.js
* @version 0.1.1
* @author yueluo <yueluo.yang@qq.com>
* @time 2020-06-27
*/
/**
* @requires node_modules/path node内置模块
*/
const path = require('path');
// 导出webpack配置
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
resolveLoader: {
modules: ['node_modules', path.resolve(__dirname, 'loaders')]
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.jpg$/,
use: 'file-loader'
}
]
}
}
(2)编写file-loader
使用 webpack 工具类(loader-utils)对图片文件进行处理,并指定文件名称。
文件类型的数据,还需要设置 loader 的 raw 属性为 true,将其作为二进制数据处理。
/**
* @file file-loader
* @module loaders/file-loader
* @version 0.1.1
* @author yueluo <yueluo.yang@qq.com>
* @time 2020-06-27
*/
/**
* @requires node_modules/loader-utils webpack工具
*/
const loaderUtils = require('loader-utils');
/**
* @description 自定义loader
* @param {string} sourceCode - 源代码
* @return {string}
*/
function loader (sourceCode) {
const filename = loaderUtils.interpolateName(this, '[hash].[ext]', {
content: sourceCode
});
// 文件提交
this.emitFile(filename, sourceCode);
return `module.exports = "${filename}"`;
}
// 二进制数据处理
loader.raw = true;
// 导出自定义loader
module.exports = loader;
编写完 file-loader 后,运行 npx webpack 命令。
运行 dist 目录下的 index.html。
可以看到图片已经正常加载出来,图片的引用路径也是打包后的路径。
3. url-loader实现
url-loader 可以看作是 file-loader 的升级版,使用 url-loader 必须安装 file-loader。
url-loader 内部依赖 file-loader,它可以根据指定的字节大小,对图片进行 base64 编码或者图片文件的解析处理。下面就开始实现 url-loader。
(1)修改webpack.config.js文件
修改匹配到图片时处理的 loader 为 url-loader,并添加字节大小限制。
/**
* @file webapck配置文件
* @module webpack.config.js
* @version 0.1.1
* @author yueluo <yueluo.yang@qq.com>
* @time 2020-06-27
*/
/**
* @requires node_modules/path node内置模块
*/
const path = require('path');
// 导出webpack配置
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
resolveLoader: {
modules: ['node_modules', path.resolve(__dirname, 'loaders')]
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.jpg$/,
use: {
loader: 'url-loader',
options: {
limit: 100 * 1024
}
}
}
]
}
}
(2)url-loader实现
安装图片格式处理的库 mime。
npm i mime --save-dev
url-loader的核心逻辑就是根据其配置项,进行 base64 处理或者使用 file-loader 处理。
/**
* @file url-loader
* @module loaders/url-loader
* @version 0.1.1
* @author yueluo <yueluo.yang@qq.com>
* @time 2020-06-27
*/
/**
* @requires node_modules/loader-utils webpack工具
* @requires node_modules/mime 图片格式处理工具
*/
const loaderUtils = require('loader-utils'),
mime = require('mime');
/**
* @description 自定义loader
* @param {string} sourceCode - 源代码
* @return {string}
*/
function loader (sourceCode) {
const options = loaderUtils.getOptions(this),
limit = options.limit;
if (limit && limit > sourceCode.length) {
// base64处理
return `module.exports = "data:${mime.getType(this.resourcePath)};base64,${sourceCode.toString('base64')}"`;
} else {
// 使用file-loader处理
return require('./file-loader').call(this, sourceCode);
}
}
// 二进制数据处理
loader.raw = true;
// 导出自定义loader
module.exports = loader;
好了,url-loader 实现完毕。执行 npx webpack 命令进行打包。
可以很明显的看到,处理的文件中并没有图片文件,这是个好消息。
下面再运行 dist 目录下的 index.html 进行测试。
可以看到,图片依旧可以正常显示,并且引入的方式是 base64 编码格式。
这张图片的大小是 40kb,webpack配置的限制为 100kb,所以图片被 base64 处理。
下面修改一下字节限制为 20kb。再运行 npx webpack 命令进行打包。
module: {
rules: [
{
test: /\.jpg$/,
use: {
loader: 'url-loader',
options: {
limit: 20 * 1024
}
}
}
]
}
可以看到,图片文件经过 url-loader 时,选择 file-loader 进行处理。
4. 总结
通过 file-loader 和 url-loader 的实现,希望你可以对 loader 的理解更加深刻。
在之后的工作中,也可以根据项目的实际需求,实现自己的 loader。💪