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

Vendor is too big #2201

Closed
snoopy83101 opened this issue Nov 22, 2017 · 47 comments
Closed

Vendor is too big #2201

snoopy83101 opened this issue Nov 22, 2017 · 47 comments

Comments

@snoopy83101
Copy link

snoopy83101 commented Nov 22, 2017

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)
@clarkdo
Copy link
Member

clarkdo commented Nov 23, 2017

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

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

@snoopy83101
Copy link
Author

@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

@clarkdo
Copy link
Member

clarkdo commented Nov 23, 2017

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
      }
    }
  }
}

@karmazzin
Copy link

@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

@clarkdo
Copy link
Member

clarkdo commented Nov 24, 2017

@karmazzin
Do you change the filenames ?

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

@snoopy83101
Copy link
Author

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

@clarkdo
Copy link
Member

clarkdo commented Nov 24, 2017

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.

@snoopy83101
Copy link
Author

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?

@clarkdo
Copy link
Member

clarkdo commented Nov 24, 2017

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

@snoopy83101
Copy link
Author

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

@clarkdo clarkdo closed this as completed Nov 25, 2017
@chanlito
Copy link

chanlito commented Jan 16, 2018

@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

@clarkdo
Copy link
Member

clarkdo commented Jan 16, 2018

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

@chanlito
Copy link

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.

@clarkdo
Copy link
Member

clarkdo commented Jan 16, 2018

Could you provide your code ?

@chanlito
Copy link

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'
  ],
  ...
}

@clarkdo
Copy link
Member

clarkdo commented Jan 16, 2018

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)
        }
      }
    }

@chanlito
Copy link

@clarkdo doesn't seem to work.

@clarkdo
Copy link
Member

clarkdo commented Jan 16, 2018

Try 😄

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'
    ]
  }
}

@chanlito
Copy link

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

@clarkdo
Copy link
Member

clarkdo commented Jan 16, 2018

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

@chanlito
Copy link

chanlito commented Jan 16, 2018

Here's the output, after applying above code

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

app seems bigger now

@clarkdo
Copy link
Member

clarkdo commented Jan 16, 2018

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 webpack/webpack#4445 (comment)

@pi0
Copy link
Member

pi0 commented Jan 16, 2018

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

@clarkdo
Copy link
Member

clarkdo commented Jan 16, 2018

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'
    ]
  }
}

@francescobm
Copy link

francescobm commented Jan 16, 2018

@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'
    ]

@francescobm
Copy link

francescobm commented Jan 17, 2018

@pi0 image below for reference.

screen shot 2018-01-17 at 17 43 01

@pi0
Copy link
Member

pi0 commented Jan 18, 2018

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

@francescobm
Copy link

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

@chanlito
Copy link

@pi0 nice 🖖

@pxwee5
Copy link

pxwee5 commented Jan 25, 2018

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.

@pi0
Copy link
Member

pi0 commented Jan 25, 2018

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.

@NicoPennec
Copy link

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

@NicoPennec
Copy link

@pi0 @clarkdo
my proposal: #2687

@nikkwong
Copy link

Updates on this? Vendor bundle is still huge.

@besnikh
Copy link

besnikh commented Aug 27, 2018

@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/]
          })
        ]
      }
    }
  }

@clarkdo
Copy link
Member

clarkdo commented Aug 27, 2018

@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 😄 .

@P4sca1
Copy link
Contributor

P4sca1 commented Aug 29, 2018

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.

@willin
Copy link
Contributor

willin commented Aug 30, 2018

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.

@thariddler
Copy link

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?

@lock
Copy link

lock bot commented Nov 16, 2018

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.

@lock lock bot locked as resolved and limited conversation to collaborators Nov 16, 2018
@nuxt nuxt unlocked this conversation Apr 16, 2019
@cmzz
Copy link

cmzz commented Apr 18, 2019

config.entry is undefined

@clarkdo
Copy link
Member

clarkdo commented Apr 18, 2019

FYI

Comment of big vendors.app.js question: #5545 (comment)

@daggerok
Copy link

daggerok commented Dec 19, 2019

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

@mandaputtra
Copy link

mandaputtra commented Jan 1, 2020

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

@daggerok
Copy link

daggerok commented Jan 1, 2020

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

@mandaputtra
Copy link

@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.

@ryzexsp
Copy link

ryzexsp commented Apr 20, 2020

@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
      }
    }
  },
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests