All,
There’s been recent talk about taking code that has been copied across our client apps (specifically the D3 charting library that is used in Atlas Data Sources and AchillesWeb) and pull it into a shared repository. This thread is to discuss the technical details of an approach.
Some context: we’re only talking about client side (javascript) libraries. There have been 2 recent pull requests to factor out code here and here, but the first involves the UI tier so that’s the context I’d like to focus on. We already have an example of a shared component on the Java-tier with SqlRender, but discussing this approach involves maven builds and nexus repos, so that’s out of scope for this discussion.
For sharing client-side code, I think there’s 2 main approaches for organizing the codebase: one shared repository where we sub-divide the repo into sub-directories to store each component, or one-repo-per-library.
One advantage of a dedicated repository is that we can have issues and feature requests focused on the particular library. In the case of a single repo, you’d have unrelated issues mixed in together, which may make it harder to organize bugfixes.
Also, with per-library-repos, we can release each library independently under its own release version. I’m not sure what a single repo approach would look like for releases (if we would utilize releases at all) but I think it would act like a ‘OHDSI UI package’ where all updates to client UI libraries would be released as one unit.
Another thing to consider is how the OHDSI git repo list would be impacted by this. With a single repository approach, it’s just a new OHDSI repo (“Shared UI Components”). Using a lib-per-repo approach, we have N repos for N libraries. If N gets large, it could be a headache.
The initial libraries that I can think of that would make good candidates for sharing are:
jnj_chart (which we’d rename)
facet tables
cohort editors (I have an implementation that optimizes this library into a single AMD .js file that can be imported into an application)
I think these 3 examples would make a good first step towards formalizing the javascript code sharing.
Technical Details
Regardless of which way we organize the code base (repo-per-lib or single-repo), I propose that the
top-level folder of a library contain a src, test and build folder. The src contains the sourcecode of the library, test can contain testing code, and build can contain the optimized build of the library that is referenced by the client applications. I don’t propose that we have our apps reference a raw.git URL to fetch the codebase, rather we should come up with a CDN-like approach where versions of the libraries can be pushed up and referenced via version number. Example:
// require.js configuration
"jnj_chart": "https://cdn.ohsi.org/jnj_chart/1.0.1/jnj_chart.min"
This example assumes that the file jnj_chart.min.js has been pused up to a CDN called cdn.ohdsi.org, to a folder dedicated to the library: jnj_chart, with version 1.0.1. jquery uses similar semantics, as does most libraries that are posted to CDNs such as cloudflare.
We are using Require.js as our AMD module loader, which comes with a optimizer that I’ve applied to the Cohort UI components. I’ve invoked the build directly from a command line and haven’t implemented a grunt/gulp build script for this, but there are many examples of this that we could leverage.
I do not want to turn this conversation into a require.js vs. {insert other js library framework here}. The work involved in making these components shared should simply be a matter of extracting one of the copies of the library out into a shared location, and then updating the client apps to reference the shared library. We should avoid API changes that would break existing code.
By formalizing the approach, everyone can have the same expectations about how the code should function and we’ll be less prone to tripping over each other as we build out the shared code repository. So before making any specific changes, let’s come to a consensus with what the approach will be and how it will be applied.