编写 Loader 和插件

Loader Interface
loader-utils
loader-runner

一个最简单的 loader 代码结构

定义: loader 只是一个导出为函数的 JavaScript 模块

module.exports = function (source) {
    return source;
};

使用loader-runner进行loader的调试

定义:允许你在不安装webpack的情况下运行loaders
作用:作为webpack的依赖,在webpack中执行loader
进行loader的开发和调试

import {runLoaders} from 'loader-runner';
runLoaders({
    resource: "/abs/path/to/file.txt?query",
    loaders: [],
    context: {},
    readResource: fs.readFile.bind(fs)
}, function(err, result) {
    // err
    // result
});
属性名 说明
resource 资源的绝对路径(可以增加查询字符串)
loaders loader 的绝对路径(可以增加查询字符串)
context 基础上下文之外的额外 loader 上下文
readResource 读取资源的函数

loader的参数获取

通过loader-utils的getOptions方法获取

const loaderUtils = require("loader-utils");
module.exports = function(content) {
     const { name } = loaderUtils.getOptions(this);
};

loader的异常处理

1、loader 内直接通过 throw 抛出
2、通过\color{red}{this.callback}传递错误

this.callback(
    err: Error | null,
    content: string | Buffer, 
    sourceMap?: SourceMap,
    meta?:any
);

loader的异步处理

通过\color{red}{this.async} 来返回一个异步函数

module.exports = function(input) { 
    const callback = this.async();
    // No callback -> return synchronous results // if (callback) { ... }
    callback(null, input + input); //第一个参数是 Error,第二个参数是处理的结果
};

在 loader 中使用缓存

webpack 中默认开启 loader 缓存
(可以使用 this.cacheable(false) 关掉缓存)
缓存条件: loader 的结果在相同的输入下有确定的输出
(有依赖的 loader 无法使用缓存)

loader 如何进行文件输出

通过\color{red}{this.emitFile}进行文件写入

const loaderUtils = require("loader-utils");
module.exports = function (content) {
    const url = loaderUtils.interpolateName(this, "[hash].[ext]", {
        content,
    });
    this.emitFile(url, content);
    const path = `__webpack_public_path__ + ${JSON.stringify(url)};`;
    return `export default ${path}`;
};

插件的运行环境

只能在 webpack 里面运行

插件的基本结构

基本结构

/* 插件名称 */
class MyPlugin {
    /* apply方法 */
    apply(compiler) {
        /* 插件的hooks */
        compiler.hooks.done.tap(' My Plugin', (
            stats/* stats is passed as argument when done hook is tapped. */
        ) => {
            /* 逻辑 */
            console.log('Hello World!');
        });
    }
}
module.exports = MyPlugin;

插件使用:

plugins: [ new MyPlugin() ]

搭建插件的运行环境

const path = require("path");
const DemoPlugin = require("./plugins/demo-plugin.js");
const PATHS = {
    lib: path.join(__dirname, "app", "shake.js"),
    build: path.join(__dirname, "build")
};
module.exports = {
    entry: {
        lib: PATHS.lib,
    },
    output: {
        path: PATHS.build,
        filename: "[name].js",
    },
    plugins: [new DemoPlugin()]
};

插件中如何获取传递的参数

通过插件的构造函数进行获取

constructor(options) {
    this.options = options;
}
new ZipPlugin({
    filename: 'offline'
})

插件的错误处理

参数校验阶段可以直接 throw 的方式抛出

throw new Error(“ Error Message”);

通过 compilation 对象的 warnings 和 errors 接收

compilation.warnings.push("warning"); 
compilation.errors.push("error");

通过 Compilation 进行文件写入

Compilation 上的 assets 可以用于文件写入
文件写入需要使用 webpack-sources (https://www.npmjs.com/package/webpack-sources)

const {
    RawSource
} = require("webpack-sources");
module.exports = class DemoPlugin {
    constructor(options) {
        this.options = options;
    }
    apply(compiler) {
        const {
            name
        } = this.options;
        compiler.plugin("emit", (compilation, cb) => {
            compilation.assets[name] = new RawSource("demo");
            cb();
        })
    }
};
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容