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

Scripts set in manualChunks are loaded directly in front page, instead to be lazy loaded when needed #5189

Open
7 tasks done
a-tonchev opened this issue Oct 4, 2021 · 28 comments

Comments

@a-tonchev
Copy link

Describe the bug

To manage well the bundle, I am setting the packages into manualChunks e.g.:

The package fabric is used only in the admin area of my app, that is why I don't need it to be loaded directly in the front page.

If I don't set it in manualChunks, it works good and it will not be loaded in the front page, but my chunks then are too large, because vite place it automatically together with others in a huge backend chunk. Then as soon I open the backend it lazy loads all the other chunks, including the one that contains fabric. So this is the expected behavior.

If I set it in manualChunks, e.g.:

    rollupOptions: {
      output: {
        manualChunks: {
          fabric: ['fabric'],
        }
     }
   }

the fabric chunk is loaded directly on the front page. Even if I am not admin.

You can see the differences when I include fabric or not:

Not included in manualChunks
image

Included in manualChunks:
image

Expected behavior is: fabric should only be loaded when really used, else it creates only network traffic and lowers the Lighthouse score because of unused code!

NOTE: I am using an example with fabric here, but in my project I have a bunch of other libraries that have the same issue with manualChunks.

Reproduction

I created a small reproduction in this repo:

https://github.com/a-tonchev/react-boilerplate/tree/vite_no_lazy_load

Steps to reproduce:

  1. Install deps (yarn)

Try bug:

  1. yarn build && yarn serve
  2. Open localhost:4000 and see in Network -> JS, the fabric script is loaded

To try without, open vite.config.js:
https://github.com/a-tonchev/react-boilerplate/blob/vite_no_lazy_load/vite.config.js

and comment out line 40

  1. yarn build && yarn serve
  2. Open localhost:4000 and see in Network -> JS, the fabric script is no more loaded,

System Info

Windows 10 + WSL (Ubuntu)

Vite version "^2.3.8"

Used Package Manager

yarn

Logs

No response

Validations

@a-tonchev a-tonchev changed the title manualChunks loads scripts defined directly, instead of lazy loading Scripts set in manualChunks are loaded directly in front page, instead to be lazy loaded when needed Oct 4, 2021
@0biWanKenobi
Copy link

I can confirm that this issue occurs. Also, it seems that even dependencies I've never imported are passed to manualChunks, raising the chunks size.

@a-tonchev
Copy link
Author

a-tonchev commented Nov 23, 2021

On the other hand, it is good to have the option to decide which chunks should be loaded immediately, because thus we will avoid the waterfall-effect on chunks that are always needed. The <link preload is not always working like expected and is more difficult to maintain, that is why this rule would be quite nice improvement of the loading times.

I suggest to have either two rules manualChunks + preloadChunks or just to put this option in the manualChunks e.g. { chunkUrl, preload: true }

@TrickyPi
Copy link
Contributor

TrickyPi commented Jan 5, 2022

I have some confusion about this issue, i use build.rollupOptions.output.manualChunks and import() in other project. Finally, i didn't find this issue. And, the reproducible repo isn't simple.

@tomascubeek
Copy link

Is something happening with this issue? @TrickyPi if you are using it without any issue in other projects, can you show us your example? Are you sure those manual chunks are really lazy-loaded? ... because this really does not work as expected. Once you start using manualChunks, lazy-routes are not lazy-loaded at all, they load together with index (first page) - utilizing the last version of vite and vue-router.

@nicooprat
Copy link

