Vue-Cli/Rsbuild动态代理IP地址无需重新启动/依靠热更新

前言

在还没将vue-cli迁移到rsbuild之前呢,根据proxy.router实现了无需重启项目就能修改服务器IP的方法。现在迁移后,在rsbuild.config.mjs修改IP地址时,热更新还是有点慢,所以想把之前的实现重新应用

Vue-Cli(require)

先把Vue-Cli情况下的实现记录一下

  • 在根目录下新建service-config.js文件
js 复制代码
module.exports = {
  serverOrigin: 'https://192.168.70.28'
};
  • vue.config.js
    • require请求文件信息时,node会解析出我们传入的字符串的文件路径的绝对路径,并且以绝对路径为键值,对该文件进行缓存
js 复制代码
const hotServer = () => {
  const path = './server-config.js';
  // require.resolve可以通过相对路径获取绝对路径
  // 以绝对路径为键值删除require中的对应文件的缓存
  delete require.cache[require.resolve(path)];
  // 重新获取文件内容
  const { serverOrigin } = require(path);

  return serverOrigin || '';
};

// devServer下的proxy
proxy: {
  '/audit-apiv2': {
    secure: false,
    // target: 'that must have a empty placeholder',
    target: 'http://127.0.0.1:10086',
    router: () => hotServer(),
    onProxyReq(proxyReq) {
      // 绕过后端的csrf验证
      proxyReq.setHeader('referer', hotServer());
    }
  },
}
  • vue-cli 的代理是使用的http-proxy-middleware包,所以proxy选项的配置也是基于这个包的配置。在proxy配置选项中有两个属性target以及router。其中target是默认的代理地址。而router可以return一个字符串服务地址,那么当两个选项都配置了时,http-proxy-middleware在解析配置时,会首先使用router函数的返回值,当router的返回值不可以用时,那么就会fallbacktarget
  • 项目在每次发起http请求时都会调用router中的函数,对我们的环境地址文件进行实时读取,从而指向我们最新修改的环境地址。

Rsbuild(jiti)

查了rsbuild的proxy实现方式后,发现和webpackproxy的实现是差不多的,都是使用了http-proxy-middleware包,描述也和webpack一致,所以我直接原封不动的迁移过来了

  • 在迁移完代码后,我对其进行验证发现,并没有生效,修改service.config.jsserverOrigin的值并不生效
  • hotServer函数中打印
js 复制代码
const hotServer = () => {
  const path = './server-config.js';
  // require请求文件信息时,node会解析出我们传入的字符串的文件路径的绝对路径,并且以绝对路径为键值,对该文件进行缓存
  // require.resolve可以通过相对路径获取绝对路径
  // 以绝对路径为键值删除require中的对应文件的缓存
  console.log('require', require);
  console.log('require.cache', require.cache);
  delete require.cache[require.resolve(path)];
  // 重新获取文件内容
  const { serverOrigin } = require(path);
  console.log(serverOrigin, 'serverOrigin');

  return serverOrigin || '';
};
  • 打印内容如下:
js 复制代码
[Function: jiti] {
  resolve: [Function: _resolve] { paths: [Function: paths] },
  cache: {},
  extensions: {
    '.js': [Function (anonymous)],
    '.json': [Function (anonymous)],
    '.node': [Function (anonymous)]
  },
  main: undefined,
  transform: [Function: transform],
  register: [Function (anonymous)],
  evalModule: [Function: evalModule],
  import: [Function (anonymous)]
}
  • resolve :用于动态解析模块路径(类似 Node.js 的 require.resolve)。

  • cache :JITI 的模块缓存,类似于 Node.js 的 require.cache,但独立于 Node.js 的缓存机制。

  • extensions :定义可被加载的文件类型及其对应的处理器(.js, .json, .node 等)。

  • transform:即时编译模块(例如 TS 转译为 JS)。

  • register :注册自定义模块加载逻辑(例如扩展 .ts 支持)。

  • evalModule:直接对模块代码进行动态求值。

  • 发现,这打印的是一个jiti,而且cache是个空对象。难怪不生效,service-config.js并不在缓存中。

什么是jiti

ITI 是一个轻量级动态模块加载工具,支持 CommonJS 和 ES 模块的动态加载,且在运行时进行编译和解析。以下是 JITI 的主要特性:

  1. 替代 Node.js 的 require JITI 提供类似 require 的 API,但它在内部可能对模块进行即时编译(尤其是 TS 或 ES Module),所以你看到它不是原生的 require

  2. 缓存管理

    • JITI 提供自己的缓存机制(如 jiti.cache),和 Node.js 的 require.cache 不同。
    • 你可以通过 jiti.cache 来管理模块缓存。
  3. 扩展支持

    • JITI 支持多种扩展(.js, .json, .ts 等),可以动态解析不同格式的模块。
  4. 增强功能

    • 支持动态 import
    • 提供更灵活的模块解析机制(如内联编译 TypeScript)。

在我的 Rspack 配置中,require 并不是传统 Node.js 的 require 函数,而是被替换为了 JITI("Just-In-Time-Interpreter")。

如果使用 JITI,模块的缓存不会存储在 require.cache 中,而是在 jiti.cache 中。因此,你无法通过传统的 delete require.cache[require.resolve(...)] 来清除缓存,而需要清理 jiti.cache

那么,我们需要安装jiti

sh 复制代码
npm install jiti

删除cache缓存

  • rsbuild.config.mjs文件中
mjs 复制代码
const jiti = require('jiti')(__dirname);

const hotServer = () => {
  const path = './server-config.js';
  // require.resolve可以通过相对路径获取绝对路径
  // 以绝对路径为键值删除require中的对应文件的缓存
  delete jiti.cache[require.resolve(path)];
  // 重新获取文件内容
  const { serverOrigin } = require(path);

  return serverOrigin || '';
};
  • 其余的代码照旧使用hotServer,如此一来,只需要修改service-config.js文件中的IP地址即可,这样省略了热更新的时间,也能提升一点效率。

通用方法(fs文件读取)

使用文件读取的方式,这样就不需要再安装jiti

  • rsbuild.config.mjs
js 复制代码
import fs from 'fs';

const hotServer = () => {
  const path = './server-config.json';
  const content = fs.readFileSync(path).toString();
  const { serverOrigin } = JSON.parse(content);
  return serverOrigin || '';
};
  • service-config.json
json 复制代码
{
  "serverOrigin": "https://192.168.70.203"
}

总结

以上三种方式都能实现,在修改IP地址后,无需重新启动项目或等待热更新,直接刷新浏览器页面即可。

当然,service-config.json中的serverOrigin也可以抽取到.env文件,本质都是读取文件。

相关推荐
codingandsleeping7 分钟前
前端工程化之webpack(万字)
前端·javascript
Jiude36 分钟前
UnoCSS presetWind4() 背景色使用 color-mix() 的原因及解决方案
前端·css
无名之逆1 小时前
Hyperlane:Rust 生态中的轻量级高性能 HTTP 服务器库,助力现代 Web 开发
服务器·开发语言·前端·后端·http·面试·rust
范哥来了1 小时前
python web开发django库安装与使用
前端·python·django
烛阴1 小时前
JavaScript 的 “new Function”:你不知道的黑魔法,让代码更灵活!
前端·javascript
ConardLi2 小时前
发布第五天,我的开源项目突破 1.7 K Star!
前端·javascript·人工智能
程序员小刚2 小时前
基于SpringBoot + Vue 的心理健康系统
vue.js·spring boot·后端
尚学教辅学习资料2 小时前
基于SpringBoot+Vue的幼儿园管理系统+LW示例参考
vue.js·spring boot·后端·幼儿园管理系统
Moment2 小时前
京东一面:postMessage 如何区分不同类型的消息 🤪🤪🤪
前端·javascript·面试
鱼樱前端2 小时前
🔥 Vue2 vs Vue3 的 h 函数终极指南:从入门到源码级深度解析
前端·vue.js