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

Like (0)
Donate 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
ZEROZERO
Previous 2022年11月23日
Next 2022年11月24日

相关推荐

  • Webpack入门,样式预处理

    样式预处理指的是开发者在开发过程中经常会使用一些样式预编译语言,如SCSS、Less等,在项目打包过程中再将这些预编译语言转换成CSS。借助这些语言强大和便捷的特性,可以降低项目的…

    2022年11月25日
    555
  • JAVA基础知识整理

    终于下定决心2020年转JAVA开发,自学之路坎坷曲折。俗话说的话,好记性不如烂笔头。如果有小伙伴们也像我一样在JAVA自学之路上徘徊,那就关注一下我的博客网站。我会不定期更新一下…

    2020年1月11日
    1.6K
  • Spring Tools学习之JAVA开发环境搭建【windows 10】

    一直以来都想学习JAVA,但是苦于找不到门路,网上学习资料要不看不懂,要不需要金钱。 终于,迫于生活与年龄的压力,下定决心,学习JAVA。 写下此文档,记录一下自己学习JAVA之路…

    2018年12月6日
    2.7K
  • Angular4.x ngModel 指令详解

    用过angular的前端工程师都知道,angular数据是可以双向绑定的。但是它为什么可以使数据双向绑定?原理又是什么?阅读这篇文章,来了解一下吧。

    2019年7月3日
    1.8K
  • 创建vue3 + typescript项目说明

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

    2023年11月23日
    461
  • spring boot练习篇之用户登录系统【接入数据库】

    抛弃JSP,只做纯粹的前后端分离项目。 写在前面 学习基础知识是枯燥无味的,之所以会这样,多数是因为心不静,对于如何运用它,感到茫然。所以建议大家在学习Java基础知识的时候,一定…

    2021年5月28日
    1.1K
  • spring4.x学习之创建工程

    断断续续学习Java有两三个月了,目前还是处于入门阶段。关于java及spring那些的设计理念方面的理论知识,不花费大量精力及时间是看不懂的(至少对于我这么一个前端转后端的初学者…

    2019年3月19日
    1.7K
  • Webpack入门,模块打包之ES6 Module

    JavaScript之父Brendan Eich在最初设计这门语言时,并没有包含模块的概念。基于越来越多的工程需要,为了使用模块化进行开发,JavaScript社区涌现出了多种模块…

    2022年11月11日
    439
  • STS插件mybatis-generator安装及使用

    断断续续学习Java也有好长时间了,没有师傅带,没有项目练手,学习超级慢,也很烦。视频、书籍翻看了一大推,还是没有目标。 相信滴水成海,外加条条大路通罗马,只要坚持,自己终能达成目…

    2019年12月27日
    2.1K
  • 如何搭建MyBatis开发环境

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

    2022年4月6日
    653