How should I handle front end routing in webpack?

Viewed 448

I am building a website with separated front end and back end via restful api. When I develop the front end UI, I bought a template that uses webpack to generate the bundled production files.

Currently I am using pure javascript to handle the routing. For example, to show different view for logged in users compare to other users, I did the following:

if (window.location.pathname === "/") {
    const token = window.localStorage.getItem("token")
    // if token exists and it has not expired, show the logged in homepage. 
    if (token && !jwt_expired(token)) {
        window.location.replace("/index-loggedIn.html")
    } else {
        window.location.replace("/index.html")
    }

Here are my questions:

  1. I notice window.location.replace could be pretty slow and it would take half a second to route from index.html to index-loggedIn.html. Is this the right way to do it?

  2. I am planning to deploy the front end static files on Nginx as a web server. I guess this workflow will be like: User sends a request to the "/" route -> Nginx responds with index.html -> The above javascript code gets ran -> Another request to "/index-loggedIn.html" gets sent to Nginx -> Nginx responds with index-loggedIn.html

    Is that what actually will happen? It sounds very inefficient to me since I would like to be able to check user's log in status before serving the home page.

  3. Is there any other frontend server/framework I can use to make the routing easier? Then I can use Nginx simply as a reverse proxy. I checked out Angular but I think it will take too much effort to convert the whole template into Angular's format. Can I use express just for front end routing?

Thanks in advance for your suggestions!

1 Answers

You are asking too many things with too many assumptions. Let us try to uncover them step by step.

Type of Application

Basically, you can build two types of applications: SPA (Single Page Application) or Multiple independent pages application; or the hybrid of two Multi-page SPA application. Typically, we use React/Vue/Angular to build a SPA application.

Routing in SPA application

In a SPA application, the routing is completely done on the client-side. The server plays very little role in it. We use HTML History API to achieve this (This is what you are doing by hand using replace method).

With this setup, you need a UI Server (typically build with Node.js) or a Nginx like Reverse proxy. Your server won't be aware of the routes that client-side code has defined. The server/reverse-proxy needs to do two things. First, when the request is for asset (request ending with .html, .css, .js, .png, etc.), then it should try to serve that asset. When the request is for non asset (request without any file extension https://example.com/users/), then you can safely assume that it is a request that must be handled by the client (your client-side code has defined the routing) and thus you must always and always send index.html page which then will bootstrap your SPA application.

In the initial boot sequence of the SPA, you would read the location and determine if this is a valid route. If this is not a valid route, you can redirect user (client-side only) to some default view or 404 view.

Why you would need to do this? Because initially, your user may just say https://example.com and then navigate to /users route by some action. But, if user does full page refresh after navigation, you back-end server will see the route as https://example.com/users. There you need to handle the fallback route to always serve index.html. In this case, 404 must be handled by using client-side code. All the major UI frameworks provide routing solution. You don't need to do it by hand.

Authentication

Now if you using using index-loggedIn.html for authenticated views and index.html, then from SPA perspective, you have a anti-pattern or code-smell at least. You must have a single index.html view which takes care of both authenticated and un-authenticated views. In routing world, we typically use guards to protect the views from unauthorized access.

What you are doing would currently work but as you mentioned that you see the lag of half seconds before redirect. And, that would happen on every page refresh. But that exactly is the problem with full client-side SPA apps in general. However with proper architecture, you should be able to address this.

Routing in a Multi-page SPA or multiple pages application

If you are building an application like this, then your server needs to be more involved and must handle more routing responsibility. In this case, you should probably use cookie instead of localstorage for managing your token. Browser automatically sends the cookies to the server and your server then can make the decision if it wants to serve index.html or index-loggedIn.html page.

To answer your question:

Is this the right way to do it? - It would work but it is an anti-pattern.

Is that what actually will happen? It sounds very inefficient! - It is not inefficient as long as you are properly loading the views with spinner and doesn't cause awkward UX for the users.

Can I use express just for front end routing? - It is an invalid question. Literally, you cannot use express for front-end routing. But then if you plan to implement UI server using express, then you can use it to define proper routing architecture eventually making it part of your front-end stack.

In the end, note that there are few more consideration that you need to take into account. What happens when user is doing hard refresh when he is on some route that server doesn't recognize? How to properly support bookmarking capability for your users? Also, are you building SPA or traditional server rendered application? If SPA, use client-side framework. If server rendered, then keep all the logic inside Express or equivalent code. If it is hybrid, determine the architectural boundary.

Finally, if this sounds too complex consider using hash-based routing for your SPA. That simplifies many things at the cost of not-so clean URLs.

Related