Uncaught ReferenceError: window is not defined. While using Huggingface Transformers.js clientside inference

@Xenova @chelouche9
I am quite new to Transformers.js library on Huggingface. I am following this tutorial link

Steps to recreate: :hugs:

IN VSCode

npx create-next-app@latest

name the app <any-name-you-prefer>

Configuration options chosen while creating the app as below:

√ What is your project named? ... next
√ Would you like to use TypeScript? ... No / Yes
√ Would you like to use ESLint? ... No / Yes
√ Would you like to use Tailwind CSS? ... No / Yes
√ Would you like to use `src/` directory? ... No / Yes
√ Would you like to use App Router? (recommended) ... No / Yes
√ Would you like to customize the default import alias? ... No / Yes

Install transformersjs

npm i @xenova/transformers

Replace the contents of your next.config.mjs with this

/** @type {import('next').NextConfig} */
const nextConfig = {
    // (Optional) Export as a static site
    // See https://nextjs.org/docs/pages/building-your-application/deploying/static-exports#configuration
    output: 'export', // Feel free to modify/remove this option

    // Override the default webpack configuration
    webpack: (config) => {
        // See https://webpack.js.org/configuration/resolve/#resolvealias
        config.resolve.alias = {
            ...config.resolve.alias,
            "sharp$": false,
            "onnxruntime-node$": false,
        }
        return config;
    },
}

export default nextConfig

Create a file src/app/worker.js, with the following code:

import { pipeline, env } from "@xenova/transformers";

// Skip local model check
env.allowLocalModels = false;

// Use the Singleton pattern to enable lazy construction of the 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;
    }
}

// Listen for messages from the main thread
self.addEventListener('message', async (event) => {
    // Retrieve the classification pipeline. When called for the first time,
    // this will load the pipeline and save it for future use.
    let classifier = await PipelineSingleton.getInstance(x => {
        // We also add a progress callback to the pipeline so that we can
        // track model loading.
        self.postMessage(x);
    });

    // Actually perform the classification
    let output = await classifier(event.data.text);

    // Send the output back to the main thread
    self.postMessage({
        status: 'complete',
        output: output,
    });
});

Replace the contents of the /src/app/page.js with the following code:

'use client'

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

export default function Home() {
  // Keep track of the classification result and the model loading status.
  const [result, setResult] = useState(null);
  const [ready, setReady] = useState(null);

  // Create a reference to the worker object.
  const worker = useRef(null);

  // We use the `useEffect` hook to set up the worker as soon as the `App` component is mounted.
  useEffect(() => {
    if (!worker.current) {
      // Create the worker if it does not yet exist.
      worker.current = new Worker(new URL('./worker.js', import.meta.url), {
        type: 'module'
      });
    }

    // Create a callback function for messages from the worker thread.
    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;
      }
    };

    // Attach the callback function as an event listener.
    worker.current.addEventListener('message', onMessageReceived);

    // Define a cleanup function for when the component is unmounted.
    return () => worker.current.removeEventListener('message', onMessageReceived);
  });

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

  <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 template</h2>

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

    {ready !== null && (
      <pre className="bg-gray-100 p-2 rounded">
        {(!ready || !result) ? 'Loading...' : JSON.stringify(result, null, 2)}
      </pre>
    )}
  </main>
}

Run the app using npm run dev

Then when you refresh the localhost:3000 you’ll get the following error on the console of chrome

Full stacktrace

Uncaught ReferenceError: window is not defined
    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
Show 36 more frames
Show less
1 Like

Thanks for posting about this. I am also having this issue, and I’m stuck. I would love some help figuring this out