2021了自己写个loader吧

2022-07-14 21:17:43 浏览数 (1)

其实你爱我像谁,扮演什么角色我都会。

前情回顾

上篇文章简单介绍了一下loader,今天谈一谈自己对loader的理解。

什么是loader

loader的定义:一个导出了一个函数的node模块儿。当某些资源或文件需要转换时这个函数被调用。并且这个函数或方法有权调用webpack提供的Loader API

loader的配置

通常情况下loader的配置在webpack的module.rules对象中,例如:

代码语言:javascript复制
    module: {
      rules: [
        {
          // test: /.vue$/,
          // use: [
          //   {
          //     loader: 'iview-loader',
          //     options: {
          //       prefix: true
          //     }
          //   }
          // ]
          test:/.vue/,
          loader: 'test-loader'
        },
      ],
    },

test表示匹配到哪些文件,loader表示使用哪个loader对这些文件进行转换。这里我写了个test-loader,用来测试我本地自己写的一个demo。

测试自己的loader

自己的电脑里有之前的项目,随便起了一个基于vue的项目,在项目的根目录创建文件夹test-loader。我项目的文件夹名称为h5_pay。所以直接执行了以下命令:

代码语言:javascript复制
# h5_pay 是我自己的项目名称 这个可以根据自己的改
cd h5_pay
mkdir test-loader && npm init

然后在test-loader文件夹下的index.js中添加如下代码:

代码语言:javascript复制
module.exports = function(content) {
  console.log('content',content)
  return content && content.replace(/terrence/gi, 'Javascript高级程序设计')
}

这个函数接受一个参数content,表示匹配到的文件内容。如果内容中匹配到terrence这个单词,就替换为Javascript高级程序设计

接下来执行:

代码语言:javascript复制
npm link test-loader

npm link这个命令会将本地的测试包放入node_modules中。放入的动作其实是个软连接或者硬链接,应该是个软连接。如图:

执行完这个命令以后,重启本地服务,打开页面,就会发现代码中的terrence已经被替换为Javascript高级程序设计

而对于index.js中函数接收的参数content,打印出来就是接收到的整个vue文件的代码,如图:

content是什么

再举个例子 iview-loader

iview-loader的主要功能是将带有前缀i-的组件替换为驼峰,例如i-affix替换为Affix

iview-loader中有两个文件,tag-map.jsloader.js

tag-map.js定义了带前缀组件和驼峰组件(暂且怎么叫吧)的映射关系。

代码语言:javascript复制
// tag-map.js
exports.tag = {
    'Switch': 'i-switch',
    'Circle': 'i-circle'
};

exports.prefixTag = {
    'i-affix': 'Affix',
    'i-alert': 'Alert',
    'i-anchor': 'Anchor',
    'i-anchor-link': 'AnchorLink',
    'i-auto-complete': 'AutoComplete',
    'i-avatar': 'Avatar',
    'i-back-top': 'BackTop',
    'i-badge': 'Badge',
    'i-breadcrumb': 'Breadcrumb',
    'i-breadcrumb-item': 'BreadcrumbItem',
    'i-button': 'Button',
    'i-button-group': 'ButtonGroup',
    'i-card': 'Card',
    'i-carousel': 'Carousel',
    'i-carousel-item': 'CarouselItem',
    'i-cascader': 'Cascader',
    ...
};

loader.js定义了组件名称的替换法则,并在匹配到vue文件时进行替换。

代码语言:javascript复制
// loader.js
"use strict";

const loaderUtils = require('loader-utils');
const { tag, prefixTag } = require('./tag-map');

function replaceTag(source, tagMap) {
    Object.keys(tagMap).forEach(i => {
        source = source.replace(new RegExp(`<${i}(?!-)`, 'g'), `<${tagMap[i]}`)
            .replace(new RegExp(`</${i}>`, 'g'), `</${tagMap[i]}>`);
    })
    return source;
}

module.exports = function (source) {
    const options = loaderUtils.getOptions(this);
    this.cacheable();

    let newSource = source;
    newSource = replaceTag(newSource, tag);

    if ('prefix' in options && options.prefix) {
        newSource = replaceTag(newSource, prefixTag);
    }

    return newSource;
};

这里需要注意的是引用了一个新的包loader-utils。loader-utils是一个webpack工具类,通过一些方法配合loader处理文件。大致内容如图:

这个包在开发loader时非常重要。

总结

  • 自己如何开发一个loader
  • 简单分析下iview-loader
  • 加深对loader的理解

javascript基础知识总结

0 人点赞