webpack-loader详解

一、loader的分类

1.pre:前置loader
2.normal:普通loader
3.inline:内联loader
4.post:后置loader

二、执行顺序

pre > normal > inline > post,相同类型的loader执行顺序为:从右到左,从下到上

module:{
	rules:[{
		enforce:"pre",  //通过这个参数来定义loader的类型,默认是normal类型
		test:/\.js/,
		loader:"loader"
	}]
}

内联loader不能用上面的方式定义,必须用下面的方式

// 多个loader用!分开,要给loader传参就必须用?后面接参数,就比如?module,module就是css-loader的参数
import style from "style-loader!css-loader?module!./style.css"

使用内联loader会遇到一个问题,就比如上面的代码使用了css-loader,可能在配置文件里面也配置了css-loader,这样就会造成重复,所以内联loader提供了添加前缀的方式来避免这种问题

  • 使用 ! 前缀,将禁用所有已配置的 normal loader(普通 loader)
import Styles from '!style-loader!css-loader?modules!./styles.css';
  • 使用 !! 前缀,将禁用所有已配置的 loader(preLoader, loader, postLoader)
import Styles from '!!style-loader!css-loader?modules!./styles.css';
  • 使用 -! 前缀,将禁用所有已配置的 preLoader 和 loader,但是不禁用 postLoaders
import Styles from '-!style-loader!css-loader?modules!./styles.css';

三、手写loader

1.定义同步testLoader.js文件

/**
 *  content:文件内容
 *  map  SourceMap
 *  meta  别人loader传递的参数,必须是处理同一个文件的loader
 */
module.exports = function (content, map, meta) {
  /**
   *    callback参数
   *    第一个参数是报错信息,没有报错就是null,其余参数就是上面loader接收的参数
   * 	这种写法也叫同步loader,同步loader里面不能写异步操作
   */
  this.callback(null, content, map, { whh: 1 });
};

2.定义异步testLoader.js文件

/**
 *  content:文件内容
 *  map  SourceMap
 *  meta  别人loader传递的参数,必须是处理同一个文件的loader
 */
module.exports = function (content, map, meta) {
  const callback = this.async();  //等同于await,有异步操作的时候,这样才能拿到值
  setTimeout(() => {
    callback(null, content, map, { whh: 1 });
  }, 1000);
};

3.定义raw loader

/**
 *  content:文件内容
 *  map  SourceMap
 *  meta  别人loader传递的参数,必须是处理同一个文件的loader
 */
module.exports = function(content,map,meta){
	//这里的content就变成二进制buffer数据了,可以用于处理图片等等媒体文件
    console.log(content);
    return content;   //不需要做太多操作的时候,就可以直接返回content,不需要使用callback
}
module.exports.raw = true;   //开启

4.定义picth loader

/**
 *  content:文件内容
 *  map  SourceMap
 *  meta  别人loader传递的参数,必须是处理同一个文件的loader
 *  这个函数就是普通函数
 */
module.exports = function (content, map, meta) {
  return content;
};
/**
 * {
        test: /\.js$/,
        use: ["loader1","loader2","loader3","loader4","loader5"],
    },
    假如有多个loader来处理js文件,每个loader都有定义pitch函数,那么他们的顺序是先从左到右执行loader里面的picth函数,
    然后再从右到左执行普通函数,pitch函数的return不是必需的,如果在执行picth函数途中,某个loader的pitch函数有return,
    那么整个picth执行会结束,然后从当前loader开始从右到左执行普通的函数
    举例说明,
    执行顺序为loader1里面的pitch,然后loader2里面的pitch,一直到loader5里面的pitch,然后再执行loader5里面的普通函数,
    一直到loader1里面的普通函数,整个流程就是loader的执行过程,但是如果执行到loader3里面的pitch,发现有return,
    那么就不会执行loader4和loader5里面的pitch函数和普通函数,会直接执行loader3的普通函数,然后loader2的普通函数,
    最后到loader1的普通函数,然后执行结束
*/
module.exports.pitch = function () {
  console.log("picth");
  return "result";
};

使用方法:

{
   test: /\.lth$/,
   loader: path.resolve(__dirname, "../loader/testLoader.js"),
},

还有很多很多API,就不详细说了,看官方文档或者其他人的博客吧
官方链接
这里主要说一下传参的api,这个还是很重要的

module.exports = function (content, map, meta) {
   const obj =  this.getOptions();  //通过这个来获取传递进来的参数
   console.log(obj);  //{ name: 'kobe', age: 24 }
  return content;
};
 {
        test: /\.lth$/,
        use: [
          {
            loader: path.resolve(__dirname, "../loader/testLoader.js"),
            options: {   //通过options传递给loader
              name: "kobe",
              age: 24,
            },
          },
        ],
      },

loader的详解就到这里了,可以看着官方文档和百度试着自己写一个loader,下一篇再说plugin的详解了

你可能感兴趣的:(webpack,前端,node.js)