Webpack如何实现一个Loader?

更新日期: 2019-03-03阅读量: 1393标签: webpack
loader定义: 用于对模块的源代码进行转换。loader 可以使你在 import 或"加载"模块时预处理文件

简单使用

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            // loader 是导出为一个a函数的 node 模块。该函数在 loader 转换资源的时候调用
            // 给定的函数将调用 loader API,并通过 this 上下文访问
            loader: path.resolve('loader.js'),
            options: {/* ... */}
          }
        ]
      }
    ]
  }
};

回顾了loader的定义及简单使用后,我们再来分析一下实现loader的思路

  • 单一职责,一个loader只做一件事
  • 链式组合,链中的每个 loader 会将转换应用在已处理过的资源上
  • 模块化,是导出为一个函数的 node 模块
  • 参数合并,loader 可以通过 options 对象配置

基于上面分析的几点,我们开始动手

// 这个就是一个最简单loader,
// 如果我们的loader有依赖其它模块,也得以module的写法将在在顶部引入
import fs from 'fs';
export default function(source){
    return source
}

我们发现上面直接使用了return,是因为是同步类的loader且返回的内容唯一,如果你希望你的loader支持链式调用,将结果返给下一个loader继续使用,这时候就需要用webpack提供的api

这里我们简单看一下this.callback的定义,一个可以同步或者异步调用的可以返回多个结果的函数。预期的参数是

this.callback(
  err: Error | null,
  content: string | Buffer,
  sourceMap?: SourceMap,
  meta?: any
)
// loader-utils 它提供了很多有用的工具
// 最常用的一个就是获取传入 loader 的 options
import { getOptions } from 'loader-utils';
export default function(source, other) {
  const options = getOptions(this)    
  // do whatever you want
  // ...
  this.callback(null, source, other)
}

手写一个loader对没有研究过的听上去好像有点难,事实上, 掌握上面所介绍的内容及思想,就可以开始写一个简单的 Loader 了, 我们再来用简单的代码绥一下loader到底是什么?

// 首先loader它是一个node模块,这很好理解
export const lessTocss = function(source, other) {
    // source 就是你即将要转换的文件源
    // TODO
    // 将转换好的文件源流转至一个管道
    this.callback(null, source, other)
}
让你的loader更好用

loader api中有几个好用的家伙这里就顺便带一下

  • this.cacheable() 从提高执行效率上,如何处理利用缓存是极其重要的, webpack 中this.cacheable就可以轻松将loader缓存了
  • this.async() 当一个loader无依赖时,我们应该异步的去返回结果
案例分析

下方贴上less-loader的源码,代码很简洁,结合上方我们所分析的,也很容易理解

import processResult from './processResult';
const render = pify(less.render.bind(less));

function lessLoader(source) {
  const loaderContext = this;
  const options = getOptions(loaderContext);
  const done = loaderContext.async();
  const isSync = typeof done !== 'function';

  if (isSync) {
    throw new Error(
      'Synchronous compilation is not supported anymore. See https://github.com/webpack-contrib/less-loader/issues/84'
    );
  }
  processResult(loaderContext, render(source, options));
}


总结

  • loader是一个node模块
  • 编写loader时要遵循单一原则,每个loader只做一种"转义"工作
  • webpack为我们提供了丰富的loader api
  • webpack为我们还提供了工具函数集——loader-utils


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

链接: https://www.fly63.com/article/detial/2702

webpack—url-loader 解决项目中图片打包路径问题

刚开始用webpack的同学很容易掉进图片打包这个坑里,比如打包出来的图片地址不对或者有的图片并不能打包进我们的目标文件夹里。下面我们就来分析下在webpack项目中图片的应用场景。

webpack是什么?

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle

你必须知道的webpack插件原理分析

在 webpack 中,专注于处理 webpack 在编译过程中的某个特定的任务的功能模块,可以称为插件。它和 loader 有以下区别:loader 是一个转换器,将 A 文件进行编译成 B 文件,比如:将 A.less 转换为 A.css,单纯的文件转换过程。webpack 自身只支持 js 和 json 这两种格式的文件

webpack的异步加载原理及分包策略

webpack ensure 有人称它为异步加载,也有人称为代码切割,他其实就是将 js 模块给独立导出一个.js 文件,然后使用这个模块的时候,再创建一个 script 对象,加入到 document.head 对象中,浏览器会自动帮我们发起请求

webpack 构建多页面应用初探

如何使用webpack构建多页面应用,这是一个我一直在想和解决的问题。网上也给出了很多的例子,很多想法。猛一看,觉得有那么点儿意思,但仔细看也就那样。使用webpack这个构建工具,可以使我们少考虑很多的问题。

为什么要用webpack?

现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包。模块化,让我们可以把复杂的程序细化为小的文件;

在webpack自定义配置antd的按需加载和修改主题色

最近使用antd来做react项目的UI。从antd官网上,在使用create-react-app脚手架搭建项目时步骤如下:加模块 react-app-rewired, babel-plugin-import, react-app-rewire-less,根目录添加config-overrides.js,修改npm script即可, 一切正常

深入了解 webpack 模块加载原理

webpack 是一个模块打包器,在它看来,每一个文件都是一个模块。无论你开发使用的是 CommonJS 规范还是 ES6 模块规范,打包后的文件都统一使用 webpack 自定义的模块规范来管理、加载模块

webpack 中 import css 文件报错: Module build failed...

项目中引入了css文件,配置了 rules 中:在执行 webpack 命令时,发生错误,报错信息:Module build failed (from ./node_modules/css-loader/dist/cjs.js):CssSyntaxError,经查询,是loader顺序不正确导致此问题,修改后如下:

深入理解Webpack核心模块Tapable钩子[同步版]

tapable是webpack的核心依赖库 想要读懂webpack源码 就必须首先熟悉tapable。ok.下面是webapck中引入的tapable钩子 由此可见 在webpack中tapable的重要性

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!