I can confirm this too in our Vue app. We didn't have the issue before migrating from Webpack, using /* webpackChunkName: "foo" */ feature. We tried to mimic that, but for now it's counter productive. (we're using vite 2.8.6).

@a-tonchev
Copy link
Author

Yes the issue is still there and since it is build issue, I can not just make a code-sandbox example.

The repository I mentioned in my first post shows clearly the problem.

@TrickyPi
Copy link
Contributor

TrickyPi commented Apr 5, 2022

I created a minimal repo, and it works.

step

  1. git clone -b vite-issue-5189-temp https://github.com/TrickyPi/issue-repo
  2. see reproduce.md.

@bluwy
Copy link
Member

bluwy commented Apr 5, 2022

I think this should be fixed now in Vite 2.9 (changelog). Would appreciate if y'all can verify this, and whether this can be closed.

@TrickyPi
Copy link
Contributor

TrickyPi commented Apr 5, 2022

I think this "issue" is unrelated to the Vite's default chunking strategy.

@nicooprat
Copy link

No change with Vite 2.9.1 unfortunately, all chunks are still loaded via <link rel="modulepreload" href="xxx"> tags in <head>.

@CaptainLiao
Copy link

I use your reproduction and add the plugin vite-plugin-webpackchunkname, that resolve the issue.

your repo vite.config.js:

import {manualChunksPlugin} from 'vite-plugin-webpackchunkname'

export default defineConfig({
  plugins: [
    ....
    manualChunksPlugin(),
  ],
})

@jesuismaxime
Copy link

Any fix in view (from Vite - no extra packages solution please!)?

@exodusanto
Copy link

exodusanto commented Aug 29, 2022

Same edge-case:
I need to chuck opencv and lazy load only at some point, with this preload feature always enable an user 'll download 2.5MB gzip at app bootstrap, in background yes but it's 2.5MB

@booellean
Copy link

I've been banging my head against the wall with this error. It appears that returning void like the documentation shows is causing the error. When returning void, Vite will chunk synchronous modules with asynchronous modules, causing the chunk to be preloaded. If you return a default value to catch everything else, then Vite will not do this. Thankfully, that default return value will still pass over asynchronous components you define with defineAsyncComponent, but it will catch everything else, possibly causing large builds. There may be a work around, I'm still playing with a solution.

I also finally found a workaround that allows for custom chunk names similar to webpack's magic comments. I developed this because the plugin vite-plugin-webpackchunkname was throwing errors. Please note the last line and comment of the example

  manualChunks: (id) => {

      // This is how I do dynamic chunk naming.
      // Example uses:
      // import("some/module/index?chunkName=my-custom-chunk-name")
      // import MyComponent from "some/component.vue?chunkName=restricted_path/my-custom-chunk-name"
      if(id.includes("?chunkName=") || id.includes("&chunkName=")){
          let name = id.match(/(?<=chunkName=)(.*)(?=&)|(?<=chunkName=)(.*)/gm)
          if(name[0]) return name[0];
      }

      // Vendor Chunks
      if(id.includes('node_modules')) return 'vendor';

      // Here's the odd fix. You cannot return void, it must return a string
      return "index";
  },

I'm still cleaning this up and will post updates as it develops.
Noteable issues:

  1. Typescript is throwing errors with the query in the url string. It's possible that Javascript will too.
  2. Chunking does not work if you are importing from a generic package in node_modules. You must import a file.
    Does not work: "node_module_package_name?chunkName=package"
    Does work: "node_module_package_name/index?chunkName=package"

@pfdgithub
Copy link

pfdgithub commented Aug 22, 2023

Ignore modulepreload <link rel="modulepreload" href="xxx">

https://github.com/vitejs/vite/blob/main/docs/config/build-options.md#buildmodulepreload

{
  build: {
    modulePreload: {
      resolveDependencies: (url, deps, context) => {
        return [];
      }
    }
  }
}

Ignore type error Cannot find module 'xxx' or its corresponding type declarations.ts(2307)

https://www.typescriptlang.org/docs/handbook/modules.html#wildcard-module-declarations
microsoft/TypeScript#38638

Do not use the & character, otherwise the development mode will throw error:
TypeError: Failed to fetch dynamically imported module: http://localhost:5173/src/module/index.tsx?chunkName=name&

// e.g. import("./module?chunkName=name#")
declare module "*#" {
  const value: any;
  export = value;
}

Grouping Components in the Same Chunk

849e845
https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/splitVendorChunk.ts#L114

{
  build: {
    rollupOptions: {
      output: {
        sourcemapExcludeSources: true,
        manualChunks:(id) => {
          const url = new URL(id, import.meta.url);
          const chunkName = url.searchParams.get("chunkName");
          if (chunkName) {
            return chunkName;
          }
          // return void will invoke the built-in `viteManualChunks`
        }
      }
    }
  },
  plugins: [
    splitVendorChunkPlugin()
  ],
}

@huseyindeniz
Copy link

Hi everyone, I experienced the same problem and thanks to @pfdgithub , the following update solved the issue. Both build size and Lighthouse score ok now.

{
  build: {
    modulePreload: {
      resolveDependencies: (url, deps, context) => {
        return [];
      }
    },
    rollupOptions: {
      output: {
        sourcemap: false,
        manualChunks: {
          ethers: ['ethers'],
          router: ['react-router-dom'],
          rtk: ['@reduxjs/toolkit'],
          redux: ['react-redux'],
          chakra: ['@chakra-ui/react'],
        },
      },
    },    
  }
}

@sabbirrahman
Copy link

sabbirrahman commented Dec 24, 2023

I created a minimal repo, and it works.

step

  1. git clone -b vite-issue-5189-temp https://github.com/TrickyPi/issue-repo
  2. see reproduce.md.

Hello @TrickyPi, I've cloned this repo and tried it. Yes, it works with Vite 2.9.1. But when I updated Vite to the latest 5.0.10, it was not working as expected anymore.

Edit: The issue exists from Vite 3.0.0, everything is good until 2.9.16, so something broke this while transitioning from Vite 2 to 3.

@magicyoda
Copy link

magicyoda commented Jan 11, 2024

@huseyindeniz I tried following :
(code formatting did not work?)

export default defineConfig({ optimizeDeps: { include: ["@vue/runtime-dom"], exclude: ["flowbite"], }, resolve: { alias: { vue: "@vue/runtime-dom", }, }, build: { modulePreload: { resolveDependencies: (url, deps, context) => { return []; }, }, rollupOptions: { output: { manualChunks(id) { if (id.includes("node_modules")) { return id .toString() .split("node_modules/")[1] .split("/")[0] .toString(); } }, }, }, },

I'm getting a chunk / module BUT, all chunks are loaded immediately on page load. They are not loaded when required, which results in a bad lighthouse score. What am I doing wrong? Thank you for your help.

@huseyindeniz
Copy link

hi @magicyoda did you add the following to your index.html file, if not, can you try

<script> window.global = window; </script>

@daniilgri
Copy link

Why is this issue still opened? I've just checked it in vite@5 and the issue is still there.

@patak-dev patak-dev removed the bug label Feb 10, 2024
@jessejamesrich
Copy link

This appears to be unresolved in the latest version of Vite as far as I can tell, and none of the above solutions seem to address it. All manual chunks are eagerly loaded which has catastrophic effects on performance.

@jbool24
Copy link

jbool24 commented Apr 2, 2024

BUMP!!

Anything going on here?? Related issues breaks vue-router dynamic imports. Cannot find module with dynamic imports that are loaded on direct navigation to a URL.

@alt1o
Copy link

alt1o commented Apr 8, 2024

Still.

@a-tonchev
Copy link
Author

Yes, that is the reason I don't use manualChunks since 2021, it kind a kill my website performance and it makes no sense to use them

@jiikoosol
Copy link

Any news on this one? It really should be fixed.

@jiikoosol
Copy link

Bump.

@jesuismaxime
Copy link

2 years later: bump!

Would be nice to have, at least, a feedback!

@sirtimid
Copy link

This is still happening. Any news to resolve it?

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

No branches or pull requests