Nuxt.js: Vendor is too big

Created on 22 Nov 2017  Â·  47Comments  Â·  Source: nuxt/nuxt.js

Vendor is too big,
How to split into two files?

nuxt.config.js

only one build.vendor .....

I need more than one common file

This question is available on Nuxt.js community (#c1940)
question

Most helpful comment

for me it was just enough to reduce chunk sizes not more than 50 Kib, so I hack it like so:

    extend (config, ctx) {
      if (ctx && ctx.isClient) {
        config.optimization.splitChunks.maxSize = 51200
      }
    }

this is my output logs on npm run generate command:

Hash: 55f650db95c0aedbeaab
Version: webpack 4.41.4
Time: 19182ms
Built at: 12/19/2019 8:28:56 PM
                          Asset       Size  Chunks                         Chunk Names
 ../server/client.manifest.json     15 KiB          [emitted]              
        0cde51ddddffebfe69e4.js   26.1 KiB       5  [emitted] [immutable]  commons.app.5bec50a0
        156f5330576e65671f1d.js   22.9 KiB       1  [emitted] [immutable]  app.f69643ec
        160cec1d41e28590bf6e.js    226 KiB      18  [emitted] [immutable]  vendors.app.a2a2526c
        238517e577d836f5c0d0.js   64.4 KiB       8  [emitted] [immutable]  commons.app.aaac3122
        376425dd0a427b29f483.js   15.8 KiB      17  [emitted] [immutable]  vendors.app.78934547
        3a8b86e990c2c8a1a949.js   25.8 KiB      19  [emitted] [immutable]  vendors.app.c1e9ae2e
        423a295fbea8fa5666ec.js   13.1 KiB       9  [emitted] [immutable]  commons.app.d939e436
        4f7286dd41f72a49b6e5.js   14.3 KiB       3  [emitted] [immutable]  commons.app.253ae210
        5165ef6d7ba2a603815b.js   14.7 KiB       2  [emitted] [immutable]  commons.app.0605657e
        5cf237a5a2cd21c7b478.js   28.6 KiB      16  [emitted] [immutable]  vendors.app.74e9f0c9
        603f0a39e70c50006343.js   16.4 KiB      14  [emitted] [immutable]  vendors.app.1655f327
        6d3100c4946db9800ced.js   9.48 KiB      20  [emitted] [immutable]  vendors.app.c964cbd5
        7559d7be9c8cb40cba33.js   15.5 KiB      21  [emitted] [immutable]  vendors.app.ce053847
                       LICENSES  571 bytes          [emitted]              
        a3e7a86e0cfea400b019.js   15.1 KiB      22  [emitted] [immutable]  vendors.app.d939e436
        a4df04ec317d52b2f100.js   2.18 KiB      11  [emitted] [immutable]  pages/index.31ecd969
        a57aa1fcf1c9dfeb2548.js   20.7 KiB       0  [emitted] [immutable]  app.24120820
        c3fa29ab46b642fc22be.js   38.2 KiB      15  [emitted] [immutable]  vendors.app.24f645c1
        d4d4e98c0163682fe1cc.js   10.3 KiB      10  [emitted] [immutable]  commons.app.fdc6512a
        d736b41f2151ef8b55c2.js   8.89 KiB       7  [emitted] [immutable]  commons.app.678f84af
        d95f06092007a91d3ea0.js   15.8 KiB       4  [emitted] [immutable]  commons.app.2a42e354
        e46d9b1a3cf3197879a8.js   28.5 KiB      13  [emitted] [immutable]  vendors.app.11c2601a
        feb4891a9784216e4451.js   13.8 KiB       6  [emitted] [immutable]  commons.app.5c956a7a
runtime.8300a73d8568ed857bdb.js   2.31 KiB      12  [emitted] [immutable]  runtime
 + 2 hidden assets
Entrypoint app = runtime.8300a73d8568ed857bdb.js 4f7286dd41f72a49b6e5.js d95f06092007a91d3ea0.js
423a295fbea8fa5666ec.js feb4891a9784216e4451.js d736b41f2151ef8b55c2.js d4d4e98c0163682fe1cc.js
5165ef6d7ba2a603815b.js 0cde51ddddffebfe69e4.js 238517e577d836f5c0d0.js a3e7a86e0cfea400b019.js
376425dd0a427b29f483.js 603f0a39e70c50006343.js 5cf237a5a2cd21c7b478.js 7559d7be9c8cb40cba33.js
3a8b86e990c2c8a1a949.js 6d3100c4946db9800ced.js e46d9b1a3cf3197879a8.js c3fa29ab46b642fc22be.js
160cec1d41e28590bf6e.js a57aa1fcf1c9dfeb2548.js 156f5330576e65671f1d.js

Hash: e8905e5151dbbb6711f0
Version: webpack 4.41.4
Time: 12291ms
Built at: 12/19/2019 8:29:08 PM
                  Asset       Size  Chunks                         Chunk Names
8495f3a3db1592ed83bc.js   1.63 KiB       1  [emitted] [immutable]  pages/index
              server.js    410 KiB       0  [emitted]              app
   server.manifest.json  145 bytes          [emitted]              
Entrypoint app = server.js
ℹ Generating pages                                                                                                                                                                20:29:09
✔ Generated /                                           

Regards,
Maksim

All 47 comments

Use buid.extend to config whatever you want in webpack.

https://nuxtjs.org/faq/extend-webpack#how-to-extend-webpack-config-

@clarkdo
thank you very mush!
Can I ask you further, configuration details should be how to write?
I tried this idea, but failed.
It may be inappropriate for me to do some things, but I do not know how to do it

Maybe sth like:

module.exports = {
  build: {
    extend(config, { dev, isClient }) {
      if (isClient) {
        const vendor = config.entry.vendor
        // vendor2 is separated vendor file
        const vendor2 = [
          'vue-router',
          'vue-meta'
          // and what ever you want
        ]
        // remove from existing vendor
        config.entry.vendor = vendor.filter(x => !vendor2.includes(x))
        config.entry.vendor2 = vendor2
      }
    }
  }
}

@snoopy83101, pls let me know if @clarkdo 's example is working for you.
I have got strange result, vendor2 dependencies was been added into app chunks

@karmazzin
Do you change the filenames ?

  build: {
    filenames: {
      app: '[name].[chunkhash].js'
    }
  }

config.entry.vendor = ...
config.entry.vendor2 = ...

Is it okay to just configure config.entry?
There's no need to think about CommonsChunkPlugin?

I'll try your method. Thank you

In Nuxt, a module is extracted into the vendor chunk when it's inside node_modules and used in at-least 1/2 of the total pages.

common chunks are in vendor by default, if you want to change this rule, you can customize it by changing config.plugins.

So, I don't have to think about CommonsChunkPlugin.
just

module.exports = {
build: {
extend(config, { dev, isClient }) {
if (isClient) {
const vendor = config.entry.vendor
// vendor2 is separated vendor file
const vendor2 = [
'vue-router',
'vue-meta'
// and what ever you want
]
// remove from existing vendor
config.entry.vendor = vendor.filter(x => !vendor2.includes(x))
config.entry.vendor2 = vendor2
}
}
}
}
All right?

You can also config the filenames as I mentioned above, or vendor2 name will be like app.....js

Combining build. filenames
E... I think I understand now!
Thank you very much for your help!

@clarkdo I followed above mentioned steps the vendor is still big, and vendor2 is created but so small.

screen shot 2018-01-16 at 8 42 32 am

You can try analyse to find which libs are big and separate them into different vendors.

I'm trying to move vuetify, vee-validate to a different bundle. but as above image it shows only 82 byes. This can't be right.

Could you provide your code ?

A part from my nuxt.config.js

{
  ...
  build: {
    analyze: true,
    babel: {
      plugins: ['transform-decorators-legacy', 'transform-class-properties']
    },
    filenames: {
      app: '[name].[chunkhash].js'
    },
    extend(config) {
      const { vendor } = config.entry;
      if (vendor) {
        const vendor2 = ['axios', 'vuetify', 'vee-validate'];
        config.entry.vendor = vendor.filter(v => !vendor2.includes(v));
        config.entry.vendor2 = vendor2;
      }
    },
    vendor: [
      'axios',
      'vuetify',
      'vee-validate',
      'nuxt-class-component',
      'vue-class-component',
      'vue-property-decorator',
      'vuex-class'
    ]
  },
  // specify additional nuxt plugins
  plugins: [
    {
      src: '~/plugins/vue-notifications',
      ssr: false
    },
    '~/plugins/vee-validate',
    '~/plugins/vuetify'
  ],
  ...
}

Can you try to remove commonChunksPlugin or exclude the you vendor2 libs in minChunks of commonChunksPlugin.

    // sth like
    extend(config) {
      if (process.client) {
        const plugin = config.plugins.find((plugin) => plugin.filenameTemplate === 'vendor.js')
        const old = plugin.minChunks
        plugin.minChunks = function (module, count) {
          return old(module, count) && !(/(axios)|(vuetify)|(vee-validate)/).test(module.context)
        }
      }
    }

@clarkdo doesn't seem to work.

Try :smile:

module.exports = {
  build: {
    extend(config, { isClient }) {
      if (isClient) {
        const { vendor } = config.entry
        const vendor2 = ['axios', 'vuetify', 'vee-validate']
        config.entry.vendor = vendor.filter(v => !vendor2.includes(v))
        config.entry.vendor2 = vendor2
        const plugin = config.plugins.find((plugin) => ~plugin.chunkNames.indexOf('vendor'))
        const old = plugin.minChunks
        plugin.minChunks = function (module, count) {
          return old(module, count) && !(/(axios)|(vuetify)|(vee-validate)/).test(module.context)
        }
      }
    },
    filenames: {
      app: '[name].[chunkhash].js'
    },
    vendor: [
      'axios',
      'vuetify',
      'vee-validate'
    ]
  }
}

That config just made it worse, bundles are now bigger, 😭 too bad I don't know much about webpack.

It works for me:

package.json:

{
  "name": "nuxt-demo",
  "dependencies": {
    "axios": "^0.17.1",
    "nuxt": "latest",
    "vee-validate": "^2.0.3",
    "vuetify": "^0.17.6"
  },
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start"
  }
}

