Skip to content

Single Page App Design

bảo.thiên.ngô edited this page Apr 12, 2018 · 4 revisions

Overview

The goal of this document is to outline the transition of the if me application to become a modern web experience. This document assumes you have basic familiarity with Rails and its accompanying folder structure.

Infrastructure

React for UI components

The Rails application will use react_on_rails gem for inclusion of modern NodeJS based projects inside the Rails asset pipeline.

Server-side rendering / isomorphism

API

  • RESTful or GraphQL?
  • Documentation?

Bundling and deployment

Webpack, dynamic chunking

I18N

Asset location and code generation

The I18N feature is provided by react_on_rails to allow our NodeJS application to inherit from the work on the Rails side. The process by which the rails application generates the I18N configs is by reading the default Rails I18N file locations in config/locales/*.yml. From there we can use the react_on_rails rake tasks to generate JavaScript consumable locale files.

rake react_on_rails:locale # Generate i18n javascript files

These files will live in the path defined by the react_on_rails configurations found in config/initializers/react_on_rails.rb. These files will compile the Rails locale files and then distribute them out to the I18N config directory. In our app this is:

config.i18n_dir = Rails.root.join("client", "app", "libs", "i18n")

The two files this rake task generates are the following default.js and translations.js. Translations will take the nested translations and create a JSON object keyed as dot-delimited strings, e.g. "title.nested.description" -> translated value.

Since react_on_rails uses the react-intl plugin to support I18N context in React components. The default.js file translates the Rails->Javascript intermediary object into react-intl compatible representations. Most of our javascript will reference the definitions found in default.js.

const defaultLocale = 'en';
const defaultMessages = defineMessages({
  "deviseConfirmationsConfirmed": {
    "id": "devise.confirmations.confirmed",
    "defaultMessage": "Your email address has been successfully confirmed."
  }
});

This does lead to camelCasing of the keys, which deviates from the hash key references found in Rails.

We then consume the I18N outputs in our React components through the setup methods found in client/apps/libs/i18n/.

I18nSetup.js is the first loaded object to load the I18N JSON file into the client side. This increases bundle size slow downs as we grow the size of these JSON files. There may be a way to lazy load the I18N translations, but further digging into react-intl is pending on that task.

I18nUtils.js is a temporary compatibility layer, as we want our React component to be able to change the Rails I18N state. So we resort to having some helper libraries that will transparently interface with the Rails I18N context through the cookie mechanism that Rails defines.

You can see the I18N tool being used in storybooks.

For now the requirement that we must interop React components with jQuery elements makes this hard to architecture properly. Pending changes or full SPA migration will alleviate some of the complexity found here.

UI I18N library

We'll be using react-intl to render translated text in the UI.

(How do we load localization bundles?)

Progressive web application

The idea of a progressive web application (PWA) is to make the application appear like a native mobile app.

Responsive design

There are three main devices to consider: mobile, tablet, desktop. Generally the considerations are viewport resolution, and gesture/touch capabilities.

Search

Product features

This section deals with any particularly unique technical needs for features of the product.

Moments

  • Rich input editor

Medications

Allies

Resources

Clone this wiki locally