webpack中loader笔记

loader

loader是做什么的?

众所周知,webpack中万物皆模块,但是呢webpack默认只能处理js模块,那要是用户 import一个图片,webpack处理不了,那不就很尴尬了,所以才有了loader机制,So,loader其实就是处理模块的,如果图片有 file-loader,vue文件有 vue-loader 等...

怎么自定义loader

说明 其实loader就是个函数,他的参数是这个loader匹配到的源文件,它的返回值就是模块处理后的结果,比如下面这个loader 处理js文件,把每个js文件前面都加上注释,注明打包时间

{
  test: /\.js$/,
  use: "loader1"
}

上面的这个自定义loader的参数其实就是js源码了

loader1源码

function loader1(source) {
  console.log(source);
  let zhushi = `
  /*我是注释
  打包时间${new Date().getFullYear()}/${new Date().getMonth() + 1}/${new Date().getDate()} ${new Date().getHours()}:${new Date().getMinutes()}
  我是注释*/  
  `;
  return zhushi + source;
}

module.exports = loader1;

使用loader

  • 1 使用loader
module.exports = {
  mode: "development",
  entry: "./main.js",
  output: {
    filename: "budle.js",
    path: path.resolve(__dirname, "dist"),
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        //使用自定义loader
        //写入要使用loader的绝对路径
        use: path.resolve(__dirname, "loaders", "loader1.js"),
      },
      {
        test: /\.css$/,
        //使用多个第三方loader
        //style-loader 用来将样式转为style标签插入head标签中
        //从右向左执行 先执行 css-loader 再执行 style-loader
        //跟我们使用js向页面插入样式是一样的
        use: ["style-loader","css-loader"],
      },
      {
        test: /\.less$/,
        //对象方式使用第三方loader并给loader传递options
        use: [
          {
              loader:"style-loader",
              options:{
                  insertAt:"top"
              }
          },
          "css-loader"],
      },
    ],
  },
};

如果觉得使用时需要写入绝对路径很麻烦,有两种方法可以帮助webpack找到loader

  • A 可以定义webpack.config.js中的resolveLoader.alias(即配置别名)
let path = require("path");

module.exports = {
  mode: "development",
  entry: "./main.js",
  output: {
    filename: "budle.js",
    path: path.resolve(__dirname, "dist"),
  },
  resolveLoader: {
    alias: {
      loader1: path.resolve(__dirname, "loaders", "loader1.js"),
    },
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: "loader1",
      },
    ],
  },
};
  • B 定义webpack的查找目录
let path = require("path");
module.exports = {
  mode: "development",
  entry: "./main.js",
  output: {
    filename: "budle.js",
    path: path.resolve(__dirname, "dist"),
  },
  resolveLoader: {
    //先去node_modules中找 如果找不到到loaders中找
    modules:["node_modules","loaders"]
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: "loader1",
      },
    ],
  },
};

使用多个loader

  • 1 数组方式使用(执行的顺序为倒序即 loader1 > loader2 > loader3)
  module: {
    rules: [
      {
        test: /\.js$/,
        use: ["loader3", "loader2","loader1"],
      },
    ],
  },
  • 2 多个rules方式(执行的顺序为倒序即 loader1 > loader2 > loader3)
  module: {
    rules: [
      {
        test: /\.js$/,
        use: "loader3",
      },
      {
        test: /\.js$/,
        use: "loader2",
      },
      {
        test: /\.js$/,
        use: "loader1",
      },
    ],
  },

loader的分类

分为 pre(前置)、normal、post(后置)、inline(行内,嵌在代码中的loader) 四类(默认是normal),loader的执行顺序为

pre > normal > inline > post

上面说loader的执行顺序是倒序,那如果我真的是希望强制更改loader3在 loader1之前执行就可以这么做(此时的执行顺序为 loader3 > loader1 > loader2)

  module: {
    rules: [
      {
        test: /\.js$/,
        use: "loader3",
        enforce:"pre" //增加了此行
      },
      {
        test: /\.js$/,
        use: "loader2",
      },
      {
        test: /\.js$/,
        use: "loader1",
      },
    ],
  },

inline loader的使用方式

console.log("hello")
let str = require("inline-loader!./a.js");
//这句话的意思就是把a.js的内容导入,并传递到inline-loader,然后require的是inline-loader处理后的结果

loader中可以使用的webpack提供的常用api