javascriptvue.jsnuxt.jsdevextremenuxt3.js

DevExtreme in Nuxt3 failing during build


I am trying to include DevExtreme UI components into Nuxt 3 project. I took basic Nuxt3 app generated via npx nuxi init nuxt-app and started with bending it.

This is my test component with very basic DevExtreme menu:

<template>
  <div id="container">
    <dxMenu>
        <dxItem icon="home" />
        <dxItem text="O aplikaci" />
        <dxItem icon="key" />
    </dxMenu>
  </div>
</template>

<script lang="ts">
  import DxMenu, { DxItem } from 'devextreme-vue/menu.js';
  import { defineComponent } from 'vue'
 
  export default defineComponent({
    components: {
        DxMenu, DxItem
    }
  })
</script>

Then I just render the component in my app.vue. I have no other configuration related to that (apart from importing DevExtreme css file via nuxt.config.ts).

My nuxt.config.ts looks just like this:

import { defineNuxtConfig } from 'nuxt'

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
    css : [
        '@/assets/css/dx.generic.zdd-scheme.css'
    ]
})

I was quite successful for dev environement - running npm run dev works like charm. But when I try npm run build it always fails.

The output looks like this:

i Client built in 11430ms                                                13:38:43
i Building server...                                                     13:38:43
āˆš Server built in 4482ms                                                 13:38:47
āˆš Generated public .output/public                                  nitro 13:38:47
start Building server...                                           nitro 13:38:47

ERROR  Rollup error: Error: Cannot find module devextreme/ui/menu imported from file:///C:/ATOS_Projekty/ZDD/web- 
ui/app/node_modules, file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nuxt/node_modules, 
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nitropack/node_modules, file:///C:/ATOS_Projekty/ZDD/web-ui/app/, 
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/_index.js, file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules, 
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nuxt/, file:///C:/ATOS_Projekty/ZDD/web- 
ui/app/node_modules/nuxt/node_modules/_index.js, file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nuxt/node_modules, 
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nitropack/, file:///C:/ATOS_Projekty/ZDD/web- 
ui/app/node_modules/nitropack/node_modules/_index.js, file:///C:/ATOS_Projekty/ZDD/web- 
ui/app/node_modules/nitropack/node_modules


ERROR  Error: Cannot find module devextreme/ui/menu imported from file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules, 
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nuxt/node_modules, file:///C:/ATOS_Projekty/ZDD/web- 
ui/app/node_modules/nitropack/node_modules, file:///C:/ATOS_Projekty/ZDD/web-ui/app/, file:///C:/ATOS_Projekty/ZDD/web- 
ui/app/node_modules/_index.js, file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules, file:///C:/ATOS_Projekty/ZDD/web- 
ui/app/node_modules/nuxt/, file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nuxt/node_modules/_index.js, 
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nuxt/node_modules, file:///C:/ATOS_Projekty/ZDD/web- 
ui/app/node_modules/nitropack/, file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nitropack/node_modules/_index.js, 
file:///C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nitropack/node_modules

at resolvePath (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/mlly/dist/index.mjs:1079:10)
at _resolve (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nitropack/dist/shared/nitro.8d0213e3.mjs:304:22)
at Object.resolveId (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/nitropack/dist/shared/nitro.8d0213e3.mjs:348:34)
at async resolveId (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/rollup/dist/es/shared/rollup.js:21737:26)
at async ModuleLoader.resolveId (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/rollup/dist/es/shared/rollup.js:22037:19)
at async /C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/@rollup/plugin-commonjs/dist/es/index.js:773:14
at async Promise.all (index 0)
at async /C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/@rollup/plugin-commonjs/dist/es/index.js:765:30
at async rewriteRequireExpressionsAndGetImportBlock (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/@rollup/plugin-commonjs/dist/es/index.js:1312:28)
at async transformCommonjs (/C:/ATOS_Projekty/ZDD/web-ui/app/node_modules/@rollup/plugin-commonjs/dist/es/index.js:1874:23)`

devextreme-vue/menu is importing from devextreme/ui/menu, but it looks like this module is not being passed through during build.

Do I have to declare the dependency somewhere in my code to notify build server to use it? I have tried various things already (like trying to convince Vite (rollup) not to perform tree shaking or to switch to Webpack instead), but always ending up with the same result. But maybe I just fail to do it correctly, I still have to learn a lot about how exactly the things work here. Any help/clues will be appreciated.

This is my package.json in case I shall change or install something there.

{
  "private": true,
  "scripts": {
    "build": "nuxt build",
    "dev": "nuxt dev",
    "generate": "nuxt generate",
    "preview": "nuxt preview",
    "postinstall": "nuxt prepare",
    "start": "nuxt start"
  },
  "devDependencies": {
    "nuxt": "3.0.0-rc.8"
  },
  "dependencies": {
    "devextreme": "22.1.4",
    "devextreme-vue": "22.1.4"
  }
}

EDIT: my node is 16.17.0 and npm 8.19.0, maybe the versions are relevant...


Solution

  • So the working solutuion appears to be adding a plugin, in my case named dx.client.ts, but it shouldn't matter, into /plugins folder which imports all necessary components and makes them globally available inside the application:

    import { DxButton } from "devextreme-vue/button";
    import { DxMenu, DxItem } from 'devextreme-vue/menu';
    // the list goes on as the app grows
    
    export default defineNuxtPlugin((nuxtApp) => {
        nuxtApp.vueApp
          .component("DxButton", DxButton)
          .component("DxMenu", DxMenu)
          .component("DxItem", DxItem);
    
          // the list goes on as the app grows 
    
    });
    

    I also had to add:

    ssr: false
    

    option into nuxt.config.ts, otherwise I ended up with Entry module cannot be external (devextreme-vue). error message during build.

    So it has some limitations, but so far it works.

    EDIT: it turned out, that while it works fine for some DevExtreme components without further adjustments, some components (like DxForm) also require to disable tree-shaking during Vite build - see how to do it. Otherwise the necessary files are lost in the build process and vague runtime error TypeError: f(...)[t] is not a function appears while rendering the component.

    Thanks Stefan (stenet) for the right answer provided here