Webpack入门,自定义loader

有时开发者会遇到现有loader无法很好满足需求的情况,这时就需要对其进行修改,或者编写新的loader。

下面以一个简单的示例,讲解以下如何实现一个loader。

需求

实现一个loader,为所有JS文件启用严格模式。也就是说,它会在文件头部加上“use strict”。

创建一个force-strict-loader目录,然后在该目录下执行npm初始化命令。npm init -y

接着创建index.js,也就是loader的主体。

module.exports = function (content) {
  var useStrictPrefix = "'use strict';\n\n";
  return useStrictPrefix + content;
};

现在就可以在Webpack工程中安装并使用这个loader了。

npm install <path-to-loader>/force-strict-loader -D

在Webpack工程目录下使用相对路径安装,会在项目的node_modules中创建一个指向实际force-strict-loader目录的软链,也就是说之后开发者可以随时修改loader源码并且不需要重复安装了。

下面修改Webpack配置。

// webpack.config.js
module.exports = {
  ...
  module: {
    rules: [{
      test: /\.js$/,
      use: 'force-strict-loader'
    }]
  }
}

上面的配置为对所有JS文件生效。此时对该工程进行打包,应该可以看到JS文件的头部都已经加上了启用严格模式的语句。

当文件输入和其依赖没有发生变化时,应该让loader直接使用缓存,而不是重复进行转换的工作。在Webpack中可以使用this.cacheable进行控制,修改自定义的loader。

// force-strict-loader/index.js
module.exports = function(content) {
  if(this.cacheable) {
    this.cacheable();
  }
  var useStrictPrefix = "\'use strict\';\n\n";
  return useStrictPrefix + content;
}

通过启用缓存可以加快Webpack打包速度,并且可保证相同的输入产生相同的输出。

在之前的文章讲过,loader的配置项通过use.options传进来。就是说,在工程配置文件中配置了loader的options对象。

// webpack.config.js
module.exports = {
  ...
  module: {
    rules: [{
      test: /\.js$/,
      use: {
        loader: 'force-strict-loader',
        options: {
          sourceMap: true,
        }
      }
    }]
  }
}

上面的配置为force-strict-loader传入了一个配置项sourceMap。要在loader中获取,需要在force-strict-loader中安装一个依赖库loader-utils,它主要用于提供一些帮助函数。在force-strict-loader目录下执行以下命令。

npm install loader-utils -D

接着更改loader。

// force-strict-loader/index.js
var loaderUtils = require("loader-utils");
module.exports = function(content) {
  if(this.cacheable) {
    this.cacheable();
  }
  // 获取和打印options
  var options = loaderUtils.getOptions(this) || {};
  console.log("options",options);
  // 处理content
  var useStrictPrefix = "'use strict\';\n\n";
  return useStrictPrefix + content;
}

通过loaderUtils.getOptions可以获取到配置对象。

开启source-map可以便于开发者在浏览器的开发者工具中查看源码。在上面的示例中,工程配置已开启source-map,但是在force-strict-loader中没有对source-map进行处理,这样会使Webpack无法生成正确的map文件。需要修改force-strict-loader。

// force-strict-loader/index.js
var loaderUtils = require("loader-utils");
var SourceNode = require("source-map").SourceNode;
var SourceMapConsumer = require("source-map").SourceMapConsumer;
module.exports = function(content,sourceMap) {
  var useStrictPrefix = "\'use strict\';\n\n";
  if(this.cacheable) {
    this,cacheable();
  }
  // source-map
  var options = loaderUtils.getOptions(this) || {};
  if (options.sourceMap && sourceMap) {
    var currentRequest = loaderUtils.getCurrentRequest(this);
    var node = SourceNode.fromStringWithSourceMap(content,new SourceMapConsumer(sourceMap));
    node.prepend(useStrictPrefix);
    var result = node.toStringWithSourceMap({file:currentRequest});
    var callback = this.async();
    callback(null,result.code,result.map.toJSON());
  }
  // 不支持source-map情况
  return useStrictPrefix + content;
}

