Tauri 中嵌入百度网页:从 iframe 到 Webview 的迁移实践
问题背景
在开发 Tauri 桌面应用时,我们常需要在插件窗口中嵌入第三方网页。比如要在 src/plugins/baidu/index.vue 中显示百度首页,同时保留窗口控制按钮(最小化、最大化、关闭)。我们的技术栈是 Tauri 2.0 + Vue 3 + TypeScript。
起初我们尝试用 iframe 实现,但很快遇到了点击无响应的问题。经过排查,发现这是浏览器安全策略导致的根本性限制,最终通过迁移到 Tauri 的 Webview API 成功解决。
初次尝试:使用 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>
遇到的问题
用户反馈:打开百度网页之后点击没反应。
问题分析
这并非代码逻辑错误,而是浏览器的安全机制在作祟:
- X-Frame-Options 限制:百度在响应头中设置了
X-Frame-Options: SAMEORIGIN,明确禁止在 iframe 中嵌入。 - 跨域安全策略:现代浏览器出于安全考虑,阻止了 iframe 内的点击事件传递。
- 用户体验差:即使能加载,iframe 内的交互也会受到各种限制,无法获得原生体验。
iframe 方案在嵌入第三方网站(尤其是大型网站如百度)时存在根本性限制,不是技术实现的问题,而是浏览器同源策略的限制。
解决方案:使用 Tauri Webview API
研究现有实现
为了找到正确的实现方式,我研究了项目中其他使用外部链接的插件,比如动态内容插件和聊天机器人插件。在 src/components/rightBox/chatBox/Bot.vue 中找到了关键实现模式。
参考代码如下,展示了如何创建和管理外部 Webview:
const createExternalWebview = async (url: string) => {
const windowInstance = await ensureHostWindow()
if (!windowInstance || !webviewContainer.value) return
try {
const existing = await Webview.getByLabel(webviewLabel)
existing?.()
} (error) {
}
()
rect = webviewContainer..()
newWebview = (windowInstance, webviewLabel, {
url,
: rect.,
: rect.,
: rect.,
: rect.,
: ,
:
})
externalWebview. = newWebview
containerResizeObserver = ( {
()
})
containerResizeObserver.(webviewContainer.)
.(, updateExternalWebviewBounds, { : })
}

