用了这么久 webpack 一直想简单的记录以下这篇博客来讲解如何手写自己所需的 webpack loader 和 Plugin,说人话就是自定义 webpack 的加载器与插件,其实官方文档也有详细的记录,大家可直接查看官方文档都 ok 的
loader
一、loader 是什么,有什么用
是 webpack 用于在编译过程中解析各类文件格式,并输出;
本质上就是一个 node 模块,通过写一个函数来完成自动化的过程;
由此我们就可以在开发模式下,通过解析各类前端无法解析的文件格式,然后将其解析后返回为对象或字符串供前端开发时使用,在 webpack 的编译过程中自动会将我们前端项目中引用的文件格式对应到指定 loader 解析后输出。
二、怎么写一个自定义 loader
接下来我将写一个非常简单的 loader 来解析 txt 文件,它将满足以下功能
读取 txt 文件内容并输出为一个对象,对象内包括文件内容与文件名
读取 webpack loader 选项,将内容中的 [name] 替换为我们选项 name 的值
// web
module.exports = {
//...
module: {
rules: [
{
test: /\.txt$/,
use: {
loader: (__dirname, '.;),
options: {
name: 'YOLO'
}
}
}
]
}
}
//
var utils = require('loader-utils')
module.exports = function (source) {
const options = u(this)
source = (/\[name\]/g, o)
return `export default ${ JSON.stringify({
content: source,
filename:
}) }`
}
// 测试在项目中 import 的 txt 文件
test loader output from [name]
// 前端引用
import test from '@/public;
// 在浏览器中 log 出结果,因为 txt 中保存时自动换行了,所以大家可以看到存在一个换行符
{
content: "test loader output from YOLO↵"
filename: "/Users/yanglu/Desktop/Programers/test-loader/src/public;
}
结果截图
更复杂的用法,请大家自行参照文档
writing-a-loader/
Plugin
一、Plugin 是什么,有什么用
是 webpack 用于在编译过程中利用钩子进行各种自定义输出的函数;
本质上就是一个 node 模块,通过写一个类来使用编译暴漏出来的钩子实现编译过程的可控;
由此我们就可以在开发模式下,可以通过监听编译过程的各个钩子事件来完成如释出模版,对 js、css、html 进行压缩、去重等各类操作,结束后释出对应文件等等你可以想到的任何操作
二、先说点细节,再说怎么写一个自定义 plugin
webpack 的插件简单来说就是在函数中通过调用 webpack 执行的钩子来完成自动化的过程,在函数中我们通过监听 compiler 钩子,并在回调中执行我们需要做的事情,最后调用回调中的第二个参数 callback 使 webpack 继续构建,否则将在此处停止编译,整个过程都是在 webpack 的整个编译过程中利用其暴漏出的钩子进行的
以下是我写的一个简短的例子,它完成了这样的功能:
仿照 htmlWebpackPlugin 进行模版输出,实例化插件时传入模版地址,释出文件名,需解析参数变量即可;
解析过程中会解析 {{ key }} 中的 param,将 {{ key }} => 实例化对象中 params[key]
// webpack 配置
var EmitTemplatePlugin = require('./emit-template-plugin')
plugins: [
new EmitTemplate({
template: './src/template;,
filename: (__dirname, '.;),
params: {
title: '测试啊',
name: 'YOLO'
}
})
]
// emi
const fs = require('fs')
function EmitTemplate (options) {
= o
= o
= o
}
Emi = function (compiler) {
var self = this
com('emit', function (compilation, callback) {
, (err, data) => {
if (err) throw err
// 匹配参数替换 html 模版中变量
var reg = new RegExp(`{{\\s*(${Object.key).join('|')})\\s*}}`, 'g')
var html = da().replace(reg, function (str, key, index) {
return [key]
})
, html, function () {
con('模版写入成功')
callback()
})
})
})
}
module.exports = EmitTemplate
// 模版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
</head>
<body>
<div class="">
{{ name }}
</div>
</body>
</html>
// 解析后的释出文件 index-emit-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>测试啊</title>
</head>
<body>
<div class="">
YOLO
</div>
</body>
</html>
上面的写法是 webpack2 或 webpack3 调用钩子的方法,在 4 中已变为
1
com([compiler hooks event], (compilation, callback) => {
...
})
【前端迷】公众号是一个公益性的前端技术分享社区,不定期为前端开发者带来面试经历,源码解析以及技术分享,欢迎大家订阅。
欢迎关注公众号,回复【教程】获取最新教学资源视频,回复【pdf】获取前端开发热门书籍pdf。
微信扫码关注