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

如何在Remix开发环境中禁用React StrictMode?

如何在Remix开发环境(npm dev)中禁用React StrictMode?

开发环境下Remix会自动用React StrictMode包裹整个应用,这会导致组件加载两次,进而触发重复的第三方服务请求,最终出现429限流错误。如果你的/app/root.tsx里没有手动添加StrictMode,但仍遇到这个问题,可以通过以下两种方法在npm dev时禁用StrictMode:

方法一:通过remix.config.js配置(Remix v2.x 或 v1.15+)

直接在项目根目录的remix.config.js中添加dev.strictMode配置项,设置为false即可:

/** @type {import('@remix-run/dev').AppConfig} */
export default {
  // 保留原有配置(比如appDirectory、assetsBuildDirectory等)
  dev: {
    strictMode: false,
  },
};

修改后重启npm dev,StrictMode就会被禁用,组件不会再重复加载。

方法二:自定义入口文件(兼容旧版Remix)

如果你的Remix版本不支持上述配置,可以通过自定义entry.client.tsx和entry.server.tsx,结合环境变量手动控制StrictMode的启用:

1. 修改entry.client.tsx

import { RemixBrowser } from "@remix-run/react";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";

const hydrate = () => {
  startTransition(() => {
    const rootElement = document.getElementById("root");
    if (!rootElement) return;

    const app = <RemixBrowser />;
    // 根据环境变量判断是否启用StrictMode
    const wrappedApp = process.env.NODE_ENV === "development" && !process.env.DISABLE_STRICT_MODE
      ? <StrictMode>{app}</StrictMode>
      : app;

    hydrateRoot(rootElement, wrappedApp);
  });
};

if (window.requestIdleCallback) {
  window.requestIdleCallback(hydrate);
} else {
  setTimeout(hydrate, 1);
}

2. 修改entry.server.tsx

import { PassThrough } from "node:stream";
import type { AppLoadContext, EntryContext } from "@remix-run/node";
import { createReadableStreamFromReadable } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
import { isbot } from "isbot";
import { renderToPipeableStream } from "react-dom/server";
import { StrictMode } from "react";

const ABORT_DELAY = 5_000;

export default function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext,
  loadContext: AppLoadContext
) {
  return isbot(request.headers.get("user-agent") || "")
    ? handleBotRequest(request, responseStatusCode, responseHeaders, remixContext)
    : handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext);
}

function handleBotRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext
) {
  return new Promise((resolve, reject) => {
    let shellRendered = false;
    const { pipe, abort } = renderToPipeableStream(
      // 环境变量控制StrictMode
      process.env.NODE_ENV === "development" && !process.env.DISABLE_STRICT_MODE
        ? <StrictMode><RemixServer context={remixContext} url={request.url} /></StrictMode>
        : <RemixServer context={remixContext} url={request.url} />,
      {
        onAllReady() {
          shellRendered = true;
          const body = new PassThrough();
          const stream = createReadableStreamFromReadable(body);

          responseHeaders.set("Content-Type", "text/html");

          resolve(
            new Response(stream, {
              headers: responseHeaders,
              status: responseStatusCode,
            })
          );

          pipe(body);
        },
        onShellError(error: unknown) {
          reject(error);
        },
        onError(error: unknown) {
          responseStatusCode = 500;
          if (shellRendered) console.error(error);
        },
      }
    );

    setTimeout(abort, ABORT_DELAY);
  });
}

function handleBrowserRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext
) {
  return new Promise((resolve, reject) => {
    let shellRendered = false;
    const { pipe, abort } = renderToPipeableStream(
      // 环境变量控制StrictMode
      process.env.NODE_ENV === "development" && !process.env.DISABLE_STRICT_MODE
        ? <StrictMode><RemixServer context={remixContext} url={request.url} /></StrictMode>
        : <RemixServer context={remixContext} url={request.url} />,
      {
        onShellReady() {
          shellRendered = true;
          const body = new PassThrough();
          const stream = createReadableStreamFromReadable(body);

          responseHeaders.set("Content-Type", "text/html");

          resolve(
            new Response(stream, {
              headers: responseHeaders,
              status: responseStatusCode,
            })
          );

          pipe(body);
        },
        onShellError(error: unknown) {
          reject(error);
        },
        onError(error: unknown) {
          responseStatusCode = 500;
          if (shellRendered) console.error(error);
        },
      }
    );

    setTimeout(abort, ABORT_DELAY);
  });
}

3. 更新package.json的dev脚本

在scripts中添加环境变量DISABLE_STRICT_MODE=true:

"scripts": {
  "dev": "DISABLE_STRICT_MODE=true remix dev",
  // 保留其他脚本(build、start等)
}

完成以上修改后,运行npm dev就会自动禁用StrictMode,避免重复请求导致的429错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 04:37:51