Singular Stack Style Monorepo

Cam White
Cam White
Dec 12, 2018 · 5 min read

One JavaScript repository across modern web and mobile platforms.

Generated By Cam White


It was a tough time to be alone, application codebases across the platforms lay dispersed throughout the cloud. How could one hacker deploy an app to every relevant platform without expending a life of development time reaching these targets?

Isomorphic — Having identical relevant structure; being structure-preserving while undergoing certain invertible transformations.

Enter the Vue CLI, in combination with some godlike plugins we can have an isomorphic progressive client that lives alongside a fully ECMAScript 2018 spec’d Node API. Where, each piece is contained in one source of truth for all application deployments. As a lone wolf developer, this unlocks the full spectrum of the stack to hit as many targets as possible in one shot.

The Construct

We start with a single directory named for our project. We will take advantage of yarn wokspaces to sync the node_modules/ of our pieces.

We can then edit the newly created root package.json to include the workspace information. Our workspaces in this case are frontend/, frontend/src-cordova/, and backend/ because they all have their own package.json. This allows us to install all dependencies across the project stack with one command; yarn.

Example file tree

In the frontend/ groundwork is laid by the Vue CLI.

With the backend/ I prefer a custom pattern to generated norms. It is based on a fractal, essentially every directory is a connected expansion of the root.

However, this API pattern is up to the architect and can be interchanged freely!

Let’s take a closer look at the initial scaffolding of the frontend/ and what it did. We have three Vue CLI plugins Cordova, PWA, and last but definitely not least UVue. These are the magic beans unlocking our three targets.

  1. Progress web with SSR and a service worker to be accessible via a url.
  2. Android native build to be available in the play store.
  3. iOS native build to be available in the app store.
Initializing Vue and installing the CLI plugins

The frontend/ has one entry point that effects every instance of the clients. For example all updates to frontend/src/App.vue are reflected across targets, meaning changes to the browser app are seen on the native platforms. Furthermore, when we execute our serve commands the app runs in two different modes, SSR and SPA.

Let’s examine these commands and expose their key differences, keep in mind they are run from the project root via workspaces.

All this is already right at your fingertips, but we need a uniquely simple configuration to mesh things together.

The Configuration

One great thing to mention about this workflow is it maintains an extensible, upgrade-able, and config driven base that is flexible in what suits your style. That being said, the frontend/ root requires three separate configuration files. One file for the CLI , plus two for UVue’s server and core. These files will be automatically generated and augmented by the CLI, but in our case we need to tweak some.

Config — the options given to us by the greater creators; passed down like heirlooms through the generations.

The files below contain some basic config related to both Cordova and Workbox, the development server proxies, and UVue.

The baseUrl depends if we are running on Cordova or not, while the cordovaPath is where the Cordova shell lives.

The workBoxOptions contain two important properties. The runtimeCaching which applies a 'networkFirst' strategy that keeps a record of all API requests in the cache, but always asks for for updated content first. Next, we need templatedUrls specified as our base route required for SSR.

The devServer here bundles and serves the frontend/ when running as an SPA in Cordova. REST and real-time APIs, the backend/ use a proxy to curry their requests.

UVue core plugins

Here we have UVue’s core configged to our needs. This mounts the core’s built-in plugin system along with plugins I had created. Also know this, order of the plugins matters.

The httpClient handles requests to REST API including authorization, while guards are responsible for protection of routes. The sockets plugin uses a Vue middleware when the store becomes available.

UVue server plugins

Finally, the UVue connect server that renders the page before delivering it to a web based client has a lot out of the box plugins, but is also extremely customize-able. Again the order does matter.

The only plugin we need to create is a proxy from the SSR server to the API server. We also need some important cache control headers for the service-worker.js file defined in the static plugin.

The UVue server also includes adapters to build an API layer on top of it. But for our use case I believe the decoupled server approach can be more easily scaled across platforms. That’s it for ourfrontend/ configuration.

For more on other frontend/ the configuration options start here and here.

That’s it for this post, but if there is interest I can expand with backend, environment and deployment stories in a part two.


vue + node

With Appearances By

  1. uvue — universal server rendering or single page micro framework
  2. pwa — progressive web app workbox
  3. cordova — web view native builds

About the Author

Inspired by what I see as new digital forms of life I look at code as the interface to shaping this world.

Javascript for breakfast, lunch, and dinner. Autodidact all day!

Want to know more about me? I stream my work almost daily on twitch. Come hangout!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store