告别 iframe 通信的 “飞鸽传书”:Webpage Tunnel 上手指南

1,156 阅读3分钟

作为前端开发,你一定遇到过这样的场景:

老板拍着你的肩膀说:“小王啊,把隔壁组做的那个‘用户画像’页面,直接用 iframe 嵌到我们的后台里吧,顺便把当前登录的 Token 传过去,再把用户选好的标签拿回来。”

你心想:“这简单,页面跨 iframe 可以用 postMessage 方法通信。”

然而当你开始写代码时,噩梦开始了。

😫 以前的痛苦:像在用对讲机吵架

为了在父页面和 iframe 之间传数据,你不得不使用浏览器原生的 postMessage。这玩意儿就像是一个公共广播

  1. 父页面喊话iframe.contentWindow.postMessage('嘿!这是 Token', '*')
  2. 子页面监听window.addEventListener('message', (e) => { ... })

随着业务变复杂,你的代码很快就会变成这样:

// ❌ 令人头秃的传统写法
window.addEventListener('message', (event) => {
  // 1. 先得确认是不是自己人(安全校验)
  if (event.origin !== 'https://trusted.com') return;
  
  // 2. 解析数据,还得防着格式不对报错
  const data = event.data;
  
  // 3. 开始写一堆 switch-case 来判断对方到底想干啥
  switch (data.type) {
    case 'UPDATE_TOKEN':
      // ...逻辑...
      break;
    case 'GET_USER_TAGS':
      // ...逻辑...
      // 4. 还要想办法把结果“扔”回去
      event.source.postMessage({ type: 'USER_TAGS_RESULT', payload: ... }, event.origin);
      break;
    // ...此处省略一万行...
  }
});

这就像两个人隔着一条河喊话,不仅费嗓子,还容易听错,而且谁都能插一嘴。维护起来简直是灾难。

😎 现在的救星:Webpage Tunnel

这时候,Webpage Tunnel 登场了。

它的作用很简单:把那条混乱的“河”填平,给你们拉一根专线电话。

它不再让你去处理底层的消息监听和过滤,而是让你像调用普通函数一样去跟 iframe 里的页面交流。

webpage-tunnel.png

核心理念:网页即服务 (Webpage as a Service)

想象一下,你嵌入的那个 iframe 页面,不再只是一个页面,而是一个微型服务器。它对外提供了一组 API 接口,你只需要连接它,然后调用接口拿数据。

亮点一:代码变得无比清爽

让我们看看用 Webpage Tunnel 怎么实现刚才的需求。

1. 在 iframe 页面(服务方):
只需要把你的功能“注册”一下,就像开店摆摊一样。

import { serve } from 'webpage-tunnel';

// 把页面里的功能打包成 API
serve({
  // 别人调这个方法,我就更新 Token
  updateToken: (token) => {
    localStorage.setItem('auth_token', token);
    return 'Token 更新成功!';
  },
  
  // 别人调这个方法,我就返回标签数据
  getSelectedTags: async () => {
    // 甚至可以去后台请求数据再返回
    const tags = await fetch('/api/tags').then(res => res.json());
    return tags;
  }
});

2. 在父页面(调用方):
就像打个电话一样简单,直接调用!

import { Request } from 'webpage-tunnel';

// 建立连接
const iframeApi = new Request({
  server: 'https://other-site.com/profile', // 对方的地址
  methods: ['updateToken', 'getSelectedTags'] // 我要调用的方法名
});

async function doWork() {
  // ✨ 见证奇迹的时刻
  // 不需要监听 message,不需要 switch-case,直接 await 拿结果!
  
  await iframeApi.updateToken('new-token-123');
  console.log('Token 传过去了');

  const tags = await iframeApi.getSelectedTags();
  console.log('拿到的标签是:', tags);
}

亮点二:双向奔赴

不仅仅是父页面可以调子页面,子页面也可以反过来调父页面。只要双方都 serve(提供服务)并 new Request(发起请求),就能实现无缝的双向对话。

亮点三:TypeScript 党的福音

如果你用 TypeScript,体验会更上一层楼。你可以定义好接口类型,当你输入 iframeApi. 的时候,编辑器会自动提示有哪些方法可以调,入参是什么,返回值是什么。再也不用担心拼错单词或者传错参数了。

总结

Webpage Tunnel 并没有发明什么黑科技,它只是把繁琐的 postMessage 封装进了一个黑盒子里,留给你一套优雅、现代的 API。

  • 如果你受够了 window.addEventListener
  • 如果你希望 iframe 通信代码像后端接口调用一样清晰;
  • 如果你想少掉几根头发;

那么,Webpage Tunnel 绝对值得你尝试一下。

传送门GitHub 项目地址