Webpack - Loader

Jun 15

意在梳理

loader 是一个函数,处理非 JS 语法的资源

使用

对不同类型的文件使用不同 loader

module.exports = {
  module: {
    rules: [
      {
        test: /\.(a|b|c)$/, // 正则匹配文件
        use: 'some-loader', // 使用 loader
        options: {
          // 一些 loader 相关配置
        }
      }
    ]
  }
}

编写 mini-loader

实践,练手✋

raw-loader

  • 识别 txt 文件并输出为 JS 理解的语法
  • 转化要求 a.txt => module.exports / export default = 'a content'
schema.json 校验 options 的参数格式
{
  "type": "object",
  "properties": {
    "esModule": {
      "type": "boolean"
    }
  },
  "additionalProperties": true
}
raw-loader.js
module.exports = function (content, mp, meta) {
  const options = this.getOptions(schema)
  const callback = this.async()

  // 将字符串转为标准格式的json字符串,内部的换行符和引号会被转移
  const transformContent = JSON.stringify(content)
    .replace(/\u2028/g, '\\u2028')
    .replace(/\u2029/g, '\\u2029')

  const isEsModule =
    typeof options.esModule !== 'undefined' ? options.esModule : true

  callback(
    null,
    `
      ${isEsModule ? 'export default' : 'module.exports ='} 
      ${transformContent};
    `,
  )
}
webpack.config.js
{
  test: /\.txt$/,
  use: [
    {
      loader: 'raw-loader',
      options: {
        esModule: true,
      },
    },
  ],
},

file-loader

  • 识别 图片、视频、字体资源等文件
    • 根据 options.name 给文件重命名
    • 将重命名的文件输出至打包后的 outputPath 目录下
schema.json 校验 options 的参数格式
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "outputPath": {
      "type": "string"
    }
  },
  "additionalProperties": true
}
file-loader.js
const path = require('path')
const { interpolateName } = require('loader-utils')

module.exports = function (content, map, meta) {
  const options = this.getOptions(schema)

  // test.jpg -> [name]-[hash].[ext] -> test-xxxx.jpg
  const url = interpolateName(this, options.name, {
    content,
  })

  // 打包的目的地址
  const outputPath = path.posix.join(options.outputPath, url)
  this.emitFile(outputPath, content)

  // 填入 src 的 publicPath
  // 在浏览器中能够访问到的构建文件的路径 __webpack_public_path__,等于 output.publicPath
  const publicPath = `__webpack_public_path__ + ${JSON.stringify(outputPath)}`

  const isEsModule = typeof esModule !== 'undefined' ? esModule : true
  return `${isEsModule ? 'export default' : 'module.exports ='} ${publicPath};`
}

// !!!
module.exports.raw = true
webpack.config.js
{
  test: /\.(jpg|png)$/,
  use: [
    {
      loader: 'file-loader',
      options: {
        outputPath: 'images/',
        name: '[name]-[contentHash].[ext]',
      },
    },
  ],
},

了解更多

  • normal loader & pitching loader

  • async loader & sync loader

  • loader.raw

  • 多角度解析 ->

  • 多图详解 ->