1

I am trying to implement my application as a micro-frontend using a single-spa library. The folder structure of the application is as below,

  • micro-frontend
    • root app
    • navbar app (Angular application)
    • dashboard app (Angular application)
    • service app (Angular application)

I have deployed the same in the server and the website works as expected. The folder structure in the server(/var/www/html/) is as follows,

  • home (root) [URL: https://microfrontendapp.com/home]
  • dashboard [URL: https://microfrontendapp.com/dashboard/my-dashboard]
  • service [URL: https://microfrontendapp.com/service]
  • navbar

The issue I am facing is that I start using the website from the home page, then move to the dashboard or service application, and if I try reloading from this URL path, I receive a 404 Page not found error for the web URL.

I am trying to use route hashing to resolve the issue. The code is as below:

Home(Root) App

index.html

 <template id="single-spa-layout">
    <single-spa-router mode="hash" base="/">
      <div style="display: flex">
        <nav>
          <application name="navbar"></application>
        </nav>
        <div style="width: 96%; margin: 5% 1%">
          <route path="/dashboard">
            <application name="dashboard"></application>
          </route>
          <route path="/service">
            <application name="service"></application>
          </route>
        </div>
      </div>
    </single-spa-router>
  </template>

root-application.js

System.import("single-spa").then(function(singleSpa) {
  singleSpa.registerApplication(
    "navbar",
    function() {
      return System.import("navbar");
    },
    function(location) {
      return true;
    }
  );

  singleSpa.registerApplication(
    "dashboard",
    () => System.import("dashboard"),
    location => location.pathname.startsWith("/dashboard"),
    { some: "value" }
  );

 singleSpa.registerApplication(
    "service",
    () => System.import("service"),
    location => location.pathname.startsWith("/service"),
    { some: "value" }
  );

Navbar App

onNavigation() {
        window.location.pathname += "/"; 
// The above was used because on during navigation to dashboard or any other app, URL is changed as https://microfrontendapp.com/home#/dashboard/my-dashboard
        window.location.hash = "/" + url; // To point to the selected navigation URL
}

Dashboard App

router.ts

const routes: Routes = [
    {
        path: 'dashboard',
        component: DashboardComponent,
        children: [
            {
                path: 'my-dashboard',
                component: MyDashboardComponent,
                data: { }
            }
      }
]
@NgModule({
    imports: [RouterModule.forRoot(routes), { useHash: true, preloadingStrategy: NoPreloading }],
    exports: [RouterModule],
    providers: [
        { provide: APP_BASE_HREF, useValue: '/' },
    ],
})
export class AppRoutingModule { }

Local server URL behavior is as below,

  1. Home page: http://localhost:4200/#/
  2. Navigate to Dashboard: http://localhost:4200/#/dashboard/my-dashboard
  3. When reloading on the above URL it works just fine.

When deployed in the apache server the behavior is as below,

  1. Home page: https://microfrontendapp.com/home
  2. Navigate to Dashboard: https://microfrontend.com/home/#/dashboard/my-dashboard. But the page is not loading. There is no HTTP call to get the main script file (dashboard app compiled script file) to load the page.

Can someone help on why has the HTTP call for the script file not started? I am not sure if I have done something wrong. Or is there any other solution to resolve the 404 Page not found issue

Kindly help me here. Thanks in advance.

2 Answers2

0

This is a problem with your deployment server, not with single-spa or anything client-side, really. Apache needs to be configured to serve every request with the same index.html, which is something you would have to do for any single-page application and even if not using single-spa.

There isn't a single solution to this since you may need specific routes handled differently, but Angular and Vue offer very good starting points for how to config this on various servers. For Apache, it may look something like this:

RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html
filoxo
  • 8,132
  • 3
  • 33
  • 38
  • Hi, Thanks for the reply. I have tried using the same configuration. I am facing '404 Page Not found' issue when I try to reload the dashboard page. I am not sure what the problem is. – Vyshnavi Muvvala Oct 26 '21 at 10:31
  • Hi, I have deployed the catalyst-root app without build/compress but the other two apps use the single-spa build command. As mentioned in the above comment I have tried changing the server configuration but that is redirecting to the catalyst-root folder instead of the active route (catalyst-selfservice). I have only one index.html file which is in catalyst-root folder. The other two micro applications build version has only main.js file. I have a few queries, 1. Is the above implementation, correct? 2. I don’t use hash in URL. Is it mandatory to use hashing in routing? – Vyshnavi Muvvala Nov 01 '21 at 10:29
0

There is some irregularity in your routes.

Earlier when your were using PathLocationStrategy, your URL looked like: https://microfrontendapp.com/dashboard/my-dashboard

And after HashLocationStrategy, your URL is like: https://microfrontend.com/home/#/dashboard/my-dashboard

What is this /home/ here ? If this is context path, you might have to consider adding baseHref in your application.

Check my answer here

YogendraR
  • 2,144
  • 12
  • 17
  • Hi, /home is the path of the root folder where all the other micro applications were registered in. I am not sure why the hash shows up after the /home path. This is one of my doubts too (I have the clickable menu where it only sets the hash path when clicked). Since when used without hash, /home is not acting as baseHref. – Vyshnavi Muvvala Nov 01 '21 at 10:27