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

使用Huggingface Transformers.js客户端推理时遇window未定义错误

问题:Transformers.js在Next.js中运行时抛出"window未定义"错误

我是Transformers.js新手,这个库基于ONNX Runtime在浏览器中运行大模型。严格按照官方Next.js教程操作后,遇到了运行错误。

复现步骤

  1. 在VSCode中执行命令:
npx create-next-app@latest

应用名称可自定义。

  1. 创建应用时的配置选项如下:
√ 你的项目名称是什么?... next
√ 是否使用TypeScript?... 否/是
√ 是否使用ESLint?... 否/是
√ 是否使用Tailwind CSS?... 否/是
√ 是否使用`src/`目录?... 否/是
√ 是否使用App Router?(推荐)... 否/是
√ 是否自定义默认导入别名?... 否/是
  1. 安装Transformers.js:
npm i @xenova/transformers
  1. 替换next.config.mjs内容为:
/** @type {import('next').NextConfig} */
const nextConfig = {
    // (可选)导出为静态站点
    output: 'export', // 可根据需要修改或移除该选项

    // 覆盖默认webpack配置
    webpack: (config) => {
        config.resolve.alias = {
            ...config.resolve.alias,
            "sharp$": false,
            "onnxruntime-node$": false,
        }
        return config;
    },
}

export default nextConfig
  1. 创建src/app/worker.js文件,代码如下:
import { pipeline, env } from "@xenova/transformers";

// 跳过本地模型检查
env.allowLocalModels = false;

// 使用单例模式延迟构建pipeline
class PipelineSingleton {
    static task = 'text-classification';
    static model = 'Xenova/distilbert-base-uncased-finetuned-sst-2-english';
    static instance = null;

    static async getInstance(progress_callback = null) {
        if (this.instance === null) {
            this.instance = pipeline(this.task, this.model, { progress_callback });
        }
        return this.instance;
    }
}

// 监听主线程消息
self.addEventListener('message', async (event) => {
    // 获取分类pipeline,首次调用时会加载模型并缓存
    let classifier = await PipelineSingleton.getInstance(x => {
        // 添加进度回调以跟踪模型加载状态
        self.postMessage(x);
    });

    // 执行文本分类
    let output = await classifier(event.data.text);

    // 将结果发送回主线程
    self.postMessage({
        status: 'complete',
        output: output,
    });
});
  1. 替换/src/app/page.js内容为:
'use client'

import { useState, useEffect, useRef, useCallback } from 'react'

export default function Home() {
  // 跟踪分类结果和模型加载状态
  const [result, setResult] = useState(null);
  const [ready, setReady] = useState(null);

  // 创建Worker对象引用
  const worker = useRef(null);

  // 组件挂载时初始化Worker
  useEffect(() => {
    if (!worker.current) {
      // 若Worker不存在则创建
      worker.current = new Worker(new URL('./worker.js', import.meta.url), {
        type: 'module'
      });
    }

    // 处理Worker线程的消息回调
    const onMessageReceived = (e) => {
      switch (e.data.status) {
        case 'initiate':
          setReady(false);
          break;
        case 'ready':
          setReady(true);
          break;
        case 'complete':
          setResult(e.data.output[0])
          break;
      }
    };

    // 添加消息监听
    worker.current.addEventListener('message', onMessageReceived);

    // 组件卸载时清理监听
    return () => worker.current.removeEventListener('message', onMessageReceived);
  });

  const classify = useCallback((text) => {
    if (worker.current) {
      worker.current.postMessage({ text });
    }
  }, []);

  return (
    <main className="flex min-h-screen flex-col items-center justify-center p-12">
      <h1 className="text-5xl font-bold mb-2 text-center">Transformers.js</h1>
      <h2 className="text-2xl mb-4 text-center">Next.js模板</h2>

      <input
        className="w-full max-w-xs p-2 border border-gray-300 rounded mb-4"
        type="text"
        placeholder="在此输入文本"
        onInput={e => {
          classify(e.target.value);
        }}
      />

      {ready !== null && (
        <pre className="bg-gray-100 p-2 rounded">
          {(!ready || !result) ? '加载中...' : JSON.stringify(result, null, 2)}
        </pre>
      )}
    </main>
  )
}
  1. 执行npm run dev启动应用,刷新localhost:3000后,Chrome控制台出现如下错误:

错误栈跟踪

