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日

相关推荐

  • 如何搭建MyBatis开发环境

    进入一段时间的学习及温习,已经可以说是初步掌握了Javaweb入门开发,由于我的中心思想是抛弃JSP,做纯粹的前后端分离项目,所以接下来计划学习持久层开发,现在主流的持久层开发工具…

    2022年4月6日
    877
  • px、em和rem实战经验

    在自适应布局或者移动端网页开发时,我们经常会用到em和rem两个长度单位。接下来我们讨论一下这两个单位和px之间的区别,以及他们的使用场景等。 px px,像素(计算机屏幕上的一个…

    2018年9月11日
    2.2K
  • MySQL数据库入门之单表数据记录查询

    简单数据查询 语法形式如下: 在上述语句中,参数fieldn表示所要查询的字段名字,参数table_name表示所要查询数据记录的表名。 当需要查询表中所有字段时,可使用&#822…

    2020年7月15日
    1.6K
  • 封装JDBC工具类,连接MySQL数据库

    JDBC是由java编程语言编写的类及接口组成,同时它为程序开发人员提供了一组用于实现对数据库访问的JDBC API,并支持SQL语言。利用JDBC可以将JAVA代码连接到orac…

    2022年3月31日
    974
  • spring boot练习篇之用户登录系统【接口篇】

    写在前面 抛弃JSP,只做纯粹的前后端分离项目。 作为一个资深前端工作者,想要转JavaWeb开发,无论是书籍,还是网上视频、资料,竟然没有一篇能清楚明白地讲解怎样搭建一个前后端分…

    2021年5月25日
    1.8K
  • 创建vue3 + typescript项目说明

    创建项目 选择Manually select features【手动配置】 如上图选择配置项,并在下一步,选择3.x 接下来,按照推荐设置,进行选择【推荐设置都已英文字母大写的形式…

    2023年11月23日
    763
  • 前端遍历树形数据,返回满足条件的树形数据

    在一次做手机端小程序项目中,有一个机构表单项,需要在页面展示是树形层级结构,但是后端开发人员返回的数据却是一维数组,而且还要在前端做过滤筛选功能。但是在使用的手机端组件库中,却没有…

    2022年11月8日
    563
  • Webpack入门,项目工程配置说明

    使用npm scripts 在《Webpack入门,打包第一个工程》文章讲到,webpack打包工程命令为 npx webpack –entry=./index.js –mod…

    2022年11月9日
    581
  • Webpack入门,资源处理流程

    在前几篇的文章中,梳理了Webpack的模块打包功能。可以把Webpack打包模块理解成类似于工厂中的产品组装,也就是把一个个零部件拼起来得到最终的成品。接下来的几篇,则主要要关注…

    2022年11月18日
    775
  • 前端常见跨域解决方案

    跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。 广义的跨域: 资源跳转: A链接、重定向、表单提交 资源嵌入: <link>、<scr…

    2019年3月25日
    3.3K