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

webpack配置之自定义loader

webpack入门和实战:全面理解和运用loader和plugins

Webpack自定义loader的执行顺序实战分析

webpack打包-----plugin

webpack打包-----plugin