Skip to content

Hydrogen 2025.7.0, entry.server.tsx doesn't work, (ReferenceError: require is not defined) #18089

@necheporenko

Description

@necheporenko

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/cloudflare

SDK Version

^10.22.0

Framework Version

React 18.3.1

Link to Sentry event

No response

Reproduction Example/SDK Setup

Here is my code:

package.json:

{
  "name": "project-name",
  "private": true,
  "sideEffects": false,
  "version": "2025.7.0",
  "type": "module",
  "scripts": {
    "build": "shopify hydrogen build --codegen",
    "dev": "shopify hydrogen dev --codegen",
    "preview": "shopify hydrogen preview --build",
    "lint": "eslint --no-error-on-unmatched-pattern .",
    "typecheck": "react-router typegen && tsc --noEmit",
    "codegen": "shopify hydrogen codegen && react-router typegen"
  },
  "prettier": "@shopify/prettier-config",
  "dependencies": {
    "@algolia/requester-fetch": "^4.25.2",
    "@headlessui/react": "^2.2.9",
    "@okendo/shopify-hydrogen": "^2.5.3",
    "@portabletext/react": "^3.2.1",
    "@sanity/image-url": "^1.2.0",
    "@sanity/webhook": "^4.0.4",
    "@sentry/cloudflare": "^10.22.0",
    "@sentry/react-router": "^10.22.0",
    "@shopify/hydrogen": "2025.7.0",
    "@tailwindcss/forms": "^0.5.10",
    "@tailwindcss/typography": "^0.5.19",
    "@tailwindcss/vite": "^4.1.15",
    "@typeform/embed-react": "^4.6.0",
    "algoliasearch": "^4.25.2",
    "clsx": "^2.1.1",
    "disqus-react": "^1.1.7",
    "get-youtube-id": "^1.0.1",
    "graphql": "^16.10.0",
    "graphql-tag": "^2.12.6",
    "hydrogen-sanity": "^5.1.0",
    "isbot": "^5.1.22",
    "lodash.debounce": "^4.0.8",
    "lucide-react": "^0.539.0",
    "react": "18.3.1",
    "react-currency-input-field": "^3.10.0",
    "react-dom": "18.3.1",
    "react-instantsearch": "^7.16.3",
    "react-portable-text": "^0.6.0",
    "react-router": "7.9.2",
    "react-router-dom": "7.9.2",
    "react-slider": "^2.0.6",
    "react-use": "^17.6.0",
    "swiper": "^11.2.10",
    "tailwind-merge": "^3.3.1",
    "tailwindcss": "^4.1.15",
    "yet-another-react-lightbox": "^3.25.0"
  },
  "devDependencies": {
    "@eslint/compat": "^1.2.5",
    "@eslint/eslintrc": "^3.2.0",
    "@eslint/js": "^9.18.0",
    "@graphql-codegen/cli": "5.0.2",
    "@react-router/dev": "7.9.2",
    "@react-router/fs-routes": "7.9.2",
    "@shopify/cli": "3.85.4",
    "@shopify/hydrogen-codegen": "^0.3.3",
    "@shopify/mini-oxygen": "^4.0.0",
    "@shopify/oxygen-workers-types": "^4.1.6",
    "@shopify/prettier-config": "^1.1.2",
    "@total-typescript/ts-reset": "^0.6.1",
    "@types/eslint": "^9.6.1",
    "@types/lodash.debounce": "^4.0.9",
    "@types/react": "^18.2.22",
    "@types/react-dom": "^18.2.7",
    "@types/react-slider": "^1.3.6",
    "@typescript-eslint/eslint-plugin": "^8.21.0",
    "@typescript-eslint/parser": "^8.21.0",
    "eslint": "^9.18.0",
    "eslint-config-prettier": "^10.0.1",
    "eslint-import-resolver-typescript": "^3.7.0",
    "eslint-plugin-eslint-comments": "^3.2.0",
    "eslint-plugin-import": "^2.31.0",
    "eslint-plugin-jest": "^28.11.0",
    "eslint-plugin-jsx-a11y": "^6.10.2",
    "eslint-plugin-react": "^7.37.4",
    "eslint-plugin-react-hooks": "^5.1.0",
    "eslint-plugin-simple-import-sort": "^12.1.1",
    "globals": "^15.14.0",
    "prettier": "^3.4.2",
    "typescript": "^5.9.2",
    "vite": "^6.2.4",
    "vite-tsconfig-paths": "^4.3.1"
  },
  "engines": {
    "node": ">=18.0.0"
  },
  "browserslist": [
    "defaults"
  ]
}

