Webpack Loader学习笔记

307 阅读1分钟

简介

loader作用:将源代码转换成javascript格式的目标代码

webpack.config.js配置示例
rules: [
    {
        test: /\.css$/,
        use: [
            {
                loader: 'css-loader',
                options: {}
            },
            path.resolve(__dirname, 'myloader')
        ]
    },
],

loader介绍

loader分类:
// (1) 内联形式
import util from 'raw-loader!../utils.js'
// (2) webpack config 配置形式: test相同的数组并列形式
{
    test : /\.css$/,
    loader: 'style-loader',
    // pre, normal(默认)
    enforce: 'post'
}
执行优先级
  • 不同级:pre > normal > inline > post
  • 同级: 从右到左,从下到上
内联方式(前缀)
  • 使用 ! 前缀,将禁用所有已配置的 normal loader(普通 loader)
  • 使用 !! 前缀,将禁用所有已配置的 loader(preLoader, loader, postLoader)
  • 使用 -! 前缀,将禁用所有已配置的 preLoader 和 loader,但是不禁用 postLoaders
执行顺序

划分为pitch(需定义),execution两个阶段;

webpack-loader-flow-with-pitch.png

若任一loader在pitch阶段有返回值,则loader阻断,直接进入上一个Loade的execution阶段

webpack-loader-flow-with-pitch2.png

自定义loader

my-style-loader
const loaderUtils = require('loader-utils')

function loader(source) {
    // 测试
    let style = `
        let style = document.createElement('style')
        style.innerHTML = ${JSON.stringify(source)}
        document.head.appendChild(style)
    `
    return style
}

// remainingRequest:loader链中排在自己后面的 loader 以及资源文件的绝对路径以`!`作为连接符组成的字符串。
// precedingRequest:loader链中排在自己前面的 loader 的绝对路径以`!`作为连接符组成的字符串。
// data:每个 loader 中存放在上下文中的固定字段,可用于 pitch 给 loader 传递数据
loader.pitch = function(remainingRequest,precedingRequest,data) { // 剩余的读取绝对路径
    // 自定义条件
    let str = `
        let style = document.createElement('style')
        style.innerHTML = ${loaderUtils.stringifyRequest(this, '!!' + remainingRequest)}
        document.head.appendChild(style)
	`
    return str
}
module.exports = loader
my-url-loader
const loaderUtils = require('loader-utils')
const mime = require('mine')

function loader(source) {
    let { limit } = loaderUtils.getOptions(this)

    if (limit && limit > source.length) {
        return `module.exports="data:${mime.getType(this.resoucePath)};base64,${source.toString('base64')}"`
    } else {
        return require('./file-loader').call(this, source)
    }
}

// source为二进制输入
loader.raw = true
module.exports = loader

常用API:

// https://www.webpackjs.com/api/loaders/#%E7%A4%BA%E4%BE%8B
this.emitFile(name, content, sourceMap)  // 写file
this.cacheable(false)                    // 不缓存

// 同步: 直接执行同步fn 或 this.callback(null, fn(content), map, meta) 生成
// 异步:
let cb = this.async()
cb(null, res, map, meta)

工具库

const loaderUtils = require('loader-utils')
let option = loaderUtils.getOptions(this)
// loaderUtils.stringifyRequest() // 将绝对路径转换为相对路径

// schema校验
const validateOptions = require('schema-utils')
const schema = {
    type: 'object',
    properties: {
        text: {
            type: 'string'
        },
        filename: {
            type: 'string'
        }
    }
}
validateOptions(schema, option)

参考:

loader API
## 揭秘webpack loader : 图片引用