Search code examples
blazorgithub-pagesblazor-webassembly

Blazor WASM app on github-pages loads however refresh results in 404


Blazor WASM app on github-pages

I've published a Blazor WASM app on github pages and it loads fine here:

https://dharmatech.github.io/FractionalReserveBankingTest/

enter image description here

Specific page

Clicking on the Banking System link in the nav bar on the left loads that page properly:

enter image description here

Refresh leads to 404

At this point, if I hit F5 to reload the page, I get the following:

enter image description here

Questions

What's a good way to get page reloading working?

Code

If it helps, here's the main.yml file for this project:

https://github.com/dharmatech/FractionalReserveBankingTest/blob/master/.github/workflows/main.yml

The Blazor project that is being published:

https://github.com/dharmatech/FractionalReserveBankingTest/tree/master/BankCapitalWasm

The gh-pages branch that github-pages uses:

https://github.com/dharmatech/FractionalReserveBankingTest/tree/gh-pages


Solution

  • This problem is not only related to blazor wasm and all SPA Apps have this problem and the reason is that when you enter an address directly or refresh the page, the Github page looks for a directory that does not exist because of how GitHub Pages serves files. This repository has provided a solution for this problem

    What you need to do is redirect the user to some known page where you can control their further navigation. And then you will need to tell the Blazor where the user actually wanted to go. First Create a file called 404.html in the wwwroot folder is the following:

    <!DOCTYPE html>
     <html>
      <head>
        <meta charset="utf-8">
        <title>Single Page Apps for GitHub Pages</title>
         <script type="text/javascript">
         // Single Page Apps for GitHub Pages
         // MIT License
         // https://github.com/rafgraph/spa-github-pages
         // This script takes the current url and converts the path and query
         // string into just a query string, and then redirects the browser
         // to the new url with only a query string and hash fragment
    
         // If you're creating a Project Pages site and NOT using a custom domain,
         // then set pathSegmentsToKeep to 1 (enterprise users may need to set it to > 1).
         // This way the code will only replace the route part of the path, and not
         // the real directory in which the app resides, for example:
         // https://username.github.io/repo-name/one/two?a=b&c=d#qwe becomes
         // https://username.github.io/repo-name/?/one/two&a=b~and~c=d#qwe
         // Otherwise, leave pathSegmentsToKeep as 0.
    
         var pathSegmentsToKeep = 1;
    
         var l = window.location;
    
         l.replace(
         l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') +
         l.pathname.split('/').slice(0, 1 + pathSegmentsToKeep).join('/') + '/?/' +
         l.pathname.slice(1).split('/').slice(pathSegmentsToKeep).join('/').replace(/&/g, '~and~') +
         (l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') +
         l.hash
         );
    
        </script>
        </head>
           <body>
          </body>
     </html>
    

    you then need to decode these query strings and navigate to the correct page. This is done with the following code snippet that we will need to place in the head of yourindex.html file

    <script type="text/javascript">
    
      // Single Page Apps for GitHub Pages
      // MIT License
      // https://github.com/rafgraph/spa-github-pages
      // This script checks to see if a redirect is present in the query string,
      // converts it back into the correct url and adds it to the
      // browser's history using window.history.replaceState(...),
      // which won't cause the browser to attempt to load the new url. 
      // When the single page app is loaded further down in this file,
      // the correct url will be waiting in the browser's history for
      // the single page app to route accordingly.
    
      (function(l) {
       if (l.search[1] === '/' ) {
        var decoded = l.search.slice(1).split('&').map(function(s) { 
        return s.replace(/~and~/g, '&')
        }).join('?');
        window.history.replaceState(null, null,
            l.pathname.slice(0, -1) + decoded + l.hash
         );
        }
       }(window.location))
    </script>