Safe property passing from Backend to Frontend

We often need to pass data from Rails to the Frontend to initialise our Vue Apps. So far we took the approach to write a helper method which then passes the properties as part of the data-* tag which then can be parsed and injected to the Vue App.

This is a boring solution and worked well so far. However, it also has a few downsides:

  1. To properly verify that variables were injected to the Vue application, we need a Feature spec. This is expensive.
  2. When Vue Apps need to be initialised on multiple parts of the application (e.g. WorkItems should be able to open anywhere within GitLab), we'd need to set and provide these properties before rendering the Vue App on every page load.
  3. We rely on writing and parsing the properties by hand which can have some gotchas. e.g. Stringify boolean values on the backend, just to later parse the properties on the frontend again (parseBoolean helper)

Not a direct downside, but very visible: there is lots of ceremony involved to get a Vue App "started".

  1. A .haml file with an element that has a specific ID where we mount the Vue App.
  2. A _helper.rb file where we throw a bunch of variables we want to pass
  3. A controller file where we need to push feature flags
  4. An /index.js file to initialize the Vue App and parse all the variables

We will not be able to get rid of the HAML file for now (although we could even standardize this?) but maybe we can get rid of the helper methods and pushing feature flags from the controller by implementing an internal API endpoint to fetch properties needed to initialize Vue Apps.

  1. This way the testing will be cheaper (we just test the API endpoint)
  2. We get some "type-safety" out of the box
  3. No need to parse the properties again as it's just JSON

Potential downsides to consider:

  1. Will this cause even more multi-version compatibility issues?

Draft API proposal


query {
  vueClient(currentNamespace: String!) {
    apps {
      WorkItemsRoot { # always the name of the Vue App
         # ... whatever is necessary for that Vue App
      }
    }
    features { # List of features checks we have
      hasOkrsFeature
      hasSubepicsFeature
      hasIssueWeightsFeature
    }
    paths { # List of paths
       issuesListPath
       labelsManagePath
       registerPath
       hasIterationsFeature
    }
    permissions { 
      canAdminLabel  
    }
  }
}
Edited by Nicolas Dular