Skip to content

Serving SPAs with client-side DOM routing and behind different routes without rebuilding.

License

Notifications You must be signed in to change notification settings

thediveo/spaserve

Repository files navigation

SPA Serve

Go Reference GitHub build and test Go Report Card Coverage

spaserve serves "Single Page Applications" (SPAs) from Go that are using...

  • ...client-side DOM routing,
  • ...varying base paths in different deployments or even within the same deployment because of multiple access paths.

And all this without the need to rebuild your SPA production code just because the (HTML) "base URL" changes.

Usage

  1. prepare your SPA index.html template (such as public/index.html) by adding a base element, if not done already; set its href attribute to ./:

    <!doctype html>
    <html lang="en">
    <head>
        <base href="./" />
        <!-- ... -->
     </head>
     <body>
         <!-- ... -->
     </body>
     </html>
  2. In case of CRA (Create React App), set the homepage field in package.json to "." (not the root slash "/"):

    {
      "homepage": ".",
    }
  3. add a basename helper to your SPA sources, such as a new file src/util/basename.ts:

    export const basename = new URL(
            ((document.querySelector('base') || {}).href || '/')
        ).pathname.replace(/\/$/, '')
  4. in your App.tsx ensure that you tell your client-side DOM router to correctly pick up the basename; this makes reloading the SPA from any route and bookmarking routes possible:

    import { basename } from 'utils/basename'
    
    <Router basename={basename}>
        <!-- your app components here -->
    </Router>
  5. Make sure that all links (and asset references) are relative, such as ./view2, et cetera.

  6. in your service, create your HTTP route muxer and set up your API handlers as usual, then create a SPAHandler and register it as the route handler to be used when all other handlers don't match:

    r := mux.NewRouter() // or whatever you prefer
    // (set up all your API routes)
    
    // finally create a suitable fs.FS to be used with the SPAHandler
    // and register it so that it serves on all routes not handled by
    // the more specific (API) handlers. Here, we assume the SPA assets
    // to be rooted in web/build.
    spa := spaserve.NewSPAHandler(os.DirFS("web/build"), "index.html")
    r.PathPrefix("/").Handler(spa)

References

Useful background knowledge when dealing with serving HTTP resources, base(names), et cetera...

Go Version Support

spaserve supports versions of Go that are noted by the Go release policy, that is, major versions N and N-1 (where N is the current major version).

Copyright and License

spaserve is Copyright 2022-23 Harald Albrecht, and licensed under the Apache License, Version 2.0.

About

Serving SPAs with client-side DOM routing and behind different routes without rebuilding.

Resources

License

Stars

Watchers

Forks