未捕获的引用错误:window未定义
    at 9693 (ort-web.min.js:5035:333)
    at __nested_webpack_require_1009257__ (ort-web.min.js:15255:43)
    at 1173 (ort-web.min.js:5086:28)
    at __nested_webpack_require_1009257__ (ort-web.min.js:15255:43)
    at 9482 (ort-web.min.js:4752:49)
    at __nested_webpack_require_1009257__ (ort-web.min.js:15255:43)
    at 2100 (ort-web.min.js:4744:29)
    at __nested_webpack_require_1009257__ (ort-web.min.js:15255:43)
    at 1446 (ort-web.min.js:3450:34)
    at __nested_webpack_require_1009257__ (ort-web.min.js:15255:43)
9693 @ ort-web.min.js:5035
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
1173 @ ort-web.min.js:5086
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
9482 @ ort-web.min.js:4752
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
2100 @ ort-web.min.js:4744
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
1446 @ ort-web.min.js:3450
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
9162 @ ort-web.min.js:13374
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
8316 @ ort-web.min.js:6520
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
6416 @ ort-web.min.js:10163
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
5038 @ ort-web.min.js:5503
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
7091 @ ort-web.min.js:5466
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
6919 @ ort-web.min.js:13253
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
7714 @ ort-web.min.js:5212
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
6018 @ ort-web.min.js:5261
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
eval @ ort-web.min.js:15281
eval @ ort-web.min.js:15283
eval @ ort-web.min.js:8
eval @ ort-web.min.js:10
(app-pages-browser)/./node_modules/onnxruntime-web/dist/ort-web.min.js @ _app-pages-browser_src_app_worker_js.js:275
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ onnx.js:9
(app-pages-browser)/./node_modules/@xenova/transformers/src/backends/onnx.js @ _app-pages-browser_src_app_worker_js.js:308
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ env.js:8
(app-pages-browser)/./node_modules/@xenova/transformers/src/env.js @ _app-pages-browser_src_app_worker_js.js:330
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ hub.js:10
(app-pages-browser)/./node_modules/@xenova/transformers/src/utils/hub.js @ _app-pages-browser_src_app_worker_js.js:440
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ tokenizers.js:48
(app-pages-browser)/./node_modules/@xenova/transformers/src/tokenizers.js @ _app-pages-browser_src_app_worker_js.js:374
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ pipelines.js:29
(app-pages-browser)/./node_modules/@xenova/transformers/src/pipelines.js @ _app-pages-browser_src_app_worker_js.js:352
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ transformers.js:450
(app-pages-browser)/./node_modules/@xenova/transformers/src/transformers.js @ _app-pages-browser_src_app_worker_js.js:385
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ worker.js:2
(app-pages-browser)/./src/app/worker.js @ _app-pages-browser_src_app_worker_js.js:286
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
(anonymous) @ _app-pages-browser_src_app_worker_js.js:1655
(anonymous) @ _app-pages-browser_src_app_worker_js.js:1658
显示36更多帧
显示更少

解决方案

错误核心原因是:Next.js构建Worker时,默认会在服务端环境处理相关代码,但onnxruntime-web依赖浏览器环境的window对象,导致服务端渲染时抛出错误。可通过以下方式修复:

方案1:修改webpack配置,隔离服务端与浏览器代码

更新next.config.mjs:

/** @type {import('next').NextConfig} */
const nextConfig = {
    output: 'export',
    webpack: (config, { isServer }) => {
        // 服务端构建时排除onnxruntime-web
        if (isServer) {
            config.externals.push('onnxruntime-web');
        }

        config.resolve.alias = {
            ...config.resolve.alias,
            "sharp$": false,
            "onnxruntime-node$": false,
        };

        // 配置Worker加载规则
        config.module.rules.push({
            test: /worker\.js$/,
            use: { loader: 'worker-loader', options: { inline: 'fallback' } }
        });

        return config;
    },
}

export default nextConfig

然后安装依赖:

npm install worker-loader --save-dev

最后修改page.js中的Worker创建代码:

import Worker from './worker.js';
worker.current = new Worker();

方案2:在Worker中添加环境判断

在worker.js顶部添加判断,确保只在浏览器环境执行代码:

if (typeof window === 'undefined') {
    module.exports = {};
    return;
}

import { pipeline, env } from "@xenova/transformers";
// 剩余代码保持不变

额外建议

检查@xenova/transformers版本,升级到最新版,新版本可能已修复Next.js环境兼容问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 17:24:50