coveo / ui-kit

Coveo UI kit repository, home of @coveo/headless, @coveo/atomic, and more.
Apache License 2.0
51 stars 34 forks source link

[Bug]: Unable to import @coveo/headless/ssr as esm module. #3677

Closed bartoszherba closed 1 week ago

bartoszherba commented 7 months ago

Which product are you using?

Headless

product version

2.52.0

bug description

We're currently utilizing the Nuxt 3 framework, leveraging the @coveo/headless/ssr package to render pages on the server-side. While development mode functions smoothly, encountering issues arises when transitioning to production mode:

Upon building and launching in production mode, an error surfaces:

Cannot find module '.<...>/storefront-unified-nuxt/.output/server/node_modules/@coveo/headless/ssr' imported from <...>/storefront-unified-nuxt/.output/server/chunks/build/default-B7qCwyG1.mjs Did you mean to import "@coveo/headless/dist/ssr/headless.js"?

Implementing a transpile solution for @coveo/headless via the build configuration introduces another hurdle:

require is not defined in ES module scope, you can use import instead

This error stems from the pino library, a dependency of your package.

Attempting to address the issue by creating an alias for the ssr package, pointing it to @coveo/headless/dist/ssr/headless.js, led to TypeScript complications.

We attempted to isolate the problem by creating a minimalist package with only the necessary library and imported dependencies, but encountered further difficulties.

Screenshot 2024-03-07 at 09 02 46

We were also trying to figure out how did you do this for the react in your samples (ui-kit github repo). We've noticed that you are transpilling all sample packages with transpilePackages: ['@coveo/headless-ssr-samples-common'], In the next.config.js but still there is an error in the terminal:

> @coveo/headless-ssr-samples-pages-router@0.0.0 build:next
> next build
   ▲ Next.js 14.1.0
   Linting and checking validity of types ...
   Creating an optimized production build ...
 :warning: Compiled with warnings
../../../headless/dist/browser/ssr/headless.esm.js
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
Import trace for requested module:
../../../headless/dist/browser/ssr/headless.esm.js
../common/components/react/search-parameter-manager.tsx
../../../headless/dist/browser/ssr/headless.esm.js
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
Import trace for requested module:
../../../headless/dist/browser/ssr/headless.esm.js

Steps to reproduce

There are two procedures: A)

  1. Create an npm package
    "name": "test",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "author": "",
    "license": "ISC",
    "dependencies": {
    "@coveo/headless": "^2.52.0"
    }
    }
  2. Create a file and import coveo/headless/ssr package into it import { defineSearchEngine } from '@coveo/headless/ssr';
  3. run `node

B)

  1. Initialize nuxt 3 application and add coveo/headless lib as a dependency
  2. Create a very simple implementation only to fetch data on the server eg.:
    
    <template>
    <h1> test</h1>
    </template>

3. `build and start` the application (it will work in dev mode, necessarily run it in a prod mode)

### Relevant log output

_No response_
louis-bompart commented 7 months ago

Hi, assuming that you use the legacy page router, you'll probably need to use the transpilePackage configuration option with both @coveo/headless and @coveo/headless-react.

+   transpilePackages: ['@coveo/headless', '@coveo/headless-react'],

This is something we can't fix without introducing a breaking change, so it's here to stay for the remaining lifespan of @coveo/headless v2.

We might be missing some documentation on the matter, we will investigate that!

Thanks for your report :)

bartoszherba commented 7 months ago

@louis-bompart We are not using react library but nuxt and @coveo/headless + @coveo/headless/ssr

I also figured out that it can be "fixed" by adding:

    transpile: ['@coveo/headless'],
  },
  vite: {
    build: {
      commonjsOptions: { transformMixedEsModules: true }, // Change
    },
   ...
  },

In the nuxt config. However, the @coveo/headless/ssr lib still cannot be imported as an es module without transpiler.

louis-bompart commented 7 months ago

@louis-bompart We are not using react library but nuxt and @coveo/headless + @coveo/headless/ssr

I also figured out that it can be "fixed" by adding:

    transpile: ['@coveo/headless'],
  },
  vite: {
    build: {
      commonjsOptions: { transformMixedEsModules: true }, // Change
    },
   ...
  },

In the nuxt config. However, the @coveo/headless/ssr lib still cannot be imported as an es module without transpiler.

My bad! But yeah, your workaround is correct and required, but should not be with our upcoming V3 release later this year. With V3, we will shift our entrypoints definition from main through several 'stubbed' package.json, such as packages/headless/ssr/package.json to conditional exports.

This will allow modern bundlers/tools such as Vite (and by extension Nuxt), to use the 'right' JavaScript at the right time.

On top of that, we will ensure that no requires remain in both our source code and our compiled code (for ESM).

All those changes are breaking changes, and we need to tread carefully with them. For that reason, we need to delay the 'true fix' to our next major release, and ask you to use the workaround you mentioned until then 😓

louis-bompart commented 1 week ago

Hi @bartoszherba , this should be fixed in v3 which should be out soon.

I'll close this issue as complete, but if you still have issue don't hesitate to reach out again