.client 模块
本页内容

.client 模块

摘要

您可能有一个文件或依赖项在浏览器中使用了模块副作用。您可以在文件名上使用 *.client.ts 或将文件嵌套在 .client 目录中,以强制将它们从服务器捆绑包中移除。

// this would break the server
export const supportsVibrationAPI =
  "vibrate" in window.navigator;

请注意,从此模块导出的值在服务器上都将是 undefined,因此唯一可以使用它们的地方是在 useEffect 和用户事件(如点击处理程序)中。

import { supportsVibrationAPI } from "./feature-check.client.ts";

console.log(supportsVibrationAPI);
// server: undefined
// client: true | false

如果您需要对客户端/服务器捆绑包中包含的内容进行更复杂的控制,请查看 vite-env-only 插件

用法模式

单个文件

通过在文件名中添加 .client 将单个文件标记为仅客户端

app/
├── utils.client.ts        👈 client-only file
├── feature-detection.client.ts
└── root.tsx

客户端目录

通过在目录名中使用 .client 将整个目录标记为仅客户端

app/
├── .client/               👈 entire directory is client-only
│   ├── analytics.ts
│   ├── feature-detection.ts
│   └── browser-utils.ts
├── components/
└── root.tsx

示例

浏览器功能检测

export const canUseDOM = typeof window !== "undefined";

export const hasWebGL = !!window.WebGLRenderingContext;

export const supportsVibrationAPI =
  "vibrate" in window.navigator;

仅客户端库

// This would break on the server
import { track } from "some-browser-only-analytics-lib";

export function trackEvent(eventName: string, data: any) {
  track(eventName, data);
}

使用客户端模块

import { useEffect } from "react";
import {
  canUseDOM,
  supportsLocalStorage,
  supportsVibrationAPI,
} from "../utils/browser.client.ts";
import { trackEvent } from "../analytics.client.ts";

export default function Dashboard() {
  useEffect(() => {
    // These values are undefined on the server
    if (canUseDOM && supportsVibrationAPI) {
      console.log("Device supports vibration");
    }

    // Safe localStorage usage
    const savedTheme =
      supportsLocalStorage.getItem("theme");
    if (savedTheme) {
      document.body.className = savedTheme;
    }

    trackEvent("dashboard_viewed", {
      timestamp: Date.now(),
    });
  }, []);

  return <div>Dashboard</div>;
}
文档和示例 CC 4.0
编辑