Nuxt.js: External webpack plugins must be installed as prod dependencies

Created on 2 May 2020  Â·  4Comments  Â·  Source: nuxt/nuxt.js

Version

v2.12.2

Steps to reproduce

Add a webpack loader.

Install dep :

npm install --save-dev node-sass-json-importer

Import in your build config this:

import jsonImporter from 'node-sass-json-importer'

export default {
  build: {
    loaders: {
      scss: {
        importer: jsonImporter(),
      },
    },
  }
}

Install dependencies for production env :

npm install --production

Build your app :

nuxt build

Start your app :

nuxt start

Error message :

✖ Nuxt Fatal Error                                    
   │                                                         
   │   Error: Cannot find module 'node-sass-json-importer'

What is expected ?

To not have to install webpack plugins as dev dependencies.

What is actually happening?

We must install webpack plugins as production dependencies.

Additional comments?

More annoying with svg-spritemap-webpack-plugin that also requires webpack...

If config.nuxt.js could be async loaded, we could use the conditional async import.

Or better, to find a way to not load the build config and its dependencies during the run.

This bug report is available on Nuxt community (#c10605)
bug-report

Most helpful comment

Hi @JBustin 😊

Actually you can use a local module and add it to buildModules so it is only required during build.

nuxt.config.js:

export default {
  buildModules: [
    '~/nuxt.build.js'
  ]
}

nuxt.build.js:

import { resolve } from 'path'
import SVGSpritemapPlugin from 'svg-spritemap-webpack-plugin'
import jsonImporter from 'node-sass-json-importer'

export default function () {
  this.nuxt.options.build.loaders.scss = {
    importer: jsonImporter()
  }

  this.extendBuild(({ plugins }) => {
    plugins.push(new SVGSpritemapPlugin(resolve(this.options.srcDir, 'assets/**/*.svg'), {
      output: {
        filename: 'icons.svg',
        svgo: {
          plugins: [
            {
              removeAttrs: {
                attrs: ['stroke', 'fill']
              }
            }
          ]
        }
      },
      sprite: {
        generate: {
          title: false
        }
      }
    }))
  })
}

All 4 comments

  1. The nuxt config can be an async function returning the config
  2. It depends on your setup. If you use the build artifact produced during nuxt build (e.g. from your CI) and only need to run nuxt start, you don't need these loaders as production deps.

Thanks for your response.

My previous message was a bit confused.
After I have built the dist (located in .nuxt) on CI, with nuxt build, I copy the sources (only with the npm production deps) in my production docker image and I use nuxt start when I run it.

When you talk about the build artifact, is there a special command to start it ?
Cause nuxt start raises an error in nuxt.config.js (or it's an indication that uses a sourcemap ?)

root@a21667af2183:/usr/app# ./node_modules/.bin/nuxt start

 FATAL  Cannot find module 'svg-spritemap-webpack-plugin'                                              18:55:51
Require stack:
- /usr/app/config/build.config.js
- /usr/app/nuxt.config.js

Maybe I missed documentation to better understand.

My nuxt.config.js contains two webpack plugins like this :

import SVGSpritemapPlugin from 'svg-spritemap-webpack-plugin'
import jsonImporter from 'node-sass-json-importer'

...
build: {
    plugins: [
      new SVGSpritemapPlugin(path.resolve(__dirname, '../src/assets/**/*.svg'), {
        output: {
          filename: 'icons.svg',
          svgo: {
            plugins: [
              {
                removeAttrs: {
                  attrs: ['stroke', 'fill'],
                },
              },
            ],
          },
        },
        sprite: {
          generate: {
            title: false,
          },
        },
      }),
    ],
    loaders: {
      scss: {
        importer: jsonImporter(),
      },
    },
}
...

Is there a way to extract build config from nuxt.config ?

Hi @JBustin 😊

Actually you can use a local module and add it to buildModules so it is only required during build.

nuxt.config.js:

export default {
  buildModules: [
    '~/nuxt.build.js'
  ]
}

nuxt.build.js:

import { resolve } from 'path'
import SVGSpritemapPlugin from 'svg-spritemap-webpack-plugin'
import jsonImporter from 'node-sass-json-importer'

export default function () {
  this.nuxt.options.build.loaders.scss = {
    importer: jsonImporter()
  }

  this.extendBuild(({ plugins }) => {
    plugins.push(new SVGSpritemapPlugin(resolve(this.options.srcDir, 'assets/**/*.svg'), {
      output: {
        filename: 'icons.svg',
        svgo: {
          plugins: [
            {
              removeAttrs: {
                attrs: ['stroke', 'fill']
              }
            }
          ]
        }
      },
      sprite: {
        generate: {
          title: false
        }
      }
    }))
  })
}

It's exactly what I need :)
Thanks a lot

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vadimsg picture vadimsg  Â·  3Comments

o-alexandrov picture o-alexandrov  Â·  3Comments

shyamchandranmec picture shyamchandranmec  Â·  3Comments

gary149 picture gary149  Â·  3Comments

bimohxh picture bimohxh  Â·  3Comments