Tauri 中嵌入百度网页:从 iframe 到 Webview 的迁移实践
问题描述
在开发 Tauri 桌面应用时,我们需要在一个插件窗口中嵌入百度首页。最初使用 iframe 实现,但遇到了点击无响应的问题。最终通过迁移到 Tauri 的 Webview API 成功解决。
问题背景
我们的应用使用 Tauri 2.0 + Vue 3 + TypeScript 技术栈。需求是在 src/plugins/baidu/index.vue 中实现一个显示百度首页的插件窗口,同时保留窗口控制按钮(最小化、最大化、关闭)。
初次尝试:使用 iframe
实现代码
<template>
<main data-tauri-drag-region>
<ActionBar :shrink="false" :max-w="true" :icon-color="'black'" :top-win-label="WebviewWindow.getCurrent().label" :current-label="WebviewWindow.getCurrent().label"/>
<iframe src="https://www.baidu.com" frameborder="0"></iframe>
</main>
</template>
<script setup lang="ts">
import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
</script>
遇到的问题
实现后,用户反馈:打开百度网页之后点击没反应。
问题分析
通过分析发现,问题出在 iframe 的跨域限制上:
- X-Frame-Options 限制:百度在响应头中设置了
X-Frame-Options: SAMEORIGIN,禁止在 iframe 中嵌入 - 跨域安全策略:现代浏览器出于安全考虑,阻止了 iframe 内的点击事件
- 用户体验差:即使能加载,iframe 内的交互也会受到各种限制
iframe 方案在嵌入第三方网站(尤其是大型网站如百度)时存在根本性限制,不是技术实现的问题,而是浏览器安全策略的限制。
解决方案:使用 Tauri Webview API
研究现有实现
为了找到正确的实现方式,我研究了项目中其他使用外部链接的插件:
- dynamic/index.vue:动态内容插件
- robot/index.vue:聊天机器人插件
- Bot.vue:聊天框组件,包含 Webview 实现
在 src/components/rightBox/chatBox/Bot.vue 中找到了关键实现:
const createExternalWebview = async (url: string) => {
const windowInstance = await ensureHostWindow()
if (!windowInstance || !webviewContainer.value) return
try {
existing = .(webviewLabel)
existing?.()
} (error) {
}
()
rect = webviewContainer..()
newWebview = (windowInstance, webviewLabel, {
url,
: rect.,
: rect.,
: rect.,
: rect.,
: ,
:
})
externalWebview. = newWebview
containerResizeObserver = ( {
()
})
containerResizeObserver.(webviewContainer.)
.(, updateExternalWebviewBounds, { : })
}

