什么是loader


webpack enables use of loaders to preprocess files. This allows you to bundle any static resource way beyond JavaScript. You can easily write your own loaders using Node.js.

webpack可以通过使用loader来预处理文件。这能让你把任意静态资源打包成JavaScript。loader可以使用node.js 简单的书写。

如上文官网原文的解释,众所周知webpack只能处理js模块,那么例如 .vue,.jsx 之类的文件处理就需要全部借助loader来做了。

常见的loader

见官网推荐:https://webpack.js.org/loaders/

如何使用loader

  1. 打开项目中的webpack默认文件,默认是webpack.config.js(此处不考虑vue-cli3+这种二次封装的配置)
  2. modules -> rules
  3. api:
    1. test: RegExp —— 查找符合条件的文件
    2. use: string | string[] | object[]
      1. string —— 只使用一个loader,且无其他配置项
      2. string[] —— 使用多个loader,顺序是从后往前,无配置项
      3. object[] —— 使用多个loader,顺序是从后往前,有的有配置项

        举例

        ```javascript const path = require(‘path’)

module.exports = { entry: “./src/index.js”, output: { filename: “[name].js”, path: path.join(__dirname, “dest/“) }, mode: “development”, plugins: [], resolveLoader: { modules: [“node_modules”, “./Loaders”] }, / here / module: { rules: [ { test: /.scss/, use: [“style-loader”, “css-loader”, “sass-loader”]

  1. }
  2. ]
  3. }

}

  1. <a name="w06bw"></a>
  2. ## 如何书写一个自定义loader
  3. <a name="AtWnR"></a>
  4. ### loader 定义的规则
  5. 1. loader 必须是一个js模块,并且export的结果要是一个方法。
  6. 1. loader不能使用箭头函数声明,因为在实际运行时,他的this会被webpack放入一系列方法。
  7. 1. loader必须有一个返回值,在同步的程序中,可以使用 `return` 或 `this.callback()` 来声明返回值;在异步的程序中,必须使用 `this.async()` 来返回,这样webpack才会等待异步执行结束。
  8. 1. loader 的返回值必须是 String 或者 Buffer。
  9. <a name="rwbIH"></a>
  10. ### 例子
  11. - 将一个 `console.log('Hello webpack!')` 编译成 `console.log('Hello loader!!')`
  12. ```javascript
  13. // index.js
  14. console.log('hello webpack!')
  15. // js-loader
  16. module.exports = function (source) {
  17. // 上一个loader处理后的结果或原文
  18. console.log(source); // console.log('hello webpack!')
  19. this.callback(null, source.replace("webpack", "loader!"))
  20. }
  21. // webpack.config.js
  22. const path = require('path')
  23. module.exports = {
  24. entry: "./src/index.js",
  25. output: {
  26. filename: "[name].js",
  27. path: path.join(__dirname, "dest/")
  28. },
  29. mode: "development",
  30. plugins: [],
  31. module: {
  32. rules: [
  33. {
  34. test: /\.js/,
  35. use: path.join(__dirname, './Loaders/js-loader.js')
  36. }
  37. ]
  38. }
  39. }

更简单的写法 —— resolveLoader

  • 从上文的例子里可以看出,loader的path要写绝对路径,当需要同时放置多个loader时,书写起来会变的非常冗杂,我们可以通过修改webpack配置的resovleLoader来解决这个问题。
  • resolveLoader 可以用来配置寻找一些东西的路径,在这里我们只需要修改寻找loader的,loader是用于module里面的,所以即为:

    1. module.exports = {
    2. // ...
    3. resolveLoader: {
    4. // 这里的路径可以是相对路径,也可以是命名的别名
    5. modules: ['node_modules', './Loaders']
    6. }
    7. }
  • 命名完成后,就可以直接使用 use: 'js-loader' 来进行书写了。webpack会先寻找node_modules里面的js-loader模块,再去Loaders文件夹中寻找。

给loader传入配置

1. 在配置文件中传入

  1. // webpack.config.js
  2. module.exports = {
  3. // ...
  4. module: {
  5. rules: [
  6. {
  7. test: /\.js/,
  8. use: [{
  9. loader: "js-loader",
  10. options: {
  11. param: "hello",
  12. replaceParam: "hi"
  13. }
  14. }]
  15. }
  16. ]
  17. }
  18. }

2. 在loader中接收参数

有两个api可以拿到传入的参数,两者拿到的东西是完全一样的:

  1. this.query
  2. 额外安装 loader-utils 组件,通过 loaderUtils.getOptions(this)
    1. module.exports = function (source) {
    2. console.log(this.query); // { param: "hello", replaceParam: "hi" }
    3. this.callback(null, source.replace(this.query.param, this.query.replaceParam))
    4. }

文档

  1. webpack给loader注入的this方法:https://webpack.js.org/api/loaders/#thisquery