webpack自定义loader

8 篇文章 1 订阅
3 篇文章 0 订阅

自定义loader

  • Loader是用于对模块的源码进行转换处理的

  • loader本质上是一个导出为函数的JavaScript模块

  • loader runner库调用这个函数,然后将上一个laoder产生的结果或者资源文件传入进去;

  • 所有的内容在经历过loader之后都必须转化为javascript字符串

  • content : 读取到的相关模块文件

    Mate: 即一些 元素参数需要传入的

    /* selfloader.js >> */
    // 这个了loader被称之为normalloader
    module.exports = function (content, sourcemap, mate) {
      // TODO ..
      // 一般情况下只使用content
    }
    
    // 我们还可以拥有其他的loader
    module.exports.pitch = function (content, sourcemap, mate) {
      // TODO ..
    }
    
  • 使用自定义loader

    module.exports = {
      context: './xx',
      module: {
        rules: [
          {
            test: /\.js$/,
            use: './selfloader' // 这里的路径是相对于 context的
          }
        ]
      },
      resolveLoader:{
        modules: ["node_modules","./xxx/selfloader.js"] // 加上这个之后,我们可以再使用loader的时候不再 填上路径
      }
    }
    
  • 这里需要注意,我们在执行loader的过程中,默认是寻找的normalloader执行的,此时,是按照rules的从尾到首来执行的,但是,loader里面的其余loader则会按照rules的从首到尾执行!!!

    在源代码中,loader-runner这个库是这样做的,它会先去执行代码中的pitch-loader,并且同时对loaderIndex++,执行完成之后,loader-runner会根据loaderIndex再以此去取出normailloader,并且同时对loaderIndex–

  • Enforce于loader执行顺序之间的关系

    • 默认所有的laoder都是normail

    • 在行内设置的loader是inline,(import ‘loader1!|loader2!./test.js’)

    • 也可以设置enforce设置pre和post

    • 	rules: [
           {
             test: /\.js$/,
             use: './selfloader', // 这里的路径是相对于 context的
             enforce: "pre", // 
           }
         ]
      

      设置上了enforce属性之后,那么normail就会先执行

      但是pitch会在最后执行

  • pitchloader阶段执行顺序

    • post,inline,normail,pre
  • normal阶段执行顺序

    • pre, normal, inline, post
  • 异步loader

    • 在前面的笔记中讲述的都是同步的loader

    • module.exports = function (context) {
        // 同步的loader中必须要有返回值才可以
        // 有两种办法做到,第一是直接 return出去你的值,
        // 第二,调用laoder执行期上下文callback 
        this.callback(err, context, sourcemap, mate);
        
        // 异步处理方式
        const callback = this.async();
        // this.async将会返回我们的callback,这是一个异步机制
        setTimeout(() => {
          // 这里的第一个参数可以是err,也可以是context
          callback(context)
        }, 0)
      }
      
  • 自定义loader参数的获取

    • 我们需要借助官方提供的库loader-utils中的getOptions

    • const { getOptions } = require("loader-utils");
      
      module.exports = function (content, sourcemap, mate) {
        getOptions(this) // 将会得到传入的参数
      }
      
    • babel-loader

      const { getOptions } = require("loader-utils");
      const { babel } = require("@babel/core");
      
      module.exports = function (content, sourcemap, mate) {
        const options = getOptions(this) // 将会得到传入的参数
        const callback = this.async();
        
        babel.tranform(content, options, ( err, result) => {
          callback(err, result.code) // result包含很多,比如ast树
        })
      }
      
  • loader解析markdown

    • marked解析md文件,输出的是html格式的字符串

    • 因为loader-runner的缘故,loader的返回值需要是一个js格式字符串,因此我们还需要借助html-loader来解析html格式的字符串

    • 这里推荐js库highlight.js帮助我们为marked解析出来为html做出美化

      const marked = require("marked");
      const hljs = require("highlight.js")
      
      module.exports = function (content, sourcemap, mate) {
      
        // 执行完成之后我们会发现解析出来的代码会自动添加上一些class
        marked.setOptions({
          highlinght: function(code, lang){
            return hljs.highlight(lang, code).value
          }
        })
        
        const html = marked(content);
        return content;
      }
      
      
      // 在src代码中我们可以自行去给class写一些样式
      // 我们也可以使用 highlight.js 的默认样式处理我们的解析代码
      import "highlight.js/styles/default.css"
      // 内部还有非常多的默认样式
      
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值