nuxt: Server-side rendering with shared vue components in yarn workspace results in "Cannot find module"

Version

v2.11.0

Reproduction link

http://n.a

Steps to reproduce

This is all inside one folder, to reproduce the exact error message it would live at /home/myuser/repos/core

  1. Create a folder structure like common/vue/components/atoms/ with box.vue at the top and a package.json at common/vue defining the name as common-vue
  2. Create a folder structure like example/test containing a nuxt project
  3. Add both as yarn workspaces
  4. In the nuxt project, import the common vue component with import EBox from 'common-vue/components/atoms/box';
  5. Run nuxt dev or build/run commands

What is expected ?

The site works as expected, showing the shared vue component

What is actually happening?

You see a page with a NuxtServerError stating: Cannot find module 'common-vue/components/atoms/box' from '/home/myuser/repos/core/example/test'

Additional comments?

We tried quite a few things:

  1. Replacing the yarn created symlinks in node_modules with an actual copy of the respective folder
  2. Setting rootDir, modulesDir and webpack’s nodeExternals to various combinations, sometimes managing to change the error to Cannot find module 'common-vue/components/atoms/box' from '/home/myuser/repos/core/' (i.e. pointing to where the root level node_modules are)
  3. Setting the bundleRenderer’s baseDir

My best guess right now is that it is tied to vue-ssr’s externals config that only whitelists css by default as documented here. I sadly can’t find whether/where nuxt sets this value and didn’t find a way to override it.

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 9
  • Comments: 20 (1 by maintainers)

Most upvoted comments

Hi! I will share a demo repository soon 😃

Having the same issue, also using Nuxt TypeScript, but seems to be an issue even without it. @pi0 did you share a demo repository anywhere, or would you like me to create one?

About this, I solve solation by some config. After setup lerna.js and yarn workspace for each package in nuxt.config.js set modulesDir: ['../../node_modules'] my directory

├─--packages
│   ├── system-design 
│   │  ├── **/*.css
│       ├── package.json
├── public
│   ├── css
│   ├── images
│   ├──nuxt.config.js
│   ├── package.json
├── node_modules
├── package.json
├── yarn-lock.json 
└── .gitignore

then for link system design to the public, I run this command to the public directory

lerna add @xx-front/system-design  --scope=@scrop-front/public

finally, import my vue component in public component by

import XComponent from "@ostadbank-front/design-system/xxx/xxx.vue"

but for short than src you also can add alias in nuxt.config

  alias: {
    '@design-system': resolve(__dirname, '../../node_modules/@xxx-front/design-system'),
  }

I hope useful.

Here’s an example repository (it’s using TypeScript & Lerna thought, but I’m pretty sure it’s the same underlying issue)

https://github.com/RobinBertilsson/nuxt-lerna-6929

Steps to reproduce

  1. Clone the repository
  2. Run yarn && yarn lerna bootstrap
  3. Open it in your browser
  4. The error should appear
  5. Switch mode inside nuxt.config.ts from universal to spa
  6. The error should NOT appear

Just ran into this issue today and spent that last 3-4 hours trying to fix it! 😞

None of the workarounds are remotely ideal. The one I’ve decided to go with is to define common-vue as an alias that points directly to the project folder:

build: {
  extend(config, ctx) {
    config.resolve.alias = {
      ...config.resolve.alias,
      'common-vue': path.resolve(__dirname, '../common-vue'),
    };

Also, need a similar path mapping in tsconfig.json for TypeScript projects:

{
  "compilerOptions": {
    ...
    "paths": {
      ...

      "common-vue/*": ["../common-vue/*"]
    },

It’s important that common-vue isn’t symlinked into node_modules. In my case, I actually defined my alias with a different name (e.g. common-vue-alias) so that I don’t forget to fix it properly once there’s a better solution. Speaking of which…

Anyone know a better solution? Like I said, none of the workarounds are ideal, and having a shared component library in a monorepo must be a common use case. Is it not?