We decided to build an app for our demo site and we opted to prototype the native mobile application with React Native that would use content from eZ Publish CMS.
Building our first React Native mobile app
Because of the reasons presented above, our strong will to learn new stuff, and a belief that React will continue to grow better and better, we decided to prototype the native mobile application with React Native that would use content from eZ Publish CMS. Not only was this a test for React Native, but also for eZ Publish REST API.
While the logic might imply that one would have fewer troubles with API that’s more than twice older than the library which is still in its minor version (and is still being mocked), it was quite the opposite, actually. eZ Publish REST API might be REST indeed, but is it really an API suitable for this kind of use is still arguable. It is way too chatty and at the moment it has no resource accessible via GET method for fetching/searching the content based on criteria, so very atypical practices, like making a POST request to /views resource, had to be used in order to fetch content using criterions. Also, in early October, when the application was made, eZ REST Client was not compatible with React Native.
However, none of that discouraged us and we proceeded with the application development. We decided to build our app based on Netgen Life Demo site, our own eZ Platform & Netgen Layouts demo installation we regularly use as a starting point for new web projects.
After a couple of weeks we had a simple content-driven mobile app that had a home screen with the latest articles and a side menu with custom categories. Upon choosing the category, the user would see an article list with the latest articles from the selected category. Upon choosing the article, the article screen was shown with an image, article’s metadata, and article’s content placed in a WebView.
The application, as you have probably noticed, is fairly simple and required relatively small amount of work, even though I’ve never worked with React Native (I spent the most hours grasping eZ REST API). Apart from the restricted number of components one can use and a different navigational/routing system, everything else is pretty much the same as developing the web application. While React components on the web use HTML tags, React components on mobile use a set of React Native components for the preview. Instead of with CSS, SCSS, or any other stylesheets, React Native components are styled with the StyleSheet object which is an abstraction over CSS subset. As you can see, React Native is web developer-friendly and makes abstraction for creating native cross-platform mobile applications using web technologies.
The sketch below shows a basic example of splitting application screen into React components and reusing them across the application. There are basically two different containers: one for listing articles and the other one for showing the article’s content. The aforementioned container that lists articles has two possible rendering states: if (left screen) or if not (right screen) articles category is selected. Both use the same ArticlesList React component for showing a list of articles, they just receive a different array of articles to show. Furthermore, if we are on the landing screen (no category selected), the container will render ArticlesTiles which is basically a React component that renders other React components – one SingleColumnTile and two TwoColumnTiles. In this case, the aforementioned component is reused inside of the same container and can be reused an arbitrary amount of times, depending on our needs.
If you are interested in digging further into the application structure, you can find its codebase on the GitHub repository, as we decided to open source this React Native application under the MIT license.
Running the React Native app locally
In order to run the application on your local machine, you need Node.js, the React Native command line interface, Android Studio (for running on Android emulator), and XCode (if you are a MacOS user and want to run it on iOS emulator).
For installing all the needed prerequisites please consult the projects docs or the React Native Getting Started page. After you had set up your machine, clone the repository and install the dependencies. Provide content to the application by editing ngdemoappconfig.json.example file in the project root and removing .example suffix. Properties restEndpointUrl and siteInfoContentID are mandatory, while articlesPerCategory and contentTypes will fall back to the default values. Defining contentTypes is also highly recommended. Configuration restEndpointUrl defines the URL of the eZ installation from which the application will fetch content, while siteInfoContentID should be content ID of a so-called SITE INFO object where the content categories are defined. It is a custom-made eZ object (hence not part of the eZ installation) and must have a main_menu object relation list field which references the objects that represent categories used in the application.
If you want to run the application on the iOS emulator and your REST endpoint does not use HTTPS, you will have to modify ios/NetgenMoreSiteApp/Info.plist file manually in order to fetch content on iOS application. Simply add the following inside of NSExceptionDomains and change example.com with your endpoint:
<key>example.com</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> </dict>
Finally, you can build and run the application in a simulator by typing the following instructions in your terminal:
- iOS: react-native run-ios
- Android: react-native run-android
While iOS simulator will start automatically after running react-native run-ios, you'll have to start Android Virtual Device manually before running react-native run-android. For more information about run Android Virtual Devices (AVD) follow this link. It's also possible to run application live on physical device.
Download the app from Google Play and AppStore
Looks great, but...
Note that in the real-life scenario one should consider implementing local caching and smarter prefetching for better user experience. Secondly, as mentioned before, the application consumes eZ REST API which is quite chatty and therefore requires a lot of custom code for handling fetches inside the mobile app. A better approach would be implementing custom REST API atop of eZ because of a superior fetching speed and a control over the content that is being displayed in the app.
In typical content-driven apps, like this one, the control over content being delivered to a specific landing screen needs to be at least partially kept on the editor side. Currently, if you would want to change how the content is fetched from the CMS in this approach, you would need to adapt the mobile application code and push the new app release (a quite cumbersome process). By moving the logic outside the mobile app to a custom server-side REST API (which is then utilized by the app), developers and editors gain much better outside control over the mobile app behavior.
Other useful resources
Besides this sample application, there are other various projects and resources which can help you with writing and building your own React Native application:
Note that not all features in the app have been implemented (like search or share feature). Feel free to implement them yourself for practice if you are bored with todo tutorials. :)