laravel-enso / enso

Laravel Vue SPA, Bulma themed. For demo login use `admin@laravel-enso.com` & `password` -
https://www.laravel-enso.com
MIT License
1.08k stars 277 forks source link

vue.config.js chunks configuration #381

Closed robbykrlos closed 3 years ago

robbykrlos commented 3 years ago

This is a question.

Prerequisites

Description

I have a question regarding the js/chunks generated by enso's default configuration: JS files generated on our side are 138. We do not use (require) other yarn packages except fontawesome-pro.

I see that on your demo site (https://www.laravel-enso.com/) there are ~58 chunks loaded inside index file.

Is there different configuration used for this demo site, compared to laravel-enso/enso?

I tried playing around with configureWebpack optimization.splitChunks but had no result comparing to https://www.laravel-enso.com/. I also thought maybe my yarn is messy and started fresh with no yarn.lock file, and no node_modules, but still no improvement.

Any ideas/suggestions you have are recommended.

robbykrlos commented 3 years ago

An interesting read about Js speed optimization - https://www.diva-portal.org/smash/get/diva2:1318692/FULLTEXT01.pdf

robbykrlos commented 3 years ago

Difference:

https://www.laravel-enso.com/ image

Local image

robbykrlos commented 3 years ago

I found the reasons why this happens. I'll document this here later.

aocneanu commented 3 years ago

@robbykrlos thanks!

robbykrlos commented 3 years ago

The reason why I had so many files, was because on top of node_modules there were the internal (local, custom made in client\src\js) vue/js files that generated chunks. many of them, very small ones.

Even more important I think is that by default (client/vue.config.js - configureWebpack settings) chunks are generated unoptimized or even with redundant content. I'm saying this because I find that without any changes to the configureWebpack I have these many files: 146 chunk files - observe the size - very similar, right?:

2021-03-26  13:07    <DIR>          .
2021-03-26  13:07    <DIR>          ..
2021-03-26  13:07            90,002 chunk-0259ebe7.96aa39e3.js
2021-03-26  13:07         1,371,872 chunk-04bb69af.92ec25d8.js
2021-03-26  13:07         1,371,575 chunk-054531f7.60ce2406.js
2021-03-26  13:07         1,371,575 chunk-094b81ee.35f525d3.js
2021-03-26  13:07         1,371,461 chunk-0959f959.5e642a7c.js
2021-03-26  13:07         1,379,194 chunk-0b48e1bf.b2ba8f84.js
2021-03-26  13:07             6,832 chunk-0c5d9a40.202d9631.js
2021-03-26  13:07             1,749 chunk-0d1476e3.43387adb.js
2021-03-26  13:07            33,784 chunk-0d92b433.e9be77f7.js
2021-03-26  13:07         1,371,575 chunk-10af28ed.04ddf17e.js
2021-03-26  13:07            33,159 chunk-110c5aa2.a5ed28e4.js
2021-03-26  13:07             7,031 chunk-13c8efd2.3065f54e.js
2021-03-26  13:07             7,298 chunk-13cb3914.948e9b0c.js
2021-03-26  13:07             7,555 chunk-13f1f400.814a565b.js
2021-03-26  13:07             7,219 chunk-13f3b27a.be175011.js
2021-03-26  13:07             7,032 chunk-13f44214.2ba2b9a0.js
2021-03-26  13:07             7,214 chunk-13f5b158.37884cc1.js
2021-03-26  13:07             7,037 chunk-13f77016.0c84238a.js
2021-03-26  13:07         1,376,985 chunk-147fa46b.30a2ee31.js
2021-03-26  13:07         1,371,575 chunk-1a21cab5.91b9f914.js
2021-03-26  13:07         1,371,464 chunk-1a42f0d5.69feaad8.js
2021-03-26  13:07           820,413 chunk-1b5830d8.ce60e005.js
2021-03-26  13:07         1,371,460 chunk-1c004b7a.340d9f6c.js
2021-03-26  13:07            33,153 chunk-2011f281.096695e3.js
2021-03-26  13:07            43,096 chunk-2059b3bc.f3381682.js
2021-03-26  13:07         1,371,575 chunk-20d3c4e8.ff3d9880.js
2021-03-26  13:07         1,371,577 chunk-22bc9121.bbde567d.js
2021-03-26  13:07         1,371,460 chunk-23805c81.6d8376ff.js
2021-03-26  13:07           227,866 chunk-2509f14e.d8eda39a.js
2021-03-26  13:07             7,529 chunk-252dba4c.c8e792f4.js
2021-03-26  13:07         1,371,462 chunk-256360e8.cb36715b.js
2021-03-26  13:07         1,371,575 chunk-27dd4ba4.5101e742.js
2021-03-26  13:07         1,371,577 chunk-2a88a8e2.695be01e.js
2021-03-26  13:07         1,371,575 chunk-2b11593d.049701b7.js
2021-03-26  13:07               789 chunk-2d0aa7a6.9dced15f.js
2021-03-26  13:07               805 chunk-2d0ae8a9.e3ad9870.js
2021-03-26  13:07               502 chunk-2d0b5f38.871cb197.js
2021-03-26  13:07               534 chunk-2d0ba2c9.7b55f99f.js
2021-03-26  13:07               536 chunk-2d0bd7e6.00eed7bd.js
2021-03-26  13:07               937 chunk-2d0bff22.c48643a4.js
2021-03-26  13:07               534 chunk-2d0c0df3.ba9ecb34.js
2021-03-26  13:07               806 chunk-2d0c4d88.18bef473.js
2021-03-26  13:07               534 chunk-2d0c89f9.fe0d8db4.js
2021-03-26  13:07               800 chunk-2d0cbe18.f1d9df40.js
2021-03-26  13:07               817 chunk-2d0cf299.6edd4106.js
2021-03-26  13:07               536 chunk-2d0cf4c0.3ee29359.js
2021-03-26  13:07               846 chunk-2d0cf639.21c3971c.js
2021-03-26  13:07               798 chunk-2d0cfc24.f15fb92a.js
2021-03-26  13:07               787 chunk-2d0d0429.b06a10cf.js
2021-03-26  13:07               797 chunk-2d0d0958.d55d6b96.js
2021-03-26  13:07               797 chunk-2d0d6e94.14d44029.js
2021-03-26  13:07               858 chunk-2d0d7c68.38723ef9.js
2021-03-26  13:07             1,668 chunk-2d0e4e61.778e65fe.js
2021-03-26  13:07               804 chunk-2d0e8801.b92ec247.js
2021-03-26  13:07               526 chunk-2d0e9ba0.4e6fbff8.js
2021-03-26  13:07               785 chunk-2d0f043c.dd0e9db3.js
2021-03-26  13:07             2,784 chunk-2d207423.778e5e64.js
2021-03-26  13:07               795 chunk-2d208c2b.6ab7cbc2.js
2021-03-26  13:07               785 chunk-2d208feb.e9b3a2d7.js
2021-03-26  13:07             1,677 chunk-2d20f6f8.91b00be0.js
2021-03-26  13:07               823 chunk-2d213544.143f4867.js
2021-03-26  13:07               532 chunk-2d216436.4b948fb9.js
2021-03-26  13:07               522 chunk-2d2183e2.26d454d8.js
2021-03-26  13:07               534 chunk-2d21b0dc.4a80bf83.js
2021-03-26  13:07               784 chunk-2d221b76.fa83ffac.js
2021-03-26  13:07               795 chunk-2d2221c5.5d03aa63.js
2021-03-26  13:07               878 chunk-2d225c6f.aec716bb.js
2021-03-26  13:07               839 chunk-2d229484.117781a1.js
2021-03-26  13:07               874 chunk-2d22cb00.1450ac25.js
2021-03-26  13:07         1,389,415 chunk-2da8eb1a.5903633e.js
2021-03-26  13:07         1,371,577 chunk-2e0d25e5.a4a95ac1.js
2021-03-26  13:07         1,372,767 chunk-2ee34aa7.e6345b28.js
2021-03-26  13:07            69,273 chunk-2f129568.cf0a7b25.js
2021-03-26  13:07         1,371,575 chunk-3080b576.76a78a7a.js
2021-03-26  13:07         1,372,291 chunk-31375a2f.491f6e72.js
2021-03-26  13:07         1,371,573 chunk-33a40f63.58a615ef.js
2021-03-26  13:07         1,371,577 chunk-351e9410.5b5d0442.js
2021-03-26  13:07         1,371,575 chunk-3a0362d5.44572cd9.js
2021-03-26  13:07         1,455,774 chunk-3a3ea798.7da72d82.js
2021-03-26  13:07            34,000 chunk-3b839027.0b9b136f.js
2021-03-26  13:07            33,153 chunk-3d9ac031.f6094947.js
2021-03-26  13:07         1,373,826 chunk-41708a59.9936cb6c.js
2021-03-26  13:07             7,386 chunk-41738ad6.72686202.js
2021-03-26  13:07            33,163 chunk-429eaf3f.478573c1.js
2021-03-26  13:07         1,371,575 chunk-44929078.3f9e9578.js
2021-03-26  13:07         1,374,545 chunk-45638c94.e70b6890.js
2021-03-26  13:07             8,569 chunk-45d53202.831a5969.js
2021-03-26  13:07            33,165 chunk-46018374.bd829019.js
2021-03-26  13:07             1,200 chunk-4e80b0a1.66b1c96c.js
2021-03-26  13:07         1,381,032 chunk-511c19cd.fe376960.js
2021-03-26  13:07         1,371,573 chunk-527b2bb0.56fd2f19.js
2021-03-26  13:07             1,068 chunk-54a0b22d.f11d845e.js
2021-03-26  13:07         1,377,013 chunk-54c4dcd9.8346ef4d.js
2021-03-26  13:07         1,373,847 chunk-5604dcb1.1d93637a.js
2021-03-26  13:07             1,218 chunk-5710d3f7.d4971130.js
2021-03-26  13:07         1,371,575 chunk-590b9e76.d34a6548.js
2021-03-26  13:07             8,601 chunk-5a8d47cd.b50851f9.js
2021-03-26  13:07           690,603 chunk-5beb5cbb.e0dc9044.js
2021-03-26  13:07           124,268 chunk-5fccbdfa.d3b2033f.js
2021-03-26  13:07         1,371,577 chunk-6277514d.3cd78185.js
2021-03-26  13:07         1,371,575 chunk-62c2df33.4eaee2d2.js
2021-03-26  13:07         1,371,575 chunk-63ba7302.d78fccf4.js
2021-03-26  13:07             3,942 chunk-66c6f69e.bef66789.js
2021-03-26  13:07         1,371,466 chunk-6933ae7b.0afbb599.js
2021-03-26  13:07             4,178 chunk-6a6ef7be.d155eb3e.js
2021-03-26  13:07             5,791 chunk-6b1b6b1b.42971b26.js
2021-03-26  13:07            53,114 chunk-6b5af944.0706f9eb.js
2021-03-26  13:07            31,474 chunk-6bca86b8.6bb7b78f.js
2021-03-26  13:07         1,371,459 chunk-6dd92d16.4b7ceb03.js
2021-03-26  13:07         1,413,801 chunk-6f52fcba.03d1746e.js
2021-03-26  13:07         1,377,287 chunk-71841591.532c35b6.js
2021-03-26  13:07            33,157 chunk-71abb77b.e520e839.js
2021-03-26  13:07         1,371,460 chunk-775419f2.4004bba9.js
2021-03-26  13:07         1,371,575 chunk-796805a4.66c16f3d.js
2021-03-26  13:07         1,372,425 chunk-7a53584c.1ab02320.js
2021-03-26  13:07         1,372,538 chunk-7bdfba1c.2ab16478.js
2021-03-26  13:07         1,371,575 chunk-7db1c3d6.796e2941.js
2021-03-26  13:07         1,371,575 chunk-7df7e912.822bea4b.js
2021-03-26  13:07             1,715 chunk-7e121050.06be2a6f.js
2021-03-26  13:07         1,376,723 chunk-7f3f7f20.f52c4c2b.js
2021-03-26  13:07         1,371,575 chunk-7fa0e0c0.85bf7ac1.js
2021-03-26  13:07             2,350 chunk-85c807cc.c8ec6323.js
2021-03-26  13:07         1,371,459 chunk-85cc487c.69e9fe67.js
2021-03-26  13:07         1,371,575 chunk-88a257ec.7af8dea1.js
2021-03-26  13:07         1,371,577 chunk-95e4c5be.0a74e5f0.js
2021-03-26  13:07         1,376,731 chunk-974f895c.cadcec06.js
2021-03-26  13:07            29,185 chunk-a0526618.ccc76e26.js
2021-03-26  13:07            32,835 chunk-a9c69782.c6e62cb2.js
2021-03-26  13:07         1,371,464 chunk-ab1bfdfc.d37078f7.js
2021-03-26  13:07            15,352 chunk-ad2a579c.98e28c55.js
2021-03-26  13:07         1,371,573 chunk-aeff3558.a67ae6be.js
2021-03-26  13:07         1,371,460 chunk-bbc60ef0.8a41e173.js
2021-03-26  13:07             8,512 chunk-c218b6de.d5eebedf.js
2021-03-26  13:07            44,634 chunk-c5167d64.6c312864.js
2021-03-26  13:07           273,059 chunk-c700555e.2e6a572e.js
2021-03-26  13:07         1,371,575 chunk-cca0fc48.e7b61a93.js
2021-03-26  13:07         1,371,575 chunk-d0588888.e2af7924.js
2021-03-26  13:07            21,558 chunk-d9cfb194.a9eea9c6.js
2021-03-26  13:07         1,406,494 chunk-de1d6dae.cdee8784.js
2021-03-26  13:07            33,655 chunk-e10187b4.78fef38e.js
2021-03-26  13:07         2,256,550 chunk-e3666cfa.e866fa3d.js
2021-03-26  13:07             3,648 chunk-e7d58be8.2c7877b0.js
2021-03-26  13:07            30,269 chunk-eb560028.1d846fe5.js
2021-03-26  13:07         1,380,212 chunk-f19b85e0.453cbd3e.js
2021-03-26  13:07         3,970,438 chunk-vendors.69cab464.js
2021-03-26  13:07            64,686 main.b711eb4a.js

and here is a compare between 2 of them with similar size:

image NOTE: that 99% of the file is the same - just 4 lines are different.

This, made in the end load 25MB for login page, and nothing was rendered until all chunks were loaded. Chrome Lighthouse gave a score of 60% for Login page loading.

This on a test environment that had 2 CPU cores and 4GB RAM running Apache was a bit overwhelming and had a delay loading all this parallel requests.

My solution was to optimize chunks and merge some together.

Ex: client/vue.config.js

configureWebpack: {
        devtool: inProduction ? 'hidden-source-map' : 'source-map',
        optimization: {
            nodeEnv: 'production',
            splitChunks: {
                cacheGroups: {
                    vendor: {
                        test: /[\\/]node_modules[\\/]/,
                        name(module) {
                            // get the name. E.g. node_modules/packageName/not/this/part.js
                            // or node_modules/packageName
                            const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];

                            // npm package names are URL-safe, but some servers don't like @ symbols
                            return `vendor.${packageName.replace('@', '')}`;
                        },
                    },  
                  ...

Which in my case generated slightly bigger chunks (in size), but reduced the number of chunks therefore reducing the number or requests, which made the loading faster.

I also did the same with local files, which can be easily merged into one small file.

Ex: client/vue.config.js - below vendor cacheGroup

local: {
    test: /[\\/]src[\\/]js[\\/]/,
    name(module) {
        // get the name. E.g. src/js/packageName/not/this/part.js
        // or src/js/packageName
        const packageName = module.context.match(/[\\/]src[\\/]js[\\/](.*?)([\\/])/);
        // npm package names are URL-safe, but some servers don't like @ symbols
        return (packageName && packageName[1])
            ? `local.${packageName[1].replace('@', '')}`
            : module;
    },
},

My latest tests generated ~30 files, instead of 140.

Later I tried to play around a bit with preload and prefetch and ended up disabling them for best performance (in my case, on my env): Ex: client/vue.config.js

chainWebpack: config => {
   config.plugins.delete('preload-main');
   config.plugins.delete('prefetch-main');
   ...

Note: plugin names may be different and can be found by running vue inspect --plugins

But I plan that later, I only remove the preload/prefetch on some chunks like this: Ex: client/vue.config.js

chainWebpack: config => {
   config.plugin('prefetch').tap(options => {
        options[0].fileBlacklist = options[0].fileBlacklist || [];
        options[0].fileBlacklist.push(/vendor(.)+?\.js$/);
        return options;
        })
   ...

Finally I got

From:

image

To:

image

And this was my local dev. machine which is quite fast. Things escalate on slower systems with slower network where 25MB can take up to ~30-60 seconds to load.

robbykrlos commented 3 years ago

Bonus:

We also found that chunk files were not cached (browser cache). This was because, on Apache, mod_deflate.so is interfering with the ETag and generates a bug which makes the JS files flagged as "changed" and won't let the browser see it as "no-change"

Here is the Apache issue : https://bz.apache.org/bugzilla/show_bug.cgi?id=45023#c22

Here is the workaround on top of mod_deflate:

          #This fixes some Apache issues and was recommended in several posts.
          FileETag MTime Size

          #THIS IS THE FIX 
          RequestHeader edit "If-None-Match" '^"((.*)-gzip)"$' '"$1", "$2"'

          AddOutputFilterByType DEFLATE text/plain
      AddOutputFilterByType DEFLATE text/html
      AddOutputFilterByType DEFLATE text/xml
      AddOutputFilterByType DEFLATE text/css
      AddOutputFilterByType DEFLATE application/xml
      AddOutputFilterByType DEFLATE application/xhtml+xml
      AddOutputFilterByType DEFLATE application/rss+xml
      AddOutputFilterByType DEFLATE application/javascript
      AddOutputFilterByType DEFLATE application/x-javascript

          BrowserMatch ^Mozilla/4 gzip-only-text/html
          BrowserMatch ^Mozilla/4\.[0678] no-gzip
          BrowserMatch \bMSIE\s(7|8)  !no-gzip !gzip-only-text/html

          Header set Vary Accept-Encoding

The difference can be seen if you refresh (soft-refresh, not hard) the login page. Initially all js files will be loaded with a 200 OK status.

Second refresh, it will load faster, because

200 OK (from disk cache)
or
200 OK (from memory cache)