asyncapi-react: [BUG] NextJS: SyntaxError: Cannot use import statement outside a module

Description

I’m trying to render the AsyncApi react component in a NextJS app, but it crashes, displaying the error above: Maybe there is a problem of compatibility between CommonJS modules and ESModules

import AsyncApi from './containers/AsyncApi/AsyncApi';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at compileFunction (<anonymous>)
    at Module._compile (internal/modules/cjs/loader.js:895:18)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Function.Module._load (internal/modules/cjs/loader.js:727:14)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at eval (webpack-internal:///@kyma-project/asyncapi-react:1:18)
    at Object.@kyma-project/asyncapi-react (/Users/ricardonakashima/Projetos/asyncapireact/.next/server/pages/index.js:150:1)
    at __webpack_require__ (/Users/naka/Projetos/asyncapireact/.next/server/pages/index.js:23:31)

Expected result

It should render the component

Steps to reproduce you can easily reproduce the error by installing a simple next app:

  1. npx create-next-app
  2. installing the lib: npm install --save @kyma-project/asyncapi-react
  3. importing the component and rendering it in any page with any valid yml file.

Troubleshooting

I was able to compile the app by dynamically importing the component with ssr:false, but the component does not render.

import dynamic from ‘next/dynamic’ const AsyncApiComponent = dynamic(() => import(‘@kyma-project/asyncapi-react’), { ssr:false})

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 8
  • Comments: 18 (7 by maintainers)

Commits related to this issue

Most upvoted comments

This is actually a problem with many modules when NextJS tries to do the server-side rendering and they are components that rely on being rendered in the browser.

There’s a way around this documented in NextJS docs which consists on using a dynamic import disabling server-side rendering:

import dynamic from 'next/dynamic'

const AsyncApi = dynamic(import('@asyncapi/react-component'), { ssr: false }) // Async API cannot be server-side rendered

export const FooComponent = () => {
    return <AsyncApi {...} />
}

hey, folks.

The same problem when I use the react-pdf lib.

@YujiNNakashima Hi! Sorry for late response. I reproduced your problem by bootstrap nextjs app and yes, this is a problem with ESmodules. We are using TS in a component and have a module target set to esnext. I tried to change it to commonJS, but then if I use the component, then some internal shared components in library don’t work, so we must add webpack/rollup and create several targets like umd, esm, cjs. Unfortunately, you cannot using pure React component in your project.

But don’t worry, I tried to use our @asyncapi/web-component in nextJS app and it works in my env. So please install @asyncapi/web-component in your project:

npm i @asyncapi/web-component -s

and then import and use the component in this way:

export default function SomeYourComponent() {
  // lazy import for component
  React.useEffect(() => import("@asyncapi/web-component/lib/asyncapi-web-component"), []);

  return (
    <asyncapi-component schema={asyncapiSchema} cssImportPath="./asyncapi.css" />
  );
}

where asyncapiSchema is a schema, and cssImportPath is a path to css file. The easier way to have a css is copy this file https://codesandbox.io/s/asyncapi-web-component-in-action-l652x?file=/src/assets/asyncapi.css to ./public/asyncapi.css (please NOTE that cssImportPath prop has a ./asyncapi.css value, because NextJS read assets from public folder).

It works in dev and also in prod (after build) environments. Please try it and give the feedback. Of course, if you have any question, feel free to ask 😃

@acelaya Thanks for awesome feedback, I really appreciate that! 🤗

On TypeScript it complains about missing declaration for @asyncapi/react-component/browser. I have worked around it with @ts-expect-error for now.

Yes, we know about that, but there is a problem that TS at the moment doesn’t support exports field in package.json. You can read more about it in this issue. It means that we cannot add redirect to appropriate types of given path (at the moment package.json supports only one types file/path). Only solution is adding this typings to types folder (new common folder in transpiled module) for this path manually before packing the package and publish in npm. I didn’t check that and I’m not sure if it will work. I will try to do it and let you know 😃

Default stylesheet looks more like a page one than a component one, with a lot of resets, defaults, etc. It had some minor side effects over other styles in my page, but nothing critical. I guess this is related with the new tailwind-based styles and will be improved in the future.

We also know about that but we we wanted to prerelease the component so people could give feedback and if founded bugs with logic and styles will be fixed then we will go to 1.0.0 (I don’t know when this will happen). Of course 1.0.0 will also included custom theming etc. Sorry for reseting styles, I always tested new component on “fresh” projects, so I didn’t notice this reseting. Most likely there is a flag in tailwind to disable reseting. Thanks for the information!

When I export my Next.JS site to a static page, it does not include the stylesheet for some reason. I’m still investigating why does it skip only this specific one when I’m importing others in the same way. Probably not related specifically with this component, but more with the way Next.JS and webpack are plugged together.

Awesome that you fixed problem. To be honest, I also tested component in NextJS (of course fresh project) and everything worked as expected, also build and serve this build. Maybe some bug in your version of NextJS?

Also related to stylesheet, you can try add our stylesheet as first stylesheet in page, the maybe another will “disable” the reseting 😃

Thanks for feedback again!

Hey @magicmatatjahu, I’m testing the new version and overall, it looks amazing. I love the new look and feel.

Some feedback I can provide after starting to use it on my Next.JS app:

  • On TypeScript it complains about missing declaration for @asyncapi/react-component/browser. I have worked around it with @ts-expect-error for now.
  • Default stylesheet looks more like a page one than a component one, with a lot of resets, defaults, etc. It had some minor side effects over other styles in my page, but nothing critical. I guess this is related with the new tailwind-based styles and will be improved in the future.
  • When I export my Next.JS site to a static page, it does not include the stylesheet for some reason. I’m still investigating why does it skip only this specific one when I’m importing others in the same way. Probably not related specifically with this component, but more with the way Next.JS and webpack are plugged together.
    • EDIT: I have worked around this point by replacing the import of the stylesheet as a module from within a TypeScript file, and moved it as a CSS @import inside another one of my own CSS files. This way webpack detects it and includes it in the final bundle.

@SteveSonoa so far we just do not have an idea how to fix it and suggest web component. Since you say web component also causes issues we need to check, but for this, to move forward we need some sample project from your side, best on code sandbox, so we can see the problem in a reproducable environment

I haven’t found a fully working approach in pure react/nextjs, but @magicmatatjahu suggested using the web component instead.

I haven’t tried it though.