webpack自定义loader和plugin
Posted 我是真的不会前端
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webpack自定义loader和plugin相关的知识,希望对你有一定的参考价值。
写在前面的话
首先我想说,绝大多数初中级前端别说手写这玩意了,连webpack打包都不需要接触到,哪怕是高级,外包型公司或者大型自研项目理论上也接触不到。就算接触到了,现有的优化构建方案和第三方插件和包非常多,webpack的生态其实做的很好了,但是吧,你只要在简历里不管是真搞过还是吹了牛写上了对webpack的研究,那很有可能,面试官会问你又没有自己写过loader和plugin啊。那没事咱不慌,问就是写过,写给他看就是了
自定义loader
官方文档
https://webpack.docschina.org/contribute/writing-a-loader/
方法
首先官方文档告诉我们,要自定义loader,在webpack.config.js里通过绝对路径引入自定义loader。
以file-loader举例 源码中除了开头的绑原型链处理兼容性问题。核心内容就是一个带content参数的函数。所有编译的内容其实都是字符串。将处理的字符串交给下一个函数。就是字符串的编译
在config中创建一个loaders目录,在目录中创建一个你的loader文件
基本语法
其实觉大多数的loader的基本语法都是如此,就是核心是个函数
function loader(source)
const res =''
return `module.exports=$res`
module.exports=loader
自定义file loader
// 自定义Loader
module.exports = function(source)
// do something
let result = source.replace(/\\#/img, ' ')
// do something
// console.log('txt-loader result', result)
return `module.exports = $JSON.stringify(result)`
用法
加上自定义loader 注意loader的链式调用,下一个接收的模块是什么,所以要注意是用modules抛出还是用ES6的语法环境,最好做个判断,否则会出错。
test: /\\.txt$/i, use: ['./config/loaders/txt-loader.js']
记得放在自己的包中,不要写在node-modules包了
难点
说实话,造轮子实际上需要有较强的源码能力。所以不管未来造啥轮子,第一步,看文档看文档看文档。
阅读源码的逻辑是要把插件或者框架的核心看懂。比如vue的template编译,那是非常复杂的字符串判断。
手搓loader,难的不是写法和思路,而是字符串的编译解析。如果你懂甚至很精通编译原理,那这个面试问题就成了你的出场,是你给面试官表演的时候了,其实vue-loader也是难在编译原理。所以想想,是不是大学没学好?
自定义plugin
上官网
https://webpack.docschina.org/contribute/writing-a-plugin/
这是官网给的步骤
简单翻译下步骤
第一步,有个命名的function或者class
第二步 定义apply方法定义在原型链上 如果是面向对象 直接放在类的内部就是了
第三步 指定事件的hook,指向本身,tap事件
第四步 操作 webpack 内部实例特定数据。
第五步 处理回调
自定义一个clean 清除目录方法
clean有缺陷,每次clean后dist文件根节点的文件清理不干净,比如在dist根目录的自己创建的文件清理不干净。webpack v5中实现删除dist目录的写法:缺陷是publicPath外面的文件无法删除。
clean-webpack-plugin源码
https://unpkg.com/browse/clean-webpack-plugin@4.0.0-alpha.0/dist/clean-webpack-plugin.js
方法
config文件夹下plugins文件并创建自己的pluginjs文件
导入
plugins: [
new MyCleankPlugin()
],
核心极简代码
const del = require("del")
const path = require("path")
// 自定义定义插件
class MyCleankPlugin
// apply是webpack plugin的入口方法
apply(compiler)
// 触发插件运行
compiler.hooks.emit.tap('qf-clean-plugin', () =>
// 使用del这个库执行删除操作
try
const deleted = del.sync(['*'],
cwd: path.resolve(__dirname, '../../dist'),
dot: true,
ignore: []
)
catch (error)
throw error
)
module.exports = MyCleankPlugin
分析
用了del node的第三方包 引入path模块 核心就是个class类,用del库同步删除,调用apply方法,核心就是class 里面的apply接收编译器的方法compiler 里面有webpack编译器内置的方法,同时接收一个事件tap,这个事件触发自己。在触发时进行业务操作,抛出class。在plugins里new一下实例化就行了
以上是关于webpack自定义loader和plugin的主要内容,如果未能解决你的问题,请参考以下文章
前端工程化7:自定义实现Webpack中的Loader和Plugin