You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Deno Fresh岛组件使用@egjs/preact-flicking遇document未定义错误

解决Fresh框架中使用preact-flicking时document is not defined的报错问题

我在基于Fresh搭建网站时,选用preact-flicking作为轮播组件,但渲染时出现构建失败,报错如下:

➜  example git:(main) ✗ deno task start

Task start deno run -A --watch=static/,routes/ dev.ts
Watcher Process started.
The manifest has been generated for 5 routes and 1 islands.
error: Uncaught (in promise) ReferenceError: document is not defined
    at https://esm.sh/v132/@egjs/preact-flicking@4.11.0/denonext/preact-flicking.mjs:2:56465
Watcher Process failed. Restarting on file change...

初始代码:

// islands/Carousel.tsx
import Flicking from "https://esm.sh/@egjs/preact-flicking@4.11.0";

export const Carousel = () => <Flicking />;

之前尝试过判断typeof window !== 'undefined',以及用lazy+Suspense懒加载,但前者无效,后者初始显示[object Promise],刷新后仍报同样错误。


解决方法

问题根源在于Fresh的服务端预渲染机制:preact-flicking在模块加载阶段就会访问document对象,而服务端环境不存在这个对象,导致报错。需要确保组件的导入和渲染仅在客户端执行,同时指定适配浏览器的模块版本。

方案1:在useEffect中动态导入(推荐)

// islands/Carousel.tsx
import { useEffect, useState } from "preact/hooks";

export const Carousel = () => {
  const [FlickingComp, setFlickingComp] = useState(null);

  useEffect(() => {
    // 指定browser目标,让esm.sh返回浏览器适配版本
    import("https://esm.sh/@egjs/preact-flicking@4.11.0?browser")
      .then(mod => setFlickingComp(mod.default));
  }, []);

  if (!FlickingComp) {
    return <p>加载中...</p>;
  }

  return <FlickingComp />;
};

方案2:结合lazy加载与客户端判断

// islands/Carousel.tsx
import { lazy, Suspense } from "preact/compat";
import { useEffect, useState } from "preact/hooks";

// 导入浏览器适配版本的组件
const Flicking = lazy(() => import("https://esm.sh/@egjs/preact-flicking@4.11.0?browser"));

export const Carousel = () => {
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    // 仅在客户端标记渲染状态
    setIsClient(true);
  }, []);

  if (!isClient) {
    return <p>加载中...</p>;
  }

  return (
    <Suspense fallback={<p>加载中...</p>}>
      <Flicking />
    </Suspense>
  );
};

原理说明

  1. ?browser参数告诉esm.sh返回适配浏览器环境的模块代码,避免加载针对Deno/Node的版本;
  2. useEffect确保动态导入和组件渲染逻辑仅在浏览器客户端执行,避开服务端预渲染阶段;
  3. 两种方案都通过状态判断实现客户端渲染的条件控制,解决服务端无document的问题。

内容的提问来源于stack exchange,提问作者tkovs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 23:07:23