Skip to content

Latest commit

 

History

History
361 lines (300 loc) · 10.4 KB

Getting-Started.md

File metadata and controls

361 lines (300 loc) · 10.4 KB

👈 Return to Documentation

Getting Started With One App

One App is a web application that combines together a micro frontend of Holocron components into a single, cohesive runtime. Holocron modules empower teams to craft a rich user experience that can be used to compose parts of a web page or as route destinations all on their own. One App was built from the ground up with Holocron and its micro frontend architecture, allowing engineers to seamlessly update each module independently and collaborate across teams working together to create a product. While One App comes with a security standard in practice, progressive web app capability and many other features, its feature set can be configured by Holocron modules to your exact specification.

This guide will get us started with One App and will go over some of the fundamental concepts of the framework. We will start from the beginning by creating our first Holocron module, then we will go through a few One App essentials to get up and running quickly.

📖 Table of Contents

Generating a Module

The first step to get started with One App is to generate a Holocron module. There are two different Holocron module types, root and child module. Let us start by creating a root Holocron module, the entry point to our micro frontend.

export NODE_ENV=development
npx -p yo -p @americanexpress/generator-one-app-module -- yo @americanexpress/one-app-module

Once the command is executed, you will be prompted to fill out a few questions about your new module before it is generated.

  • Choose a name for your module
  • Select "root module"
  • Select "yes" for parrot-middleware
  • Select "yes" for internationalization

Read more about parrot-middleware and internationalization

Once the root module is generated we will be able to start developing with One App. As we continue, we will eventually create a child Holocron module for us to use - the main difference between a root module and child module is that the root module is the entry point of the micro frontend and as we will learn more on, it plays a significant role in configuring One App.

More Info

One App

Packages

react

react-dom

holocron

Running One App

Every Holocron module that is generated comes with pre-installed scripts. One of these scripts is npm start which starts up one-app-runner.

one-app-runner aids in local development by pulling a one-app docker image and running it with a set configuration provided in your modules package.json.

npm start

When one-app-runner is fully loaded and running, we can navigate to http://localhost:3000 and view our Holocron module in the browser.

It can take a few minutes when one-app-runner starts for the first time.

In a new terminal window you can run:

npm run watch:build

npm run watch:build will watch for any changes made to your module, and rebuild the module bundle. When we're ready to publish our Holocron module, we can build and bundle your Holocron module by running:

npm run build

When ready to publish to production, make sure to set NODE_ENV=production before building. This will ensure a production ready Holocron module and turn on key security mechanisms like SRI for Holocron module scripts.

Local Configuration

Inside the package.json of your Holocron module, you can include a "one-amex": {} property to configure some of the tools in our ecosystem.

{
  "name": "my-module",
  "one-amex": {
    "runner": {
      "rootModuleName": "my-module",
      "modules": [
        ".",
        "../my-adjacent-child-module"
      ]
    }
  }
}

When you start using child modules, one-app-runner can include multiple local modules when it's configured to accept them.

More Info

Guides

Development

Run One App Locally

Mocking API Calls

Production

Running In Production

Publishing Modules

Packages

@americanexpress/one-app-runner

@americanexpress/one-app-bundler

Adding CSS Styles

Styling a Holocron module with CSS or SCSS can be accomplished by creating a separate file that is used with the markup we write in our module.

src/components/styles.scss

.myButton {
  background-color: green;

  &:active,
  &:focus,
  &:hover {
    background-color: blue;
  }
}

We can import the stylesheet into our module and use CSS modules to access the class name for each selector by its name. The class names are unique when they are generated which avoids unwanted cascading of styles in our document and DOM selector collisions.

src/components/MyModule.jsx

import React from 'react';
import styles from './styles.scss';

export default function MyModule() {
  return (
    <div>
      <button type="button" className={styles.myButton}>
        Click Me
      </button>
    </div>
  );
}

More Info

Guides

Adding Styles Recipe

Creating Routes

One App has built in dynamic routing that uses each Holocron module to build out the router. There is a special property that we can assign to our module Module.childRoutes which would allow us to add routes to One App.

src/components/MyModule.jsx

import React from 'react';
import { Route } from '@americanexpress/one-app-router';
import ModuleRoute from 'holocron-module-route';

export default function MyModule({ children }) {
  return (
    <div>
      {children}
    </div>
  );
}

MyModule.childRoutes = () => [
  <ModuleRoute key="home" path="home" moduleName="home-module" />,
  <Route
    key="about"
    path="about"
    component={() => (
      <p>
        About Page
      </p>
    )}
  />,
];

childRoutes can be assigned a function that is given the Redux store used by the app, which can be useful when using route hooks like onEnter. If the Redux store is not needed, childRoutes can be an array of Routes and ModuleRoutes or a single Route if that is all that's needed.

More Info

API

Routing

Loading Modules

Guides

Module Composition

Code Splitting Using Holocron

Packages

@americanexpress/one-app-router

holocron-module-route

Module State and Data

Holocron modules have a special property called Module.holocron that allows us to configure the module. Within holocron, we can set keys like reducer to include a module reducer with the Redux store used by One App. There is also loadModuleData that is called during server side render and when a Holocron module is loaded by One App. When we combine the two, we can asynchronously load all the data needed for a module and add it to the store when a reducer is supplied to the holocron configuration.

src/components/MyModule.jsx

import React from 'react';
import { fromJS } from 'immutable';

function DataVisualizer({ data, loaded }) {
  return (
    <div>
      {/* do something with the data when it loads */}
    </div>
  );
}

export default function MyModule({ moduleState = {} }) {
  return (
    <DataVisualizer data={moduleState} loaded={!!moduleState} />
  );
}

MyModule.holocron = {
  name: 'my-module',
  reducer: (moduleState = fromJS({}), action) => {
    if (action.type === 'my-action') return fromJS(action.data);
    return moduleState;
  },
  loadModuleData: async ({ store: { dispatch }, fetchClient }) => {
    const response = await fetchClient('url/to/data.json');
    const data = await response.json();
    dispatch({ type: 'my-action', data });
  },
};

Both moduleState and moduleLoadStatus are props given to each Holocron module. All state is immutable and the reducer provided will be expected to return Immutable compliant types (which includes JavaScript primitives). loadModuleData is passed the Redux store, along with the fetchClient, ownProps and the module itself. fetchClient can be configured with appConfig which will learn about in the next section.

More Info

API

Loading Data

State Management

Guides

Making An API Call

Enabling Server Side Render

Internationalization

Packages

immutable

redux

react-redux

reselect


Up Next

Check out the Configuration guide to grasp how we can use environment variables and Holocron module app configuration to cater to our needs as well as utilize features in One App.

☝️ Return To Top