Skip to content

Instantly share code, notes, and snippets.

@johnpmitsch
Last active March 13, 2020 04:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johnpmitsch/f5c12f5d2652a07180e19da6324cef5b to your computer and use it in GitHub Desktop.
Save johnpmitsch/f5c12f5d2652a07180e19da6324cef5b to your computer and use it in GitHub Desktop.
Multiple SPAs with Foreman research

Goal:

Have Foreman, Katello, and plugins manage their own React SPAs that look and feel like one application. This would be done using single-spa which can send routes to different SPAs and even load different SPAs on the same page.

Challenges:

  • Sharing authentication between SPAs
  • Sharing components
  • Managing "global" state like organization selection
  • Having the same menu

Possible workflow:

  • Rails loads certain routes into a page with a div that can be bootstrapped by an SPA. SPAs bootstrap this div, the "routing" being done by single-spa.
  • Use observables (like RxJS) to manage state that needs to be shared. For example, all apps can subscribe to the Current Organization observable from Foreman. Could also be used for things like settings.

Notes:

  • This would mean we could use the existing work we have done to convert pages/components to React, moving this to the individual SPAs. New pages and rewrites can happen in these SPA repos.
  • UI work wouldn't be blocked by completing this new UI, it would use the same dependencies and React framework that we use now, just structured differently.
  • The SPAs could be launched by themselves and ran independently
  • Testing could happen on the SPAs individually, perhaps some data would have to be mocked, but could be run on its own.
  • Each SPA can manage it's own linting, testing, CI/CD, etc...
  • We use the foreman-js dependencies in each SPA, this is shared so we all use the same versions and UI libraries, the dependency management would most likely stay the same.

Ideas/Scratchpad

  • Have a foreman-chroming app for the menus and top bar?
    • One foreman-chroming app to handle the menus and the "global" information that another SPA can subscribe to, such as organization/location/settings, anything that is not in the API and passed through rails.
    • Any application can be run with the foreman-chroming app on its own, so I can start a katello-spa with the foreman-chroming-spa and it will run on its own and talk to API.
  • Keep foreman and all plugins in a monorepo?
  • One real-world approach -single-spa/single-spa#107

CRITERIA

  • Backend rails server does not have to be running for the UI to display
    • The backend server could serve static files, but the purpose of this investigation is to decouple with Rails and separate out the front-end

THINGS THAT MAKE AN SPA HARD

  • Having a plugin-based architecture
  • Having a variable amount of plugins
  • Plugins can be installed after installation
  • Co-existing with Rails pages
  • Sharing Authentication
  • Global state

Work that has already been done that we can use

  • Moving code to React
  • Slot and Fill (maybe)

INVESTIGATION

Repo: https://github.com/johnpmitsch/foreman-spa-microfrontend

Open questions

  • [DONE] Can we use no external URLs or dependencies, will work disconnected? Single-spa uses SystemJS now
    • uses local npm packages now, but can set up CI to publish new ones always from master
  • [DONE] Will assets not double load if we are loading multiple React apps on a page?
    • Uses webpack externals to not load assets twice, only in foreman-chroming
    • we could possibly standardize this using a common webpack config with https://github.com/survivejs/webpack-merge - this config could be overwritten too by individual plugins.
  • How to dynamically load applications based on plugins being present?
    • Use script to read a config file of plugins and edit package.json in place, adding plugins and environment variables. Use env variables in root-config.
  • How will slot + fill behavior work? Pages filling in other pages across repos.
    • Can slot and fill be adapted?
    • Could keep all components that can be expanded by apps in a 'foreman-components' shared component library and gate the functionality based on the env variables
  • Apache, how to route to both SPA and Rails?
  • How do we deploy to production?
  • How do we install plugins after the initial installation?
    • If we are using environment variables to tell what is present, those only are relevant during the webpack build process. So what is built is final and to update, the whole bundle has to be rebuilt.
    • All plugins are in mono repo and all are shipped?
    • Have some sort of in-production system that rebuilds the webpack build with env variables turned back on. This part could even be part of Rails and the files served from Rails, but not rendered server side. So they would would be fully rendered SPA files, served client-side by rails or even apache, then able to be updated by the installer.
  • Versioning for releases and master
  • Browser history? How to preserve that moving from Rails to SPA
  • Development how will we start all the servers at once?
  • Do we need single-spa or can we do this manually through apache and our own logic?

Resources

Alternatives

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment