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.
1. A `_helper.rb` file where we throw a bunch of variables we want to pass
1. A controller file where we need to push feature flags
2. 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
```graphql
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
}
}
}
```
issue