Search code examples
angularwildflysingle-page-application

How to avoid 404 error with Angular 7 Single Page Application on Wildfly


I have a front-end project as single page application (SPA) built with Angular 7, which consumes a Java REST API hosted on Wildfly (there are other projects on the same server). We recently moved this SPA from Apache to Wildfly to serve it under HTTPS. Everything works fine except when the user hits F5 or refreshes the page any other way; in this case he or she falls into a 404 error, since SPAs expect the navigation to stay at index.html all the time.

For instance, if I access [server:port]/myspa it loads correctly and redirects me to [server:port]/myspa/login. But if I am already in [server:port]/myspa/login and refresh the page, I get stuck in 404.

I've already tried some configurations in standalone.xml that didn't work, like setting a filter inside undertow subsystem like bellow:

<subsystem xmlns="urn:jboss:domain:undertow:4.0">
    ...
    <server name="default-server">
        ...
        <host name="default-host" alias="localhost">
            ...
            <filter-ref name="spa-to-index" predicate="equals(%s,404)" />            
        </host>
    </server>
    ...
    <filters>
        ...        
        <rewrite name="spa-to-index" redirect="true"
            target="http://localhost:8080/myspa/" />
    </filters>
</subsystem>

Does anyone know how to redirect requests for [server:port]/myspa/* to the index.html?


Solution

  • an easy way that I found to solve this was: installing grunt.js and grunt war.

    npm install -g grunt -cli
    npm install grunt-war --save-dev
    

    Create the Gruntfile.js file inside the root folder of the project with the following content (do not forget to replace [myapp] occurrencies with your own project info)

    module.exports = function ( grunt ) {
        grunt.loadNpmTasks( 'grunt-war' );
    
        var taskConfig = {
            war: {
                target: {
                    options: {
                        war_verbose: true,
                        war_dist_folder: 'warFile',   // Folder path seperator added at runtime. 
                        war_name: '[myapp]',      // .war will be appended if omitted 
                        webxml_welcome: 'index.html',
                        webxml_webapp_extras: ['<error-page><location>/index.html</location></error-page>'], 
    //redirect the errors pages to index.html
                        webxml_display_name: '[myapp]'
                    },
                    files: [
                        {
                            expand: true,
                            cwd: 'dist/[myapp]', //the folder where the project is located
                            src: ['**'],
                            dest: ''
                        }
                    ]
                }
            }
        };
    
        grunt.initConfig( taskConfig );
    };
    

    Then run the command:

    grunt war
    

    This will package the Angular application inside a .war file, and you can deploy it normally on Wildfly, and refreshing the page will work as expected.