前端开发环境与真实环境的接口联通的那些最佳实践

1. 背景

前端开发的产物通常是 app.jsapp.css ,然后将这些资源放在真实环境域名下进行工作的。 但前端的开发环境通常是本地的 http://localhost:xxx,业务域名可能是 https://xxx.abc.com,两者不在一个域名下在调用接口或者调试时会非常不方便。

加上现在的构建或脚手架工具,如 Vite、Webpack5、Umi 等在开发环境下采用 ES Module 构建,线上采用单文件构建,导致传统的,访问业务域名,然后将资源代理到本地的方式出现问题,所以更合适的方式应该是如何在前端的本地环境下,可以流畅的访问业务域名下的接口。

期待:

2. 实现思路

实现这种方法主要解决:CORS 问题,及 Same-site Cookies 的问题(非登陆态场景不需要解决 Cookie 问题,但很少见此类场景)。 这两个问题,通常业务侧是不能给解决的,所以需要前端自行处理这两个问题。

3. 实现方法

下面罗列下实现期望中,在本地开发环境,顺畅调用业务接口的方法。

3.1 系统级代理实现

针对 CORS 及 Same-site 处理,浏览器级代理是完全无法处理的,当然从调用方向来看也是不合适的,所以需要系统级代理进行拦截重写。

这里推荐 Whistle 或者 Charless 实现。

如 Whistle 可以使用:

perl 复制代码
pattern resCors://* reqCookies://filepath

缺点:

  • 系统级代理,全局受影响,影响网络速度及系统性能。
  • session 的 cookie 需要定期更新,非常繁琐。
  • 部分代理工具无法转发拦截本地请求。

3.2 前端工程侧代理

这个属于比较成熟的方案了,内部通过配置 proxy 可以实现应用及的代理转发。

3.2.1 Webpack OR Umi

Webpack 和 Umi 采用相似的代理方案,底层使用 http-proxy-middleware 实现,可以很方便修改请求和响应,实现 CORS 及 Same-site 的处理。

可以在 webpack.config.js 或者 Umi 的 config.js 中配置:

js 复制代码
export default {
  {
    '/api/': {
      target: "https://xxx.abc.com",
      changeOrigin: true,
      secure:false,
      onProxyReq: (proxyReq) => {
        proxyReq.setHeader(
          'Cookie',
          'sessionId=wzqa6tjqgl;sessionId2=wzqa6tjqgl',
        )
      },
    },
  }
}

3.2.2 Vite

Vite 底层通过 node-http-proxy 实现代理功能。

可以在 vite.config.js 进行配置:

js 复制代码
export default {
  server: {
    proxy: {
      "/api": {
        target: "https://xxx.abc.com",
        changeOrigin: true,
      },
    },
  },
  plugins: [
    {
      name: "append-backend-cookies",
      configureServer(server) {
        server.middlewares.use((req, res, next) => {
          req.headers["Cookie"] = "sessionId=wzqa6tjqgl;sessionId2=wzqa6tjqgl";
          next();
        });
      },
    },
  ],
};

优点:

  • 相比系统级,不会对全局系统代理产生影响,系统性能影响小。
  • 不用额外的其他工具软件支持,简单方便。

缺点:

  • session 的 cookie 需要定期更新,非常繁琐。

3.3 完美方案 Electron 修改 Webview

CORS 的问题本质是浏览器的限制,Same-site 导致的登陆 Cookies 无法携带也是浏览器的限制,那直接把浏览器的限制给去掉不就可以迎刃而解了。这样不需要 api 的域名转发了,也不需要代理了,直接在 localhost 下调用 xxx.abc.com 就可以了。且在 Electron 中也可以正常安装浏览器插件,像 React-Devtools 完全正常使用。

早期 Electron 版本只需要 webSecurity: false 就可以解决我们的问题,但在 Chrome 94 版本不再放行,无法再携带 Cookies,也就是 Electron v14 之后的版本无法通过 webSecurity: false 来禁用这些问题。

新版本(v27),通过复写 onHeadersReceived 实现:

js 复制代码
function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      webSecurity: false,
    },
  });

  win.loadURL("https://localhost:3000");
  // win.webContents.openDevTools();
}

function disableSamesiteCookies(filter = ["*://*/*"]) {
  session.defaultSession.webRequest.onHeadersReceived(
    { urls: filter },
    (details, callback) => {
      const newCookies = [];

      details?.responseHeaders?.["set-cookie"]?.map((item) =>
        newCookies.push(item.split("; ")[0] + "; Secure; SameSite=None")
      );
      details.responseHeaders["set-cookie"] = newCookies;

      callback({ cancel: false, responseHeaders: details.responseHeaders });
    }
  );
}

app.whenReady().then(() => {
  createWindow();
  disableSamesiteCookies();

  //  ......
});

优点:

  • 几乎全是优点。

缺点:

  • 需要额外开启 electron 项目。

4. 链接

原文地址: Github

相关推荐
涔溪33 分钟前
Ecmascript(ES)标准
前端·elasticsearch·ecmascript
用户31574760813535 分钟前
成为程序员的必经之路” Git “,你学会了吗?
面试·github·全栈
榴莲千丞43 分钟前
第8章利用CSS制作导航菜单
前端·css
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与1 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts
guokanglun1 小时前
CSS样式实现3D效果
前端·css·3d
咔咔库奇1 小时前
ES6进阶知识一
前端·ecmascript·es6
前端郭德纲1 小时前
浏览器是加载ES6模块的?
javascript·算法
JerryXZR1 小时前
JavaScript核心编程 - 原型链 作用域 与 执行上下文
开发语言·javascript·原型模式
帅帅哥的兜兜1 小时前
CSS:导航栏三角箭头
javascript·css3