https://github.com/thediveo/spaserve
Serving SPAs with client-side DOM routing and behind different routes without rebuilding.
https://github.com/thediveo/spaserve
Last synced: 25 days ago
JSON representation
Serving SPAs with client-side DOM routing and behind different routes without rebuilding.
- Host: GitHub
- URL: https://github.com/thediveo/spaserve
- Owner: thediveo
- License: apache-2.0
- Created: 2022-06-11T11:35:12.000Z (about 3 years ago)
- Default Branch: master
- Last Pushed: 2025-01-05T20:58:19.000Z (6 months ago)
- Last Synced: 2025-04-01T10:03:24.359Z (3 months ago)
- Language: Go
- Homepage:
- Size: 55.7 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# SPA Serve
[](https://pkg.go.dev/github.com/thediveo/spaserve)


[](https://goreportcard.com/report/github.com/thediveo/spaserve)
`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](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)" changes.For devcontainer instructions, please see the [section "DevContainer"
below](#devcontainer).## 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
`./`:```html
```2. In case of CRA (Create React App), set the `homepage` field in `package.json`
to `"."` (**not** the root slash ~~`"/"`~~):```json
{
"homepage": ".",
}
```3. add a basename helper to your SPA sources, such as a new file
`src/util/basename.ts`:```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:```tsx
import { basename } from 'utils/basename'
```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:```go
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...- [An elegant solution of deploying React app into a
subdirectory](https://skryvets.com/blog/2018/09/20/an-elegant-solution-of-deploying-react-app-into-a-subdirectory/)
(_Sergey Kryvets_) – a rare competent analysis and introduction to the `base`
HTML element. This post shows how to get SPAs working with `base` for a
_fixed_, _hardcoded_ base path. In contrast, `spaserver` _dynamically_
rewrites the `base` element when serving an SPA, as needed.- [answer to "_Golang. What to use? http.ServeFile(..) or
http.FileServer(..)?_"](https://stackoverflow.com/a/28798174/6632214)
(stackoverflow) – and yes, `spaserve` uses `http.FileServer` which supports
`fs.FS` via an `http.FS` adaptor.## DevContainer
> [!CAUTION]
>
> Do **not** use VSCode's "~~Dev Containers: Clone Repository in Container
> Volume~~" command, as it is utterly broken by design, ignoring
> `.devcontainer/devcontainer.json`.1. `git clone https://github.com/thediveo/enumflag`
2. in VSCode: Ctrl+Shift+P, "Dev Containers: Open Workspace in Container..."
3. select `enumflag.code-workspace` and off you go...## Go Version Support
`spaserve` supports versions of Go that are noted by the [Go release
policy](https://golang.org/doc/devel/release.html#policy), that is, major
versions _N_ and _N_-1 (where _N_ is the current major version).## Copyright and License
`spaserve` is Copyright 2022, 2025 Harald Albrecht, and licensed under the
Apache License, Version 2.0.