首先,在loader函数的参数中获取到sourceMap对象,这时由Webpack或者上一个loader传递下来的,只有当它存在时loader才能进行继续处理和向下传递。

之后通过source-map这个库来对map进行操作,包括接收和消费之前的文件内容和source-map,对内容节点进行修改,最后产生新的source-map。

在函数返回的时候要使用this.async获取callback函数(主要是为了一次性返回多个值)。callback函数的3个参数分别是抛出的错误、处理后的源码,以及source-map。

示例代码库

https://gitee.com/zero_79152105/webpack-vblog

原创文章,作者:ZERO,如若转载,请注明出处:https://www.edu24.cn/course/webpack-custom-loader.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
ZEROZERO
上一篇 2022年11月23日
下一篇 2022年11月24日

相关推荐

  • JAVA学习路线之夯实基础

    第一章 开发环境 JDK(Java SE Development Kit),Java标准版开发包,提供编译、运行Java程序所需的各种工具和资源,包括Java编译器、Java运行环…

    2020年1月14日
    1.7K
  • 曾被问及的一些关于VUE的面试题

    由于没有系统的专研过VUE,关于VUE的一些理论知识点,没有去挖心思记忆及理解,只是在实际工作中知道怎么去使用。所以曾在面试的过程中被人嫌弃过,这一直是小编的痛点,/(ㄒoㄒ)/~…

    2022年4月2日
    863
  • 从零开始开发vue组件库

    前言 很早之前,就有开发一套vue组件库的想法,直到现在想法依旧只是想法。汗颜啊……此篇文章将讲述如何开发vue组件库,虽然文章标题为《从零开始开发vue组件库》,实际上是从搭建v…

    2024年6月23日
    670
  • Vue项目中实现用户登录及token验证

    在前后端完全分离的情况下,Vue项目中实现token验证大致思路如下: 第一次登录的时候,前端调后端的登陆接口,发送用户名和密码 。 后端收到请求,验证用户名和密码,验证成功,就给…

    2019年8月8日
    5.1K
  • 函数防抖与函数节流

    函数防抖 定义 触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间;更直白一点就是:一个需要频繁触发的函数,在规定时间内,只让最后一次生效,…

    2020年7月17日
    1.5K
  • css如何利用transparent属性设置透明度?transparent属性绘制各种三角形

    想到用css设置元素透明度,大家的第一反应会是:用Opacity属性来设置透明度,其实在css中还有其他设置透明度的方法。本章给大家介绍用transparent属性设置透明度,以及…

    2021年2月25日
    1.4K
  • CSS布局之圣杯与双飞翼布局

    所谓圣杯布局和双飞翼布局其实解决的问题是相同的,都是解决左右两栏固定宽度,中间部分自适应,其中某部分内容比其他内容高的时候,保证三者元素等高。他俩的区别就是:圣杯用padding。…

    2019年6月18日
    1.9K
  • 两栏布局之左侧固定,右侧自适应的实现方法

    实现左侧固定,右侧自适应的两栏布局的方法有很多。其中经常用到的有float方法、BFC方法、CSS3的flex布局及grid布局。并非所有的布局都会在开发中使用,但是其中也会涉及一些知识点。

    2018年10月13日
    2.6K
  • MyBatis配置之typeHandler类型处理器

    typeHandler类型处理器作用 MyBatis在预处理语句(PreparedStatement)中设置一个参数时,或者从结果集(ResultSet)中取出一个值时,都会用注册…

    2022年4月20日
    1.2K
  • 深入理解JS内存机制

    JS的内存机制在很多前端开发者看来并不是那么重要,但是如果你想深入学习JS,并将它利用好,打造高质量高性能的前端应用,就必须要了解JS的内存机制。对于内存机制理解了以后,一些基本的…

    2019年7月14日
    1.8K