instrument.server.mjs:

import * as Sentry from '@sentry/react-router';

Sentry.init({
  dsn: 'MY DSN LINK',
  // Adds request headers and IP for users, for more info visit:
  // https://docs.sentry.io/platforms/javascript/guides/react-router/configuration/options/#sendDefaultPii
  sendDefaultPii: true,
  tracesSampleRate: 1.0,
});

app/entry.client.tsx:

import {startTransition, StrictMode} from 'react';
import {hydrateRoot} from 'react-dom/client';
import {HydratedRouter} from 'react-router/dom';
import {NonceProvider} from '@shopify/hydrogen';

import * as Sentry from '@sentry/react-router/cloudflare';

Sentry.init({
  dsn: 'MY DSN LINK',
  integrations: [Sentry.reactRouterTracingIntegration()],
  tracesSampleRate: 1.0,
});

if (!window.location.origin.includes('webcache.googleusercontent.com')) {
  startTransition(() => {
    // Extract nonce from existing script tags
    const existingNonce =
      document.querySelector<HTMLScriptElement>('script[nonce]')?.nonce;

    hydrateRoot(
      document,
      <StrictMode>
        <NonceProvider value={existingNonce}>
          <HydratedRouter />
        </NonceProvider>
      </StrictMode>,
    );
  });
}

server.ts:

// Virtual entry point for the app
import {storefrontRedirect} from '@shopify/hydrogen';
import {createRequestHandler} from '@shopify/hydrogen/oxygen';

import {wrapRequestHandler} from '@sentry/cloudflare/request';

import {createHydrogenRouterContext} from '~/lib/context';

/**
 * Export a fetch handler in module format.
 */
export default {
  async fetch(
    request: Request,
    env: Env,
    executionContext: ExecutionContext,
  ): Promise<Response> {
    try {
      return wrapRequestHandler(
        {
          options: {
            dsn: 'MY DSN LINK',
            tracesSampleRate: 1.0,
          },
          request: request as any,
          context: executionContext,
        },
        async () => {
          const hydrogenContext = await createHydrogenRouterContext(
            request,
            env,
            executionContext,
          );

          /**
           * Create a Remix request handler and pass
           * Hydrogen's Storefront client to the loader context.
           */
          const handleRequest = createRequestHandler({
            // eslint-disable-next-line import/no-unresolved
            build: await import('virtual:react-router/server-build'),
            mode: process.env.NODE_ENV,
            getLoadContext: () => hydrogenContext,
          });

          const response = await handleRequest(request);

          if (hydrogenContext.session.isPending) {
            response.headers.set(
              'Set-Cookie',
              await hydrogenContext.session.commit(),
            );
          }

          if (response.status === 404) {
            /**
             * Check for redirects only when there's a 404 from the app.
             * If the redirect doesn't exist, then `storefrontRedirect`
             * will pass through the 404 response.
             */
            return storefrontRedirect({
              request,
              response,
              storefront: hydrogenContext.storefront,
            });
          }

          return response;
        },
      );
    } catch (error) {
      console.error(error);
      return new Response('An unexpected error occurred', {status: 500});
    }
  },
};

vite.config.ts:

import {reactRouter} from '@react-router/dev/vite';
import {hydrogen} from '@shopify/hydrogen/vite';

import {sentryReactRouter} from '@sentry/react-router';
import {oxygen} from '@shopify/mini-oxygen/vite';
import tailwindcss from '@tailwindcss/vite';
import {sanity} from 'hydrogen-sanity/vite';
import {defineConfig} from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';

export default defineConfig((config) => ({
  plugins: [
    tailwindcss(),
    hydrogen(),
    oxygen(),
    reactRouter(),
    sentryReactRouter(
      {
        org: 'MY ORG',
        project: 'MY PROJECT',
        authToken:  'MY AUTH TOKEN',
      },
      config,
    ),
    tsconfigPaths(),
    sanity(),
  ],
  build: {
    // Allow a strict Content-Security-Policy
    // withtout inlining assets as base64:
    assetsInlineLimit: 0,
  },
  ssr: {
    optimizeDeps: {
      /**
       * Include dependencies here if they throw CJS<>ESM errors.
       * For example, for the following error:
       *
       * > ReferenceError: module is not defined
       * >   at /Users/.../node_modules/example-dep/index.js:1:1
       *
       * Include 'example-dep' in the array below.
       * @see https://vitejs.dev/config/dep-optimization-options
       */
      include: [
        'react-portable-text',
        '@headlessui/react',
        'algoliasearch',
        'react-instantsearch',
        'disqus-react',
        'set-cookie-parser',
        'cookie',
        'react-router',
      ],
    },
  },
  server: {
    allowedHosts: true,
  },
}));

