Analyzing JavaScript React Native: the Zooniverse case study
Zooniverse is a JavaScript / React/ React Native system. We first clone its sources from GitHub:
rootDirectory := 'zooniverse' asFileReference.
rootDirectory ensureDeleteAll. repository := IceRepositoryCreator fromUrl: 'git@github.com:zooniverse/mobile.git' to: rootDirectory
Reasoning About Package Dependencies
Let's start with a simple question: How many dependencies does this project have? And how many do not point to react-native
libraries?
The answers can be found in package.json
:
packageJson := rootDirectory / 'package.json'
Of course, you can find the answer by reading, but you are here to learn how not to read. So, how do we do it without reading? Well, JSON happens to be a reasonably structured piece of data. So, let's parse it:
dictionary := STONJSON fromString: packageJson contents. dependencies := dictionary at: #dependencies
So, how many dependencies are there? It's a simple query:
dependencies size
What about the dependencies that do not point to react-native
libraries? Another query:
dependencies associations reject: [ :each | each key includesSubstring: 'react-native' ]
This is a rather small problem. Yet, even here we can outcompete reading by means of custom tools.
Reasoning About React Dependencies
A more complicated problem is that of reasoning about dependencies between React components. For example, are there cycles between components?
To answer this question, we create a model:
model := GtReactImporter new parserClass: JSXParser; importDirectory: rootDirectory; finishImport; model.
Now, inspect the components and pick the Dependencies
view:
model allReactComponents
In this case, to answer the question effectively, we need an analysis at the level of React. To this end, we created a custom importer that understands React patterns (specifically, component definitions and dependencies), extended the base model with React specific entities, and created a custom visualization.