2020 Development choices for multi-platform SaaS application
I am currently working on a new project for my company. The project consists of a mobile app that is backed by a server; a very standard setup for SaaS projects.
In this article, I want to discuss the different available development options to implement the project. I know how much these projects are popular today, so I hope this summarized research can help you get started fast with the right choice.
This assessment process should be done before starting a new project. The depth of the process (and how much of your time it consumes) should be relative to the size and the lifespan anticipated for your project.
Choosing the right tools can give you the boost needed at the initial stages of the development, and ease the path for further expansion.
I’ll go through the process with you for the project that I’m working on. My project’s requirements might differ from yours, so you should adapt the process accordingly to fit your needs.
For this process to be successful, you need to be objective and think of non-technical/business aspects as equal. You may prefer some tech over the other. You may feel more comfortable with a solution that you know. Tech-wars are viral once in a while and may affect you. All of these should be considered to make it as objective as it should be.
The assessment process is comprised of these steps:
- List all your requirements – technical, business…
- Find three best and most popular solutions – a simple web search
- Choose the two most befitted options – a deeper web search
- Detailed comparison of the two options
- Implement a POC if it is hard to differentiate
- Update the comparison
- Conclude with one solution path – while considering future changes
People often divide such projects into frontend and backend. For simplicity, I’ll address each separately, but you should always consider the connection and consistency between them. I’ll discuss this connection in another article.
Most of the comparison is done by relying on relevant sources from the web. When searching for such sources, one should take close care to find reliable and most updated sources.
Reliability can be verified by:
- Checking the site’s reputation – popularity, professionality on software development and non-brand related; we can’t check if NodeJS is good on Node’s official site
- Author’s objectiveness – we can’t rely on the author’s thoughts and preferences
- Article’s formality – use of formal language, availability of article’s metadata
The last keynote will give us information on when the article was written thus helps us find up-to-date information (technologies develop fast especially on their initial phases). Besides, we can use the search engine’s tools to filter out old results.
Note: When there is not enough information, we could verify the article’s reliability by comparing it to other articles.
Our main requirement is that the frontend needs to run on Android, iOS, and Web platforms. For better business efficiency, the best solution needs to be based on a cross-platform development framework (since developing two separate native apps is very costly).
These frameworks have matured enough over the years and today they are ready to be used in enterprise applications (apps like Skype, Facebook/Instagram, and Google Ads already developed with such frameworks).
The leading frameworks in this space are React Native, Flutter, and Xaramin.
React Native and Flutter are newer, more popular, and have better performance than Xaramin (see this article for further details).
The real competition is between React Native and Flutter.
React Native vs Flutter
My project’s requirements are:
- Native support for Web, Android, and iOS
- Use of mobile hardware – such as location, file system, camera…
- Support for maps – the preferred choice is Google maps but should consider alternative map providers
- Good uniform UI customization (for all platforms) – such as calendar support
- Near-native performance
- Shared code between all platforms
A good comparison is done in this article.
It is almost a draw between the two frameworks. A POC needs to be performed to conclude the better fit for our use case.
I did a simple POC to verify my requirement. The POC contained a welcome screen and a map view screen. In the welcome screen, I added a form with a calendar. On the map screen, I showed the device’s location and a custom marker of a fixed place. It was sufficient to give me a feel on what I am going to deal with later.
Main differences considering the use case
|Aspect||React Native (RN)||Flutter||Winner|
|UI||Builtin UI doesn’t look good (plain HTML UI) but can be extremely customized. There are lots of UI libs (a full UI design systems) that look great and support all platforms. You can also create your own elements.||Builtin UI looks OK on all platforms. You can create your own UI elements.
UI libs are more of specific widgets/elements than a whole design system (like in RN).
|Flutter (only because there is no need for external libs to get a good basic UI)|
|Platform support||Full native support.||Web support is beta.||RN|
|Code sharing with backend (check backend section)||If the backend is written in JS, there can be code sharing.||The backend can be programmed in Dart, but it is not one of SWAPLET’s choices for backend. Can be shared as JS code after transpile.||RN|
|Easiest to employ||Almost every developer knows JS. There are many developers developing in React for the web.||Dart is new to the industry, thus almost every developer needs to learn the language.||RN|
|Learning curve||JS language is easy to learn.
React Native framework is harder to learn and the official docs are good but not enough.
From React to RN – very easy.
|Dart language is easy to learn.
Flutter framework is somewhat easy to learn from official docs.
|Environment setup||Hard for newcomers because of cross platform support.|
|Maps support||Has libs for Google, Apple and Mapbox maps. Needs modifications to support web maps.||Google maps libs only and is in beta version.||RN|
|Hardware support||Almost identical|
Note: This is a summarized version of a bigger comparison table. The larger version includes additional aspects that were omitted from this table because of their insignificant difference or importance and rated every aspect with a weighted 1-5 score (the weights represent the importance of a certain aspect concerning the use case).
As said before, these frameworks are almost identical. But when you take into account the business needs and technical requirements, we can say the React Native is a better fit at this time (Flutter will close this gap in a couple of years).
The most popular current choices in the industry for such use cases are .NET Core (Core), NodeJS (Node), and Python.
Note that while Core is a full all-in-one framework, Node and Python are not. Node is more of a runtime environment that web frameworks are based on. Python is an all-purpose programming language which has many frameworks for web development.
The frameworks that will be taken into consideration are Django for Python and ExpressJS For Node since they are the most popular frameworks.
We need to try and judge these techs without referring to a specific implementation (framework), but because of the heterogeneous comparison, we may need to rely on implementation standards driven by the community (popular frameworks). This doesn’t mean that we are locked to developing using the most popular framework.
Django is a very big framework, and great for developing enterprise applications. However, it will slow the initial development (more bloated) and is inferior in performance, for this it will lose out to Core and Node. Check this article for more information.
.NET Core is the new cross-platform framework that is replacing the .NET Framework. These are the differences between the two.
NodeJS vs .NET Core
- Callback hell
- Problem troubleshooting – stack traces are hard to understand in complex code
- Hard debugging – for several reasons:
- The nature of JS as async
- Callback hell
- Dynamic typing
- Code reuse & modularity problem – decoupling code becomes harder in JS (less natural)
- Type safety/Dynamic typing – is the cause of many problems in JS. It may be fun at first, but when writing piles of code, it is recommended that we make use of static typing.
Yet these problems don’t concern Core (C#) developers.
These issues were real in the past, but since new improvements were introduced to JS:
- Async/await mechanism (since Node v7.6 22/02/2017) – based on generator functions of JS. This article explains why callback hell, troubleshooting, and debugging are not a concern anymore.
- ES6+ fixed a variety of syntax issues with JS#https://webapplog.com/es6/.
- Typescript is a superset of JS that uses static typing and introduces “critical” OOP concepts to JS. The differences between ES6 and Typescript are explained here.
- Modularity problems are addressed in ES6 which is builtin in Node.
This article summarizes the differences between Core and Node (up-to-date).
Main differences considering the use case
- Node is considered to be more minimal (with a small footprint) than Core.
- Frontend choice (React Native), gives some advantage to Node over Core; Since both are based on JS, code can be shared between frontend and backend.
- Node is easier to start small to medium apps while Core is better for medium to large apps.
- Npm, the package manager of Node, is a very powerful tool and is considered a big advantage over other frameworks (such as NuGet) and it has a vast library.
- .NET Core is more comfortable developing on Windows – Nuget is an example of a tool that is missing for development on Linux/Mac.
- Core performs better – a better fit for CPU intensive tasks (though I didn’t find a detailed benchmark with recent versions).
- Node is a more suitable fit for client interaction – more efficient when developing, take for example the straightforward routing mechanism that is in Node.
- Frameworks’ parallelism and scaling – see later.
This article elaborates more on the differences (written in 2017 – CI/CD is much more mature today for Core).
Scalability & performance
Almost identical; Core scales using multi-threading (single process), yet Node scales using multi-processes (with a single thread).
Almost identical in performance (if deployed correctly).
The main difference between the two scaling concepts can be an advantage/disadvantage:
- It is easier to develop on a single thread.
- Multithreading has shared memory which is more intuitive for development but makes it harder to decouple and leverage microservices concept.
Node is async by nature (JS) and Core is considered sync; All code in Node is run async, and whenever you need sync, you must declare it and use one of the mechanisms given by the language/framework. In contrast, all code in Core is sync, and when async is needed, you need to use multithreading development for the specific action. Asynchronicity is mainly relevant for IO blocking operations.
Another related difference is that Node is Event-driven and Core is not (has more flexibility choosing the architecture of the code, but will be more bloated to use as event-driven).
- For OOP developers – developing sync code is more intuitive.
- Async development is more appropriate for IO intensive & real-time applications (such as chats).
There is no one good choice, as we saw earlier, Node (more precisely JS) tackled all the problems it had (though it will take years to correct this reputation) and can be considered as equal as Core for enterprise applications. The decision is based merely on preference and future needs.
There are many examples of projects using Core and Node beside each other.
The best plan would be starting with Node, for faster development (and because MVPs usually have non-complex functionality), after that we can integrate Core for CPU-intensive functions and complex business logic. The architecture will be microservices-complaint using both frameworks.
What is right for me, maybe wrong for you. Always check if my basic assumptions apply to you.
Nevertheless, hope this opened your eyes to a more manageable and thoughtful path.