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

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

相关推荐
余生H17 分钟前
前端Python应用指南(二)深入Flask:理解Flask的应用结构与模块化设计
前端·后端·python·flask·全栈
outstanding木槿21 分钟前
JS中for循环里的ajax请求不数据
前端·javascript·react.js·ajax
酥饼~28 分钟前
html固定头和第一列简单例子
前端·javascript·html
一只不会编程的猫32 分钟前
高德地图自定义折线矢量图形
前端·vue.js·vue
所以经济危机就是没有新技术拉动增长了32 分钟前
二、javascript的进阶知识
开发语言·javascript·ecmascript
m0_7482509334 分钟前
html 通用错误页面
前端·html
来吧~43 分钟前
vue3使用video-player实现视频播放(可拖动视频窗口、调整大小)
前端·vue.js·音视频
Bubluu43 分钟前
浏览器点击视频裁剪当前帧,然后粘贴到页面
开发语言·javascript·音视频
鎈卟誃筅甡1 小时前
Vuex 的使用和原理详解
前端·javascript
呆呆小雅1 小时前
二、创建第一个VUE项目
前端·javascript·vue.js