nuxt.config.js

module.exports = {
  build: {
    extend(config, { isClient }) {
      if (isClient) {
        const { vendor } = config.entry
        const vendor2 = ['axios', 'vuetify', 'vee-validate']
        config.entry.vendor = vendor.filter(v => !vendor2.includes(v))
        config.entry.vendor2 = vendor2
        const plugin = config.plugins.find((plugin) => ~plugin.chunkNames.indexOf('vendor'))
        const old = plugin.minChunks
        plugin.minChunks = function (module, count) {
          return old(module, count) && !(/(axios)|(vuetify)|(vee-validate)/).test(module.context)
        }
      }
    },
    filenames: {
      app: '[name].[chunkhash].js'
    },
    vendor: [
      'axios',
      'vuetify',
      'vee-validate'
    ]
  }
}

Before:

-rw-r--r--  1 clark  staff  455189  1 16 16:44 vendor.837fce96c1f7f2ad2abc.js

After:

-rw-r--r--  1 clark  staff  142569  1 16 16:43 vendor.4f9def85ed3690acf031.js
-rw-r--r--  1 clark  staff  312724  1 16 16:43 vendor2.69549d11643f13001613.js

Here's the output, after applying above code

screen shot 2018-01-16 at 3 50 49 pm

app seems bigger now

That should because libs in app not extracted into vendor2, maybe you can add a CommonsChunkPlugin for extracting common chunks.

You can take a look at https://github.com/webpack/webpack/issues/4445#issuecomment-285187130

@BruceHem Would you please also share nuxt build --analyze results too? Also using nuxt-edge@latest dependency instead of nuxt for latest changes :)

How about:


const webpack = require('webpack')
module.exports = {
  build: {
    extend(config, { isClient }) {
      if (isClient) {
        config.entry.vendor = config.entry.vendor.filter(v => !['axios', 'vuetify', 'vee-validate'].includes(v))
        config.plugins.unshift(
          new webpack.optimize.CommonsChunkPlugin({
            name: 'app',
            children: true,
            async: 'vendor2',
            minChunks(module, count) {
              return /(axios)|(vuetify)|(vee-validate)/.test(module.context)
            }
          })
        )
      }
    },
    vendor: [
      'axios',
      'vuetify',
      'vee-validate'
    ]
  }
}

@clarkdo thanks for the examples provided, I'm having the same issue.

My vendor chunk is about 800KB. I tried the solutions suggested, in the first case vendor2 is a few bytes, in the second case app and vendor are bigger, as it happened to @BruceHem.

@pi0 If I run analyze the interface doesn't show the vendor2 chunk, all the node_modules I associated to it seems to be still under the vendor chunk.

