[Fixed] "TypeError: Failed to fetch dynamically imported module" on Vue/Vite vanilla setup – Vite

Photo of author
Written By M Ibrahim
react-typescript vite vue.js webpack

Quick Fix: To resolve this error, disable the file hashing in Vite configuration by setting build.rollupOptions.output.chunkFileNames to '[name].js'. This ensures that chunk filenames are consistent and don’t change with code updates, preventing the error.

The Problem:

While deploying a Vue/Vite vanilla setup, users experience a strange TypeError: Failed to fetch dynamically imported module in the Sentry logs. The issue strangely correlates with each new deployment to the production environment, but not with the local development environment. It occurs only with deployed code and not with locally executed code. The issue persists with multiple dynamically imported components in the routing system, unlike similar React setups with SVGs, where the error was successfully resolved.

The Solutions:

Solution 1: Use named chunks to control hashing for dynamic imports

In your Vite configuration file (vite.config.js), enable named chunks for dynamic imports:

export default defineConfig({
  // ...
  build: {
    // ...
    rollupOptions: {
      output: {
        // Use the `name` field when generating asset chunks
        chunkFileNames: 'assets/[name]-[hash].js',
        // ...
      },
      // ...
    },
    // ...
  },
  // ...
});

This will ensure that dynamic imports always get a consistent chunk name, regardless of their content. This way, you can update your code without breaking existing links to dynamically imported modules.

Solution 2: Using an Error Handler on the Router

An efficient solution to fix the “TypeError: Failed to fetch dynamically imported module” issue in a Vue/Vite setup is by implementing an error handler on the router. This error handler monitors and handles errors that occur during dynamic module importing. When such an error is encountered, typically indicating a new deployment, the error handler triggers a hard page reload instead of attempting to dynamically load the modules. This ensures that the app reloads completely and resolves the issue.

To implement this solution:

  1. Import the router instance.

    import { router } from "./router";
    
  2. Create an error handler function.

    router.onError((error, to) => {
      if (
        error.message.includes("Failed to fetch dynamically imported module") ||
        error.message.includes("Importing a module script failed")
      ) {
        window.location = to.fullPath;
      }
    });
    
    • This error handler function checks if the error message contains specific strings indicating a dynamic module import error.

    • If an error is detected, it triggers a hard page reload by setting the window.location to the full path of the current route.

  3. Add the error handler to the router instance.

    router.onError((error, to) => {
      if (
        error.message.includes("Failed to fetch dynamically imported module") ||
        error.message.includes("Importing a module script failed")
      ) {
        window.location = to.fullPath;
      }
    });
    
    • This adds the error handler to the router instance, ensuring that it is active and will handle any dynamic module import errors.

By implementing this solution, you can effectively address the "TypeError: Failed to fetch dynamically imported module" issue in your Vue/Vite application. The error handler ensures that when a new deployment occurs, the app reloads completely, resolving any issues related to dynamic module importing.

Solution 3: Ensure File Extension for Dynamically Imported Modules

In the vanilla Vue/Vite setup, the reported error can occur due to the absence of the file extension for dynamically imported modules. While this might have worked in a webpack setup, Vite requires the file extension to be specified.

To rectify this issue, ensure that the module name includes the appropriate file extension. For instance, instead of:

import MyComponent from 'components/MyComponent'

Use:

import MyComponent from 'components/MyComponent.vue'

By specifying the file extension, Vite can correctly resolve the module and prevent the “Failed to fetch dynamically imported module” error.

Solution 4: Restart the development server

If you are facing the `TypeError: Failed to fetch dynamically imported module` error, restarting the development server may resolve the issue. This is a simple solution that has been effective in resolving the error for some users.

To restart the development server, you can run the following command in your terminal:

vite dev

Once the development server has restarted, try navigating to the affected routes again to see if the error persists.

Solution 5: Reload the page on dynamic import error

This solution is an extension of Wouter Sioen’s suggestion. It addresses an additional issue that may arise after implementing the initial fix.

The Problem: After applying the fix for the “TypeError: Failed to fetch dynamically imported module” error, a new error may occur when a chunk loading error happens: “Cannot read properties of undefined (reading ‘fullPath’)”.

The Solution: To resolve this issue, we add an error handler to the router using `router.onError`. Inside the error handler, we check if the error message includes either “Failed to fetch dynamically imported module” or “Importing a module script failed”. If it does, we check if the `to.fullPath` property exists.

If `to.fullPath` is undefined, it means that the error occurred before the navigation was completed. In this case, we reload the page using `window.location.reload()`. Otherwise, if `to.fullPath` is defined, it means that the navigation was partially completed, but an error occurred. In this case, we redirect the user to the intended destination using `window.location = to.fullPath`.

Here’s an example of the error handler:
“`
router.onError((error, to) => {
if (
error.message.includes('Failed to fetch dynamically imported module') ||
error.message.includes('Importing a module script failed')
) {
if (!to?.fullPath) {
window.location.reload();
} else {
window.location = to.fullPath;
}
}
});
“`

By implementing this error handler, we can gracefully handle chunk loading errors and prevent the “Cannot read properties of undefined (reading ‘fullPath’)” error from occurring.