Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

require() of ES modules is not supported (Quasar v2) #85

Closed
kostia7alania opened this issue Oct 24, 2021 · 6 comments
Closed

require() of ES modules is not supported (Quasar v2) #85

kostia7alania opened this issue Oct 24, 2021 · 6 comments
Labels
bug Something isn't working

Comments

@kostia7alania
Copy link

================== GENERATE ==================

App • Cleaned build artifact: "C:\apps\vue\h5-off-site\dist\ssg"
Extension(ssg) • Copying assets...
Extension(ssg) • WAIT • Generating pages in progress...
[Vue Router warn]: uncaught error during route navigation:
[ Error: C:\apps\vue\h5-off-site\node_modules\swiper\vue\swiper-vue.js
require() of ES modules is not supported.
require() of C:\apps\vue\h5-off-site\node_modules\swiper\vue\swiper-vue.js from C: \apps\vue\h5-off-site\node_modules.cache\quasar-app-extension-ssg is an ES module file as it is a .js file whose nearest parent package.json contains "type": "modu le" which defines all .js files in that package scope as ES modules.
Instead rename swiper-vue.js to end in .cjs, change the requiring code to use impo rt(), or remove "type": "module" from C:\apps\vue\h5-off-site\node_modules\swiper\ package.json.

  • errors.js:322 new NodeError
    internal/errors.js:322:7

  • loader.js:1102 Object.Module._extensions..js
    internal/modules/cjs/loader.js:1102:13

  • loader.js:950 Module.load
    internal/modules/cjs/loader.js:950:32

  • loader.js:790 Function.Module._load
    internal/modules/cjs/loader.js:790:12

  • loader.js:974 Module.require
    internal/modules/cjs/loader.js:974:19

  • helpers.js:93 require
    internal/modules/cjs/helpers.js:93:18

  • create-bundle.js:56 _require
    [h5-off-site]/[@quasar]/ssr-helpers/lib/create-bundle.js:56:9

  • render-app.js:491 Object.5804
    render-app.js:491:18

  • render-app.js:555 webpack_require
    render-app.js:555:41

  • chunk-392.js:386 Object.8072
    chunk-392.js:386:68

] {
code: 'ERR_REQUIRE_ESM'
}
Extension(ssg) • DONE • Pages generated with errors • 101ms

Extension(ssg) • ERROR • Generate route /

Error: C:\apps\vue\h5-off-site\node_modules\swiper\vue\swiper-vue.js
require() of ES modules is not supported.
require() of C:\apps\vue\h5-off-site\node_modules\swiper\vue\swiper-vue.js from C: \apps\vue\h5-off-site\node_modules.cache\quasar-app-extension-ssg is an ES module file as it is a .js file whose nearest parent package.json contains "type": "modu le" which defines all .js files in that package scope as ES modules.
Instead rename swiper-vue.js to end in .cjs, change the requiring code to use impo rt(), or remove "type": "module" from C:\apps\vue\h5-off-site\node_modules\swiper\ package.json.

@yeus
Copy link

yeus commented Oct 25, 2021

I have a similar problem with a third party library: aws-amplify/ui-vue:

 ================== GENERATE ==================

 App • Cleaned build artifact: "/home/tom/Dropbox/company/src/doxcavator/frontend/dist/ssg"
 Extension(ssg) • Copying assets...
 Extension(ssg) •  WAIT  • Generating pages in progress...
configured
the Auth module is configured
The user is not authenticated


/home/yeus/libs/node_modules/@aws-amplify/ui-vue/dist/index.js
  require() of ES modules is not supported.
  require() of /home/tom/yeus/libs/node_modules/@aws-amplify/ui-vue/dist/index.js from /home/yeus/finapp/frontend/node_modules/.cache/quasar-app-extension-ssg is an ES module file as   it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
  Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/yeus/libs/node_modules/@aws-amplify/ui-vue/package.json.

(...)

  - chunk-935.js:117 Object.3658
    chunk-935.js:117:77
  
] {
  code: 'ERR_REQUIRE_ESM'
}