Update
@pi0 I managed to get the vendor2 chunk in the -analyze view, by implementing the example of @clarkdo, however I see that the node modules of vendor2 are duplicated in app.0302932039032.js chunk.


    extend (config, { isClient }) {
      if (isClient) {
        const { vendor } = config.entry
        const vendor2 = ['adyen-cse-js', 'vuelidate', 'elliptic', 'bn.js']
        config.entry.vendor = vendor.filter(v => !vendor2.includes(v))
        config.entry.vendor2 = vendor2
        const plugin = config.plugins.find((plugin) => ~plugin.chunkNames.indexOf('vendor'))
        const old = plugin.minChunks
        plugin.minChunks = function (module, count) {
          return old(module, count) && !(/(adyen-cse-js)|(vuelidate)|(elliptic)|(bn\.js)/).test(module.context)
        }
      }
    },
    filenames: {
      app: '[name].[chunkhash].js'
    },
    vendor: [
      'vuelidate',
      'adyen-cse-js'
    ]

@pi0 image below for reference.

screen shot 2018-01-17 at 17 43 01

Trello card created (https://trello.com/c/5bL1gNbg/78-vendor-optimizations)

Thanks to the Nuxt.js Team, you are doing an awesome work!

@pi0 nice 🖖

This definitely needs work. I have less than 10 pages and my vendor.js is 200kb.
app.jsis around 50 kb.

I don't feel like I have written so much though.

Good news: With Webpack 4 vendor will be automatically split into smaller chunks for both perf and long-term caching. We are going to work on it.

I'm working on an PR about that (webpack 3)

@pi0 @clarkdo
my proposal: https://github.com/nuxt/nuxt.js/pull/2687

Updates on this? Vendor bundle is still huge.

@ALL any update? My vendor is 1.75MB I want to split it :( I don't know how though..

This is part of my nuxt.config.js

build: {
    babel: {
      plugins: [
        ["transform-imports", {
          "vuetify": {
            "transform": "vuetify/es5/components/${member}",
            "preventFullImport": true
          }
        }]
      ]
    },
    // cssSourceMap: false, // add this into the nuxt.config
    extend (config) {
      config.devtool = false
    },
    vendor: [
      // '~/plugins/vuetify.js',
      // '~/plugins/vee-validate.js',
      'firebase'
    ],
    optimization: {
      splitChunks: {
        chunks: 'all',
        automaticNameDelimiter: '.',
        name: true,
        cacheGroups: {},
        minSize: 100000,
        maxSize: 100000
      }
    },
    maxChunkSize: 100000,
    extractCSS: true,
    /*
    ** Run ESLint on save
    */
    extend (config, ctx) {
      if (ctx.isDev && ctx.isClient) {
        config.module.rules.push({
          enforce: 'pre',
          test: /\.(js|vue)$/,
          loader: 'eslint-loader',
          exclude: /(node_modules)/
        })
      }
      if (ctx.isServer) {
        config.externals = [
          nodeExternals({
            whitelist: [/^vuetify/]
          })
        ]
      }
    }
  }

@besnikh vendor has been deprecated due to webpack4 has used SplitChunksPlugin to automatically generate common chunks.

The reason may be because your config doesn't meet default conditions of the strategy, try to change maxAsyncRequests or maxInitialRequests or provide a reproducible repo, but webpack default configurations should be the best practice and recommendation 😄 .

I just updated to nuxt-edge (and webpack 4), but I still get big bundle sizes:

WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
  5ee7cf173fbbbd29401e.js (1.19 MiB)

WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (1000 KiB). This can impact web performance.
Entrypoints:
  app (1.4 MiB)
      1d2359df0b3a4c1ac2bc.js
      5ee7cf173fbbbd29401e.js
      a51c2c1bcf724420734d.js

Is there anything that needs to be changed / configured?

My nuxt.config.js does not have changed any build settings.

there's no vendor any more?

where to config vendors.app ?

yarn build
yarn run v1.9.4
$ NODE_ENV=production nuxt build
[15:14:22] Building project
[15:14:22] Builder initialized
[15:14:22] Nuxt files generated
undefined
undefined
[15:14:23] Compiling client
[15:14:35] Compiled client in 13s

Hash: 9c140484c85ee4351c71
Version: webpack 4.17.1
Time: 12716ms
Built at: 2018-08-30 15:14:35
                  Asset       Size  Chunks                    Chunk Names
a8fb3b858aa32b7162be.js    215 KiB       0  [emitted]         app
0ab00c424448a26b6ae7.js  556 bytes       1  [emitted]         pages/index
1f1e22a52a1f27462980.js    133 KiB       2  [emitted]         commons.app
94284cfffbf18ce8aa7e.js    378 KiB       3  [emitted]  [big]  vendors.app
               LICENSES   76.1 KiB          [emitted]
 + 3 hidden assets
Entrypoint app = 1f1e22a52a1f27462980.js 94284cfffbf18ce8aa7e.js a8fb3b858aa32b7162be.js

WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
  94284cfffbf18ce8aa7e.js (378 KiB)
[15:14:35] Compiling server
Webpack Bundle Analyzer saved report to /Users/willin/Desktop/nuxt-edge-split-vendors/.nuxt/stats/client.html
[15:14:43] Compiled server in 8s

Hash: d246aef4a1691711c8dc
Version: webpack 4.17.1
Time: 7700ms
Built at: 2018-08-30 15:14:43
             Asset     Size  Chunks             Chunk Names
server-bundle.json  605 KiB          [emitted]
Entrypoint app = server-bundle.js server-bundle.js.map
Webpack Bundle Analyzer saved stats file to /Users/willin/Desktop/nuxt-edge-split-vendors/.nuxt/stats/client.json
✨  Done in 23.45s.

You should reopen this issues, since Nuxt 2 have no vendor and I have the same warning, that I can't solve. How to split big package into separate file?

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

config.entry is undefined

FYI

Comment of big vendors.app.js question: https://github.com/nuxt/nuxt.js/issues/5545#issuecomment-484577422

for me it was just enough to reduce chunk sizes not more than 50 Kib, so I hack it like so:

    extend (config, ctx) {
      if (ctx && ctx.isClient) {
        config.optimization.splitChunks.maxSize = 51200
      }
    }

this is my output logs on npm run generate command:

Hash: 55f650db95c0aedbeaab
Version: webpack 4.41.4
Time: 19182ms
Built at: 12/19/2019 8:28:56 PM
                          Asset       Size  Chunks                         Chunk Names
 ../server/client.manifest.json     15 KiB          [emitted]              
        0cde51ddddffebfe69e4.js   26.1 KiB       5  [emitted] [immutable]  commons.app.5bec50a0
        156f5330576e65671f1d.js   22.9 KiB       1  [emitted] [immutable]  app.f69643ec
        160cec1d41e28590bf6e.js    226 KiB      18  [emitted] [immutable]  vendors.app.a2a2526c
        238517e577d836f5c0d0.js   64.4 KiB       8  [emitted] [immutable]  commons.app.aaac3122
        376425dd0a427b29f483.js   15.8 KiB      17  [emitted] [immutable]  vendors.app.78934547
        3a8b86e990c2c8a1a949.js   25.8 KiB      19  [emitted] [immutable]  vendors.app.c1e9ae2e
        423a295fbea8fa5666ec.js   13.1 KiB       9  [emitted] [immutable]  commons.app.d939e436
        4f7286dd41f72a49b6e5.js   14.3 KiB       3  [emitted] [immutable]  commons.app.253ae210
        5165ef6d7ba2a603815b.js   14.7 KiB       2  [emitted] [immutable]  commons.app.0605657e
        5cf237a5a2cd21c7b478.js   28.6 KiB      16  [emitted] [immutable]  vendors.app.74e9f0c9
        603f0a39e70c50006343.js   16.4 KiB      14  [emitted] [immutable]  vendors.app.1655f327
        6d3100c4946db9800ced.js   9.48 KiB      20  [emitted] [immutable]  vendors.app.c964cbd5
        7559d7be9c8cb40cba33.js   15.5 KiB      21  [emitted] [immutable]  vendors.app.ce053847
                       LICENSES  571 bytes          [emitted]              
        a3e7a86e0cfea400b019.js   15.1 KiB      22  [emitted] [immutable]  vendors.app.d939e436
        a4df04ec317d52b2f100.js   2.18 KiB      11  [emitted] [immutable]  pages/index.31ecd969
        a57aa1fcf1c9dfeb2548.js   20.7 KiB       0  [emitted] [immutable]  app.24120820
        c3fa29ab46b642fc22be.js   38.2 KiB      15  [emitted] [immutable]  vendors.app.24f645c1
        d4d4e98c0163682fe1cc.js   10.3 KiB      10  [emitted] [immutable]  commons.app.fdc6512a
        d736b41f2151ef8b55c2.js   8.89 KiB       7  [emitted] [immutable]  commons.app.678f84af
        d95f06092007a91d3ea0.js   15.8 KiB       4  [emitted] [immutable]  commons.app.2a42e354
        e46d9b1a3cf3197879a8.js   28.5 KiB      13  [emitted] [immutable]  vendors.app.11c2601a
        feb4891a9784216e4451.js   13.8 KiB       6  [emitted] [immutable]  commons.app.5c956a7a
runtime.8300a73d8568ed857bdb.js   2.31 KiB      12  [emitted] [immutable]  runtime
 + 2 hidden assets
Entrypoint app = runtime.8300a73d8568ed857bdb.js 4f7286dd41f72a49b6e5.js d95f06092007a91d3ea0.js
423a295fbea8fa5666ec.js feb4891a9784216e4451.js d736b41f2151ef8b55c2.js d4d4e98c0163682fe1cc.js
5165ef6d7ba2a603815b.js 0cde51ddddffebfe69e4.js 238517e577d836f5c0d0.js a3e7a86e0cfea400b019.js
376425dd0a427b29f483.js 603f0a39e70c50006343.js 5cf237a5a2cd21c7b478.js 7559d7be9c8cb40cba33.js
3a8b86e990c2c8a1a949.js 6d3100c4946db9800ced.js e46d9b1a3cf3197879a8.js c3fa29ab46b642fc22be.js
160cec1d41e28590bf6e.js a57aa1fcf1c9dfeb2548.js 156f5330576e65671f1d.js

Hash: e8905e5151dbbb6711f0
Version: webpack 4.41.4
Time: 12291ms
Built at: 12/19/2019 8:29:08 PM
                  Asset       Size  Chunks                         Chunk Names
8495f3a3db1592ed83bc.js   1.63 KiB       1  [emitted] [immutable]  pages/index
              server.js    410 KiB       0  [emitted]              app
   server.manifest.json  145 bytes          [emitted]              
Entrypoint app = server.js
ℹ Generating pages                                                                                                                                                                20:29:09
✔ Generated /                                           

Regards,
Maksim

@daggerok How about the entry point too big? Your solution worked though. But I dont know what is entry point?

@mandaputtra
entry point also will be reduce by chunks size. just try configure like i did and see what will happen

@daggerok
Okay I'm understand, the entry point is where you firstload the app. Thanks your solution worked, I just need to found what the best config.optimization.splitChunks.maxSize for me.

@daggerok solution is working awesome
you can change maxSize property in optimization.splitChunks,maxSize too.

export default {
build: {
    extractCSS: true,
    optimization :{
      splitChunks: {
        chunks: 'all',
        automaticNameDelimiter: '.',
        name: 'test',
        maxSize : 256000
      }
    }
  },
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

bimohxh picture bimohxh  Â·  3Comments

vadimsg picture vadimsg  Â·  3Comments

vadimsg picture vadimsg  Â·  3Comments

surmon-china picture surmon-china  Â·  3Comments

VincentLoy picture VincentLoy  Â·  3Comments