umi/max如何给请求增加公共header

news2024/11/25 16:38:58

直接上代码
在这里插入图片描述
根据 umi官网 介绍可知,umi/max仅提供一种运行时配置的方法。
如果是搭配typescript开发的话,最好使用@umi/max提供的RequestConfig类型进行字段控制。

因为是在app.ts中添加的配置,但是并不知道该配置是在何时何地如何被使用的,所以去翻阅了一下umijs/plugin-request源码

看到index.ts文件后,得到了启发:

import { IApi } from 'umi-types';
import { join, dirname } from 'path';
import assert from 'assert';
import { readFileSync } from 'fs';

export interface RequestOptions {
  dataField?: string;
}

export default function(api: IApi, options: RequestOptions) {
  api.addRuntimePluginKey('request');

  const { dataField = 'data' } = options || {};
  const source = join(__dirname, '..', 'src', 'request.ts');
  const requestTemplate = readFileSync(source, 'utf-8');
  const namespace = 'plugin-request';
  assert(/^[a-zA-Z]*$/.test(dataField), 'dataField should match /^[a-zA-Z]*$/');

  api.onGenerateFiles(() => {
    try {
      // Write .umi/plugin-request/request.ts
      let formatResultStr;
      if (dataField === '') {
        formatResultStr = 'formatResult: result => result';
      } else {
        formatResultStr = `formatResult: result => result?.${dataField}`;
      }
      api.writeTmpFile(
        `${namespace}/request.ts`,
        requestTemplate
          .replace(/\/\*FRS\*\/(.+)\/\*FRE\*\//, formatResultStr)
          .replace(/\['data'\]/g, dataField ? `['${dataField}']` : '')
          .replace(/data: T;/, dataField ? `${dataField}: T;` : '')
          .replace(
            /umi-request/g,
            api.winPath(dirname(require.resolve('umi-request/package'))),
          )
          .replace(
            /@ahooksjs\/use-request/g,
            api.winPath(dirname(require.resolve('@ahooksjs/use-request/package'))),
          ),
      );
    } catch (e) {
      api.log.error(e);
    }
  });

	// 这里,他去添加了Umi导出的配置
	// 看代码,猜测路径为: .umi/plugin-request/request.ts
	
  /**
   * umi 允许插件添加需要 umi 额外导出的内容。
   * 流程是这样的,umi 脚本执行的时候,触发 onGenerateFiles hook 生成临时文件。
   * umi 预设的插件集中有个叫做 umiExports 的插件,
   * 该插件会触发 addUmiExports hook,执行所有插件的该方法,
   * 获得插件中指定的额外导出内容,将这些内容放到临时文件中。
   */
  api.addUmiExports([
    {
      exportAll: true,
      source: api.winPath(join(api.paths.absTmpDirPath, namespace, 'request')),
    },
  ]);
}

找到了找到了,在./src/.umi/plugin-request/request.ts中找到了答案:

// .umi/plugin-request/request.ts
let config: RequestConfig;
const getConfig = (): RequestConfig => {
  if (config) return config;
  config = getPluginManager().applyPlugins({
    key: 'request',
    type: ApplyPluginsType.modify,
    initialValue: {},
  });
  return config;
};

// .umi/core/plugin.ts
import * as Plugin_0 from 'C:/workspace/psq_system/src/app.ts';
export function getPlugins() {
  return [
    {
      // Plugin_0就是{antd:{}, layout:{}, request: {}}
      apply: __defaultExport(Plugin_0),
      // 这里这里!
      path: process.env.NODE_ENV === 'production' ? void 0 : 'xxx/src/app.ts',
    },
    // ....
  ];
}

// 这里就是上面用到的keys,也就是app.ts中可以设置的内容
export function getValidKeys() {
  return ['patchRoutes','patchClientRoutes','modifyContextOpts','modifyClientRenderOpts','rootContainer','innerProvider','i18nProvider','accessProvider','dataflowProvider','outerProvider','render','onRouteChange','antd','getInitialState','layout','qiankun','request',];
}

let pluginManager = null;

export function createPluginManager() {
  pluginManager = PluginManager.create({
    plugins: getPlugins(),
    validKeys: getValidKeys(),
  });
  
  return pluginManager;
}

export function getPluginManager() {
  return pluginManager;
}

通过上面的代码,我们可以了解.umi/plugin-request/request.ts中的config是如何生成的。

  1. .umi/plugin-request/request.ts 就是umi运行时读取的配置项
  2. umi在注册plugins的时候第一个就是读取app.ts的配置,赋值给Plugin_0
  3. Plugin_0就是{ antd: {}, layout: {}, request: { }, .... }
  4. { apply: Plugin_0, path: "./src/app.ts" } 作为参数plugins的其中一个,用来创建umi的PluginManager
  5. 创建时会遍历plugins,以第一个举例,拿到他的apply,也就是Plugin_0,遍历对象,拿到key,放入pluginManager的hooks中。
  6. getPluginManager().applyPlugins({})就是对某个hooks的扩展
  7. 而.umi/plugin-request/request.ts中的config就是pluginManager.hooks.request

最后再来看一下.umi/plugin-request/request.ts中对axios的实例化,看一下config的使用

const request: IRequest = (url: string, opts: any = { method: 'GET' }) => {
  // 这里需要注意!
  const requestInstance = getRequestInstance();
  // 这里的config就是获取到的pluginManage中的hooks.request
  const config = getConfig();
  requestInstance = axios.create(config);
  // 这里就是对app.ts中request的使用
  config?.requestInterceptors?.forEach((interceptor) => {
    if(interceptor instanceof Array){
      requestInstance.interceptors.request.use((config) => {
        const { url } = config;
        if(interceptor[0].length === 2){
          const { url: newUrl, options } = interceptor[0](url, config);
          return { ...options, url: newUrl };
        }
        return interceptor[0](config);
      }, interceptor[1]);
    } else {
      requestInstance.interceptors.request.use((config) => {
        const { url } = config;
        if(interceptor.length === 2){
          const { url: newUrl, options } = interceptor(url, config);
          return { ...options, url: newUrl };
        }
        return interceptor(config);
      })
    }
  });
  // ....其他的暂时不重要
}

至此,我终于理顺了app.ts中配置项request是如何使用的了!
大功告成,理了将近5个小时,还是自己太菜了,应该直接去看plugin-request包的,结果先去看了umi中对app.ts的使用,期间又发现对@babel的parse,traverse,types包一脸懵逼,又去稍微了解了一下,花了三个小时,,
最后看plugin-request也才看了一个多小时。以后要对@babel的包也要了解一下了,前端的知识真是太多了。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/980446.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

swagger---接口文档管理生成管理工具

Swagger–接口生成工具 使用Swagger你只需要按照它的规范去定义接口及接口相关的信息,再通过Swagger衍生出来的一系列项目和工具, 就可以做到生成各种格式的接口文档,以及在线接口调试页面等等。 官网: https://lswagger.io/knife4j是为Jav…

业务逻辑漏洞复现

文章目录 一分钱买夹克任意商品购买 一分钱买夹克 登录portswigger,在all-labs中选择下面的题目: 打开后选择第一个商品: 打开后数量选择1,并用bp拦截数据包,点击添加购物车: 修改价格为1,点…

解密全产业供应关系,助力企业寻找客户资源,洞察商机

在当今商业竞争日益激烈的时代,企业要实现长期可持续的发展,需要深入了解供应链关系,抢先捕获商机,拓展优质的客户资源。然而,供应链关系错综复杂,商机、客户隐藏在其中,如何挖掘和洞察成为了企…

力扣(LeetCode)算法_C++——寻找重复的子树

给你一棵二叉树的根节点 root ,返回所有 重复的子树 。 对于同一类的重复子树,你只需要返回其中任意 一棵 的根结点即可。 如果两棵树具有 相同的结构 和 相同的结点值 ,则认为二者是 重复 的。 示例 1: 输入:root…

五大类注解和方法注解详解

五大类注解为Controller,Service,Repository,Configuration,Component,方法注解为Bean。 需要注意的是:Bean注解必须要在类注解修饰的类内才能正常使用。 一、与配置文件的关系 在spring原生项目中 如果你使用的spri…

亚马逊运营中,卖家们应该怎么挑选产品?

如今做亚马逊,选品是非常重要的。“七分靠选品,三分靠运营”,这话虽然会得罪运营小伙伴,但是目前平台就是这么个情况,一款好的产品基本上不需要花太多心思,加上一些运营技巧就能够很快表现优异。 那么选品…

深入浅出了解BeanFactory 和 ApplicationContext

一.区别 BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。 1.依赖关系 BeanFactory:是Spring里面最底层的接口,包含了各种Bean的定义,读取bean…

【系统设计系列】延迟吞吐和一致性

系统设计系列初衷 System Design Primer: 英文文档 GitHub - donnemartin/system-design-primer: Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards. 中文版: https://github.com/donnemarti…

Windows下搜索文件内容的关键字用什么命令

Windows下搜索文件内容的关键字用什么命令 findstr /s /n /i "keyword" file_path其中,/s 表示递归检索子文件夹,/n 表示显示搜索结果所在行号,/i 表示忽略大小写,“keyword” 是要搜索的关键字,file_path 是…

android程序中,产生ANR原因与分析解决

产生原因 在android程序中,所有的输入(key和touch等)事件是由底层的InputDispatcher分发到上层的InputManagerService的,再通过InputManagerService内部的InputMonitor送入WindowManagerService的Policy(PhoneWindowM…

Linux CentOS7设置时区

在Linux系统中,默认使用的是UTC时间。 即使在安装系统的时候,选择的时区是亚洲上海,Linux默认的BIOS时间(也称:硬件时间)也是UTC时间。 在重启之后,系统时间会和硬件时间同步,如果…

C# 命令行参数分割

CommandLineToArgvW 函数 [DllImport("shell32.dll", SetLastError true)] private static extern IntPtr CommandLineToArgvW([MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs); 参数: [in] lpCmdLine 类型:…

VR数字工厂,为企业工厂打造竞争新优势

工业经济中大部分行业都是制造业,为了合力助推工业经济提质增效,谋划推进制造业数字化转型就显得尤为重要了。用VR赋能工厂数字升级,打造VR数字工厂,满足各行各业沉浸式营销展示需求。 VR数字工厂是一种全新的工业模式&#xff0c…

淘宝天猫1688京东商品详情(PC端和APP端)数据代码如下

淘宝天猫1688京东商品详情(PC端和APP端)数据代码如下: 请求示例 # coding:utf-8 """ Compatible for python2.x and python3.x requirement: pip install requests """ from __future__ import print_functio…

大厂常用的B端设计系统推荐

伴随着企业级应用的迅速发展,越来越多的企业和组织开始关注设计系统,以提高其应用的设计效率和质量。B端设计系统在这一领域发挥着重要作用。本文将介绍8个著名的B端设计系统。开发者需要仔细分析自己的项目特点,了解每一个设计系统的特点和优…

登录密码加盐处理方式

哈喽!大家好,我是旷世奇才李先生 文章持续更新,可以微信搜索【小奇JAVA面试】第一时间阅读,回复【资料】更有我为大家准备的福利哟,回复【项目】获取我为大家准备的项目 文章目录 一、登录密码加盐处理方式1、简介2、密…

Linux内核的GPIO子系统驱动框架详解

目录 1 引入 2 GPIO子系统的层次 3 gpio子系统驱动程序流程 4 gpio子系统的中药数据结构 5 gpio子系统函数调用的详细细节 6 GPIO子系统的sysfs接口 6.1有哪些gpio控制器 6.2每个gpio控制器的详细信息 6.3查看gpio使用情况 6.4通过SYSFS使用GPIO 6.4.1 确定GPIO编号…

Hadoop的第二个核心组件:MapReduce框架第一节

Hadoop的第二个核心组件:MapReduce框架第一节 一、基本概念二、MapReduce的分布式计算核心思想三、MapReduce程序在运行过程中三个核心进程四、如何编写MapReduce计算程序:(编程步骤)1、编写MapTask的计算逻辑2、编写ReduceTask的…

Linux命令行

目录 CLI GUI 命令行界面 图形界面 命令行提示符 # $ ​编辑 命令一般由三个部分组成 历史命令,使用上下键,或者使用history,ctrlr搜索历史命令 通配符 *,? 切换用户 su 作业管理 &,jobs,bg,fg CLI GUI 命令行界面 …

基于SSM的健身房管理系统

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…