Giter Site home page Giter Site logo

aspnetde / typesafe-spa Goto Github PK

View Code? Open in Web Editor NEW
25.0 4.0 0.0 1.62 MB

This is a small demo that explores different approaches for creating a potentially scalable single page application.

Home Page: https://thomasbandt.com/type-safe-spa-fable-fsharp-vs-typescript

License: MIT License

JavaScript 42.07% F# 41.13% HTML 5.55% TypeScript 11.25%
fsharp mvu model-view-update elm elm-lang elm-architecture elmish spa typescript

typesafe-spa's Introduction

Type-Safe SPA

This is a small demo that explores different approaches for creating a potentially scalable single page application. See here for the completely unspectacular sample apps in action, and here for my conclusion.

Structure

Structure

Functionality

  • There is a global session object that potentially can hold shared state for all parts of the application.
  • The login page authenticates the user and initates the creation of the session.
  • After logging in, the user is redirected to the dashboard, where they are welcomed by name.
  • There is an additional profile page, showing the name again.
  • From the profile page it's possible to go to an "edit profile" page that allows changing that name.
  • After the name has changed, that change must be reflected in all parts of the application: dashboard, and profile page.
  • Although "edit profile" could be seen as a child of "profile", it is kept on the same level for simplicity reasons (we potentially already are at the third level here).

Goals

That scope of functionality allows us to look at the following questions:

  1. How are parent-child relationships handled?
  2. How much boilerplate code needs to be written?
  3. How much guidance and support provides the compiler?
  4. How maintainable, aka scalable, does the approach appear to be?

Approaches

Elmish + Feliz

Observations

  • When introducing intents (aka external messages), the parent doesn't know about them until we start handling them there. So the compiler wouldn't complain if we forget to add it to the parent(s).
  • Routing can fail silently when the expected route isn't found. Sometimes that's just a matter of lower and upper case letters.
  • Feliz.Router is best being used with arrays representing the url segments, because that's what can be passed to the format() function (it does not accept lists).
  • The Feliz syntax felt rather verbose at first. Unfortunately, Html is a type and not a module and therefore "cannot be opened". However, in direct comparison to the "classic" Elmish view syntax, for real world tasks there seems not to be that much of a difference in terms of the number of written lines of code. Good old HTML will in most cases still stay shorter, though...
  • Except for commands fully testable, as everything is (mostly pure) F# functions
  • Does not require much knowledge of React

React Function Components + Feliz

Observations

  • Much less boilerplate code to write in comparison to Elmish + Feliz
  • It is basically React written with F#, so React knowledge is needed
  • In addition, regular updates are needed whenever React changes
  • Working with the context API of react needs getting used to, but is then relatively straightforward
  • Passing data to components through props is straightforward as well
  • useElmish is useful for more complex forms (see login and edit profile), but simple operations can also be handled more pragmatically (see logout)
  • Right now, Hot Module Reloading (or Fast Refresh) does not work. Which is a clear obstacle during development time.
  • TBD: Testability

React + TypeScript

Observations

  • Having not actively worked with TypeScript since its early days in 2012, it was surprisingly easy to get started.
  • Although this small demo doesn't use much of the language's features, those that are being used were really easy to pick up and a pleasure to work with.
  • The tooling based on Visual Studio Code is amazing. I not only like the automatic code-formatting but also the really fast feedback loop that is provided during development time.
  • When the build breaks, it does so within milliseconds, and error messages are always helpful. Most of the time, however, it already becomes obvious that something went wrong while typing.
  • I could take over all the concepts (components, context, ...) from the previous implementation with Reaction Function Components + Feliz, which allowed me to implement the TypeScript demo within a couple of hours.
  • I decided to implement the two parts of the app which contain a bit more "logic" (login + edit user name) without following any strict pattern like MVU. As everything is self-contained in its own component, this seems reasonable.
  • react-router is powerful but relatively easy to get started with.
  • As with the Feliz sample, function components are easy to reason about.

Comparison

Lines of Code

Although it is not the most important factor, it might be interesting to see how much more or less code every approach produces. This comparison was created through cloc and only counts those files that are actually used to write the app. So the compiled JavaScript, for example, is not considered.

Approach App Files Blanks Comments Code
Function Components + Feliz 13 59 6 316
Elmish + Feliz 11 77 6 404
React + TypeScript 11 27 1 241

Performance and bundle size

The following is measured by looking at the final and production-ready compile SPAs with Google Chrome (83) on macOS. It is obviously not objective and may be improved by some settings (I just used the default configuration as provided by the templates I used). But it gives an idea about what to expect.

Approach Requests Transferred Resources DOMContentLoaded Load
Function Components + Feliz 8 253 KB 466 KB 167 ms 166 ms
Elmish + Feliz 7 253 KB 468 KB 171 ms 173 ms
React + TypeScript 7 216 KB 328 KB 131 ms 132 ms

(Transferred = compressed, Resources = uncompressed; in each case the fastest run was chosen)

Resources

typesafe-spa's People

Contributors

aspnetde avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.