app/entry.server.tsx:

import {renderToReadableStream} from 'react-dom/server';
import type {EntryContext} from 'react-router';
import {ServerRouter} from 'react-router';
import {
  createContentSecurityPolicy,
  type HydrogenRouterContextProvider,
} from '@shopify/hydrogen';

import {isbot} from 'isbot';

export default async function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  reactRouterContext: EntryContext,
  context: HydrogenRouterContextProvider,
) {
  const {SanityProvider} = context.sanity;
  const {nonce, header, NonceProvider} = createContentSecurityPolicy({
    shop: {
      checkoutDomain: context.env.PUBLIC_CHECKOUT_DOMAIN,
      storeDomain: context.env.PUBLIC_STORE_DOMAIN,
    },
    imgSrc: ['*'],
    styleSrc: ['*', 'unsafe-inline'],
    fontSrc: ['*', 'data:'],
    defaultSrc: ['*'],
    scriptSrc: ['*', 'unsafe-inline', "'strict-dynamic'"],
    connectSrc: ["'self'", '*'],
  });

  const body = await renderToReadableStream(
    <NonceProvider>
      <SanityProvider>
        <ServerRouter
          context={reactRouterContext}
          url={request.url}
          nonce={nonce}
        />
      </SanityProvider>
    </NonceProvider>,
    {
      nonce,
      signal: request.signal,
      onError(error) {
        console.error(error);
        responseStatusCode = 500;
      },
    },
  );

  if (isbot(request.headers.get('user-agent'))) {
    await body.allReady;
  }

  responseHeaders.set('Content-Type', 'text/html');
  responseHeaders.set('Content-Security-Policy', header);

  return new Response(body, {
    headers: responseHeaders,
    status: responseStatusCode,
  });
}

Steps to Reproduce

In my code, I use the correct DSN, project, org, authToken, and everything works fine except for app/entry.server.tsx.

I'm trying to follow this step (https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/hydrogen-react-router/# server-side-rendering-with-trace-injection), but here (app/entry.server.tsx.), if I insert import '../ instrument.server.mjs'; or start using anything from here import * as Sentry from “@sentry/react-router/cloudflare”;, I get an error:

ReferenceError: require is not defined
    at /Users/PATH/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js:3:15
    at Object.runInlinedModule (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1418:17)
    at ModuleRunner.directRequest (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1281:82)
    at ModuleRunner.cachedRequest (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1176:28)
    at request (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1225:79)
    at /Users/PATH/node_modules/@sentry/react/build/esm/hoist-non-react-statics.js?v=bab08d99:2:31
    at Object.runInlinedModule (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1418:11)
    at ModuleRunner.directRequest (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1281:61)
    at ModuleRunner.cachedRequest (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1177:79)
    at /Users/PATH/node_modules/@sentry/react/build/esm/profiler.js?v=bab08d99:7:365

Expected Result

Working app/entry.server.tsx part

Actual Result

ERROR:

ReferenceError: require is not defined
    at /Users/PATH/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js:3:15
    at Object.runInlinedModule (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1418:17)
    at ModuleRunner.directRequest (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1281:82)
    at ModuleRunner.cachedRequest (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1176:28)
    at request (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1225:79)
    at /Users/PATH/node_modules/@sentry/react/build/esm/hoist-non-react-statics.js?v=bab08d99:2:31
    at Object.runInlinedModule (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1418:11)
    at ModuleRunner.directRequest (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1281:61)
    at ModuleRunner.cachedRequest (Users/PATH/node_modules/@shopify/mini-oxygen/dist/vite/worker-entry.js:1177:79)
    at /Users/PATH/node_modules/@sentry/react/build/esm/profiler.js?v=bab08d99:7:365

Additional Context

I have already tried different versions of Node.js (https://sentry.io/answers/next-js-referenceerror-request-is-not-defined-reading-old-version-of-node/), and tried removing "type": "module" from package.json, but to no avail.

Metadata

Metadata

Assignees

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions