Tauri + Next.js 首次加载报window未定义,无法创建新窗口
解决Tauri + Next.js 创建新窗口时首次加载失败的问题
问题根源
Next.js 默认启用服务端渲染(SSR),在服务端编译阶段不存在 window 对象,但 Tauri 的 WebviewWindow API 依赖浏览器环境的 window 对象,因此首次编译时会抛出 ReferenceError: window is not defined 错误。而注释后取消注释能正常运行,是因为此时处于客户端热更新阶段,代码已在浏览器环境中执行,window 对象存在。
解决思路
1. 动态导入 Tauri Window API
将 WebviewWindow 的导入放在函数内部,仅在客户端执行时才加载该模块,避免服务端编译时触发错误:
const openWindow = async (e) => { const table = JSON.stringify({ host: active.host, port: active.port, user: active.user, password: active.password, database: e, }); try { // 动态导入WebviewWindow,仅在客户端环境加载 const { WebviewWindow } = await import('@tauri-apps/api/window'); await new WebviewWindow("test", { url: "/database?data=" + table, }); } catch (e) { console.log("error", e); } };
2. 显式判断客户端环境
在执行 Tauri 相关代码前,先检查是否处于浏览器环境,确保服务端直接跳过这段逻辑:
const openWindow = async (e) => { // 服务端环境直接返回,避免执行依赖window的代码 if (typeof window === 'undefined') return; const table = JSON.stringify({ host: active.host, port: active.port, user: active.user, password: active.password, database: e, }); try { const { WebviewWindow } = await import('@tauri-apps/api/window'); await new WebviewWindow("test", { url: "/database?data=" + table, }); } catch (e) { console.log("error", e); } };
3. 针对 Next.js 13+ App Router:标记组件为客户端组件
如果使用 Next.js 13+ 的 App Router,需要在包含 openWindow 函数的组件顶部添加 'use client' 指令,强制该组件在客户端渲染:
'use client'; // 必须放在组件最顶部 import { useState } from 'react'; // 其他导入... const YourComponent = () => { // 组件逻辑和openWindow函数... }; export default YourComponent;
4. 针对 Pages Router:使用动态导入禁用 SSR
如果使用 Pages Router,可以将包含按钮和 openWindow 逻辑的部分抽成单独组件,然后用 dynamic 导入并禁用 SSR:
// 父组件中 import dynamic from 'next/dynamic'; // 禁用SSR,组件仅在客户端渲染 const DatabaseTable = dynamic(() => import('./DatabaseTable'), { ssr: false }); const ParentComponent = () => { return ( <div> {loading === false ? <DatabaseTable databases={databases} /> : null} </div> ); };
然后在 DatabaseTable 组件中实现按钮和 openWindow 逻辑即可。
内容的提问来源于stack exchange,提问作者GusiiSenpaii
相关产品推荐
相关产品推荐

