The inability to load the main.js script in index.html results in a blank website that only gets resolved upon refresh

Using the Vite / Rollup bundler with a Vue app as an example, we can see how this issue applies to any modern web stack.

Vite automatically adds a hash to each js chunk, asset, and main.js file to indicate when changes have been made. However, there is an issue where if the hash of the main.js file changes, the website fails to load the Vue router and gets stuck on a blank index.html page until manually refreshed. One potential solution could be adding an error handler directly in the HTML file like:

<script type="module" src="/src/main.hash1.js" onerror="onMainScriptLoadingError"></script>

And inside the onMainScriptLoadingError function, include:

window.location.reload();

This would allow for the page to refresh and download the new index.html with the updated main.hash2.js file without causing an infinite loop of refreshing. However, it seems strange that this approach is not mentioned in the official documentation of any bundler. Is there a better way to handle this issue without cluttering the server with multiple historic files or tying builds together?

Answer №1

With the help of a personalized vite plugin, you have the ability to achieve something similar to this. (Make sure to adjust the regex to match the name of your vue file! Note that this example is from a react application!)

vite.config.ts

export default defineConfig(({ mode }) => {
  const indexOnErrorPlugin = () => {
    return {
      name: 'index-on-error',
      transformIndexHtml(html: string) {
        return html.replace(
          /\/assets\/index-(\w+).js"/g,
          function (match, hashValue) {
            return match + ' onerror="window.location.reload()"'
          }
        )
      },
    }
  }

  return {
   
    plugins: [
      ...
      indexOnErrorPlugin(),
    ],
    
  }
})

Alternatively, for a more complex solution (avoiding reloading the same hash):

vite.config.ts plugin:

  const indexOnErrorPlugin = () => {
    return {
      name: 'index-on-error',
      transformIndexHtml(html: string) {
        return html.replace(
          /\/assets\/index-(\w+).js"/g,
          function (match, hashValue) {
            return (
              match + ' onerror="handleIndexScriptError(\'' + hashValue + '\')"'
            )
          }
        )
      },
    }
  }

index.html

    <script>
      function handleIndexScriptError(hash) {
        console.error('Error loading index script', hash);
        const hashArray = JSON.parse(localStorage.getItem('index_hashes')) || [];
        if (hashArray.includes(hash)) return;
        hashArray.push(hash);
        localStorage.setItem('index_hashes', JSON.stringify(hashArray));
        window.location.reload();
      }
    </script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What role does the css-loader play in webpack?

As I dive into Webpack 2, I've noticed that many projects utilize the css-loader, but I'm unsure of its exact purpose. ...

Implement currency formatting in input text with v-model in Vue

Is there a way to add a currency sign to the input value in such a way that it appears as part of the input itself? For example, how can I make it display "10 $" when the user inputs 10 while still keeping "10" as the actual data value of amount? input( ...

Obtain the abbreviation inside the specified element

Currently, I have the following code snippet: <th class="day-heading mon" scope="col"> <abbr title="Lunes">L</abbr> </th> My goal is to access the abbr element and modify both its innerHTML and title attributes. How can I achiev ...

Accessing iframe's HTML using a server-side solution by circumventing the Cross-Domain Policy

Our current challenge involves accessing dynamically generated HTML elements using JavaScript, particularly when trying to extract image URLs from these elements. When the HTML elements are generated solely through JavaScript, extracting the URL is straigh ...

Using ngFor directive to iterate through nested objects in Angular

Receiving data from the server: { "12312412": { "id": "12312412", "something": { "54332": { "id": "54332", "nextNode": { "65474&q ...

Is it possible to make changes to dynamically inserted HTML using jQuery.ajax?

I'm facing a scenario in jQuery where I make an ajax call that inserts HTML into my website. However, I also need to perform operations on this inserted HTML within the same ajax call's success callback function. Here is a simplified version of ...

"Exploring the possibilities of combining AngularJS with PHP to manipulate

Recently, I started diving into AngularJS and encountered a situation where I needed to fetch data from a database as an array using a foreach function. Here is a snippet of the code I used: <ul> <?php foreach($Items as $Item):?> ...

Tips for iterating through a nested JSON response using Vue.js

Recently, I started exploring Vue JS and encountered a challenge while looping through API responses using v-for. Below is the snippet from my code: Get Coins Data <div v-for="coin in coinsData">{{coinsData.data.coins.name}}</div> T ...

Turning a string into JSON (encountering an unexpected token u/')

One burning question remains: why is this not functioning properly? It keeps throwing an 'unexpected token' error! var inquiry = "{'form_id':'foo','title':'bar'}"; console.log(JSON.parse(inquiry)); ...

Develop a TypeScript class by incorporating a static function from an external library, while ensuring type safety

I am looking to enhance the capabilities of the rxjs5 Observable class by adding a static function. While this can be easily accomplished in plain JavaScript: var myStaticFn = function() { /* ... */ }; Observable.myStaticFn = myStaticFn; this approach w ...

Implementing a hamburger menu across various webpages

I recently followed a tutorial on adding a hamburger menu from this YouTube video. The menu works perfectly on the INDEX.html page, but when I try to add the same code to other pages like "contact" or "about", none of the menu features seem to work. I rea ...

Looking for a way to determine in JavaScript whether the last item in an array is a number or not? Keep in mind that the last element could be either a number or a string, depending

console.log("case 1") var event = "Year 2021"; console.log(typeof(parseInt(event.split(" ").pop())) === "number"); console.log("case 2") var event = "Year mukesh"; console.log(typeof(parseInt(event.split(" ").pop())) === "number"); console.log("case 3") va ...

Creating unique sizes for each quad in Three.js using InstancedBufferGeometry and ShaderMaterial

I'm working on creating a visually dynamic scene filled with points of varying widths and heights. The challenge I'm facing is figuring out how to manipulate the vertices in the vertex shader to achieve customized sizes for each point. Here' ...

Updating an Object in vue.js Upon Click Event to Add a New Value

I currently have a code snippet that looks like the following: arr = [ { val1: a, val2: b }, { val1: a, val2: b }, { val1: a, val2: b } ] <div v-for="single in arr"> <button v-on:click="addSome"></button> </div> When I c ...

Utilize Axios in Vue.js to fetch and process data from a REST API endpoint in C#

After successfully creating and deploying an API on Azure, I am trying to display the response in an alert box using javascript (Vue.js). The test method of my API returns the string "working". You can test the API here. This is the code snippet from my A ...

Transformation in input value does not manifest in other components

When adjusting the sliders, the input fields are supposed to update accordingly. However, I've noticed that the changes in the input fields only take effect if I manually change their values. The automatic reflection doesn't seem to occur when us ...

Using Google's Closure Compiler to Optimize JSON Files

When dealing with a json string that is parsed and properties of the object are accessed using dot notation, a warning may be triggered by the google closure compiler stating that the property is not defined. To overcome this issue, one workaround is to c ...

Mastering the Art of Tallying Select Choices in Protractor

Experiencing an issue with counting options in the select attribute during my test. Here is the code snippet: it('should verify the number of options', function()) { expect(element(by.id('sorting_options')).all(by.tagName('optio ...

Avoid mutating the prop directly and instead, utilize a data or computed property that is based on the value of the prop. The prop that is being mutated in this case is

Help me understand this issue that Vue is displaying, I am not sure what is going on. This is my progress element: <el-progress :percentage="percentCompleted" v-show="uploadingVideo"></el-progress> data() { return{ percentCompleted: 0 ...

Can you explain the inner workings of the sort function mechanism?

After reading through this article about Array.prototype.sort(), I noticed that the Sort() function can behave differently depending on the availability of compareFunction. When it comes to sorting strings, it uses UNICODE values. However, in a specific ...