Webpack loader

loader 概念

官网对 loader 的解释是这样的:

webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。

我对 loader 的理解:就是将不同类型的文件转换为 webpack 可以识别的模块。有点像中间件的感觉,如果自己写过loader 的话,应该就知道loader 就是一个个的函数

  • 接收文件内容 content
  • loader 函数中对内容进行处理(比如将 style.less 转换成 style.css
  • 返回文件内容 content

plugin 的区别:

plugin 是监听打包整个过程中的某些结点(比如打包之后的合并压缩等等),loader 能做的事情有时候 plugin 也可以做,有些 plugin 能做的事情 loader 也可以做,plugin 的生命周期更长一些,会覆盖到 loader 的生命周期

loader 分类和执行顺序

  • 分类

    • pre: 前置 loader
    • normal:普通 loader (默认值)
    • inline:内联 loader
    • post:后置 loader
  • 执行顺序

    • pre > normal > inline > post
    • 相同优先级的loader执行顺序为:从右到左,从下到上
    // 执行顺序就是:loader3 -> loader2 -> loader1
    module: {
    	rules: [
    		{test: /.js$/, loader: "loader1"},
    		{test: /.js$/, loader: "loader2"},
    		{test: /.js$/, loader: "loader3"},
    	]
    }
    

    因为 loader 的执行顺序,如果想要改变 loader 的执行顺序,除了移动我们的代码,还可以通过 设置他们的分类 来达到改变执行顺序的目的

    module: {
    	rules: [
    		{enforce: "pre", test: /.js$/, loader: "loader1"},
    		{test: /.js$/, loader: "loader2"},
    		{enforce: "post", test: /.js$/, loader: "loader3"},
    	]
    }
    
  • 使用方式

    • 配置方式:在webpack.config.js中指定loader(只能指定pre,normal,post)
    • 内联方式:在每一个 import 语句中显示指定 loader (这种方式就是 inline-loader,用的比较少)
      // 使用 css-loader 和 style-loader 处理 styles.css文件
      // 通过 !将资源中的 loader 分开
      import styles from 'style-loader!css-loader?modules!./styles.css'
      

      !: 跳过normal loader
      -!: 跳过 pre 和 normal loader
      !! : 跳过 pre、normal和post loader

loader 的属性

  1. 同步 loader
    function someSyncOperation(content) {
    	// 进行一些同步操作,如清楚console.log
    	return content.repace(/console\.log\(\.*\)/g, '')
    }
    module.exports = function(content, map, meta) {
      this.callback(null, someSyncOperation(content), map, meta);
      return; // 当调用 callback() 时总是返回 undefined
    };
    
  2. 异步 loader
    const options = {}
    function someAsyncOperation(content, cb) {
    	// 进行一些异步操作, 比如:babel 将 es6 代码转成 es5 就是异步的,就可以这样操作
    	babel.transform(content, options, function(error, result) {
    		if (error) {
    			cb(error)
    		} else {
    			cb(null, result.code)
    		}
    	})
    }
    module.exports = function(content, map, meta) {
      var callback = this.async();
      someAsyncOperation(content, function(err, result) {
        if (err) return callback(err);
        callback(null, result, map, meta);
      });
    };
    
  3. Raw loader

    默认情况下,资源文件会被转化为 UTF-8 字符串,然后传给 loader。通过设置 raw,loader 可以接收原始的 Buffer。每一个 loader 都可以用 String 或者 Buffer 的形式传递它的处理结果。Complier 将会把它们在 loader 之间相互转换。

    // 比如:进行文件处理的时候,给文件名加个 hash 串
    const loaderUtils = require('loader-utils')
    
    module.exports = function(content) {
      const interpolatedName = loaderUtils.interopolateName(this, "[hash].[ext][query]", {content})
      this.emitFile(interpolatedName, content);
      return `module.exports = "${interpolatedName}"`
    };
    module.exports.raw = true
    
  4. Pitching loader

    loader 总是从右到左地被调用。有些情况下,loader 只关心 request 后面的元数据(metadata),并且忽略前一个 loader 的结果。在实际(从右到左)执行 loader 之前,会先从左到右调用 loader 上的 pitch 方法。对于以下 use 配置:

    module.exports = {
    	...
    	rules: [
    		{
    			...
    			use: [
    			  'loader1',
    			  'loader2',
    			  'loader3'
    			]
    		}
    	]
    	...
    }
    

    loader1 pitch > loader2 pitch > loader3 pitch
    loader3 正常执行 -> loader2 正常执行 -> loader1 正常执行
    有点类似 “洋葱模型”,进去了之后再出来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值