When I render the app with quasar build -m ssr I don't get any error messages, The ssr build itself succeeds also with the extension. Its related to this library here: https://ui.docs.amplify.aws/ui/components/authenticator?platform=vue. I use their component in my template.

@freddy38510: Is it possible to tell your extension to "leave out" one specific page or even component, or explicitly tell the extension which pages to render and which ones should stay i spa mode?

@yeus
Copy link

yeus commented Oct 25, 2021

@kostia7alania this here:

might help you. It explicitly puts the component on the client. Maybe that will help webpack circumventing the issue?

@freddy38510
Copy link
Owner

freddy38510 commented Oct 25, 2021

@yeus

You are right, the compilation with webpack itself has no errors. But even with SSR mode when you start the web-server you got the error about ES module which is not supported.

@kostia7alania

This is because since version 7 Swiper is a pure ESM package. You can downgrade to v6 or async import the components.

// your SFC component
import { defineComponent, defineAsyncComponent } from 'vue';

export default defineComponent({
components: {
  swiper: defineAsyncComponent(async () => {
    const { Swiper } = await import('swiper/vue');

    return Swiper;
  }),
  swiperSlide: defineAsyncComponent(async () => {
    const { SwiperSlide } = await import('swiper/vue');

    return SwiperSlide;
  }),
});

Using Quasar boot files can do the trick too if you want to register globally some components.
But don't forget to run it on client-side only if the component is not universal (not compatible with SSR):

Running it on client-side only:

// boot/swiper.js file
import { Swiper, SwiperSlide } from 'swiper/vue';

export default ({ app }) => {
  app.component('swiper', Swiper);

  app.component('swiper-slide', SwiperSlide);
};

// quasar.conf.js file
module.exports = configure((ctx) => ({
  boot: [
    {
      server: false, // run on client-side only!
      path: 'swiper', // references /src/boot/<name>.js
    },
  ],
});

Or on client-side and server-side:

// boot/swiper.js file
import { defineAsyncComponent } from 'vue';

export default ({ app }) => {
  app.component('swiper', defineAsyncComponent(async () => {
    const { Swiper } = await import('swiper/vue');

    return Swiper;
  }));

  app.component('swiper-slide', defineAsyncComponent(async () => {
    const { SwiperSlide } = await import('swiper/vue');

    return SwiperSlide;
  }));
};

// quasar.conf.js file
module.exports = configure((ctx) => ({
  boot: ['swiper'],
});

If after all you've got some hydration errors at client-side you can wrap the components in the Quasar q-no-ssr component.

I will open an issue about this on Quasar repository as the issue is not related to this app extension.

@freddy38510 freddy38510 changed the title is this work with quasar v3 ? require() of ES modules is not supported (Quasar v2) Oct 25, 2021
@freddy38510 freddy38510 added the bug Something isn't working label Oct 25, 2021
@freddy38510
Copy link
Owner

Found a better way to handle this.

Just transpile swiper and its dependencies and all is working fine.

// quasar.conf.js
module.exports = configure((ctx) => ({
  build: {
    transpileDependencies: ['swiper', 'swiper/vue', 'ssr-window', 'dom7'],
  }
});

If you have any errors related to babel during webpack compilation, try to remove your node_modules folder and yarn.lock file, then run the command yarn.

Could be useful to you @yeus too. Try to add @aws-amplify/ui-vue to the transpileDependencies array.

@yeus
Copy link

yeus commented Oct 25, 2021

@freddy38510. Thank you! that last one worked with the amplify library. still have some small issues on how it is displayed. Such as it assumes the initial state is "logged in" for some reason... but working on those as well now ;).

@freddy38510
Copy link
Owner

@yeus Good to know that you can now use the Vue components from Amplify lib.

If the content of your pages is conditionnaly rendered by the Auth state, I would encourage you to not pre-render it.

Otherwise, at first-load users will see the page rendered with the state initiated at build-time, then when Vue takes over, the content will change if the user is logged-in.

This can only be handle at client-side. Do not pre-render these pages. Or use the Quasar q-no-ssr component.
Also don't forget to set your Quasar boot files to be executed at client-side only based on the previous suggestion I made about authentication.

I'm closing this issue since it is solved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants