React @ Namics

2017 / 2018

React @ Namics

2017 / 2018

Projects

Projects

Sunrise.ch
 

Pathe.ch
 

Migros Impuls Coach
 

& many other smaller React Projects

Homepage CMS only → SEO 

React Widgets

Homepage React & CMS

One React App

Backend

Backend

Bootstrap Apps

 

Backend Data

 

i18n

 

 


  // index.html

  <div class="js-react" data-appName="quickBuyWidget" data-productId="64031">

  // bootstrap.js

  const $apps = $("body").find(".js-react");

  $apps.each(function(index, app) {
    let htmlNode = app;
    const $app = $(app);
    const pageData = $app.data();
    const appName = $app.data("appName");
    const $mountNode = $app.find(".js-react-mount");

    $script(`/${appName}.js`, function() {
      $(document).trigger("bootstrap-react-app", {
        htmlNode, appName, pageData, store, history
      });
    });
  });

Bootstrap Apps 1/2

Bootstrap Apps 2/2


  // quickbuyApp.js

  $(document).on("bootstrap-react-app", function(event, data) {
    if (data.appName !== "quickBuyWidget") return this;
    ReactDOM.render(
      <RootRedux store={data.store}>
        <QuickBuyWidget
          productId={data.pageData.productId}
        />
      </RootRedux>,
      data.htmlNode
    );
  });

Backend Data


  // appConfig.js

  window.ReactApp = window.ReactApp || {};

  ReactApp.Env = ReactApp.Env || {};
  ReactApp.Env.urlMagnolia = "https://pathe-ch.namics-test.com";
  ReactApp.Env.urlSolr = "https://pathe-ch.namics-test.com/solr";

  ReactApp.Sites = {
    PLA: {
      label: "Plaza",
      wheelChairAreaCode: "0000000005",
      preferredComplexID: "1011"
    },
    KUC: {
      label: "Küchlin",
      wheelChairAreaCode: "0000000006",
      preferredComplexID: "1010"
    }
  }

i18n


  // appConfig.js

  window.ReactApp = window.ReactApp || {};

  ReactApp.I18n = ReactApp.I18n || {};
  ReactApp.I18n = {
    'react.impulsCoach.molecules.Record.title': "Your new record is {recordValue}kg"
  }

  // Record.jsx

  <Link
    href={routes.dashboard.newMeasurement.href}
    title={i18n('react.impulsCoach.molecules.Record.title', { recordValue, '60' })}
    modifier="button"
  />

Architecture

Architecture

Create React App

 

Fork React Scripts

 

 

Create React App

Fork React Scripts

Fork React Scripts

Code Quality

Code Quality

Flow

 

Prettier

 

Tests

 

Flow

Flow

Prettier

Tests

Frontend UI

Frontend UI

Separate Repository

 

Frontend UI JavaScript API

UI JavaScript API

Performance

Performance

Code Splitting using Dynamic Imports

 

Recompose: OnlyUpdateForKeys

 

Sourcemap Explorer

Dynamic Imports


  // Counter.jsx

  import React from 'react';
  import { onlyUpdateForKeys } from 'recompose';

  export type CounterProps = {
    count?: string | number,
    modifier?: string,
  };

  const Counter = ({ count, modifier }: CounterProps): any => {
    return (
      <div className={`a-counter${modifier ? ' a-counter--' + modifier : ''}`}>
        <span className="a-counter__number">{count}</span>
      </div>
    );
  };

  const shallowUpdate = onlyUpdateForKeys(['count']);

  export { Counter };
  export default shallowUpdate(Counter);

Only Update For Keys

Sourcemap Explorer

That's it

That's it

namics.com/jobs 😉

HSR — React @ Namics

By Dominic Modalek

HSR — React @ Namics

Slides for my Talk at the HSR Frontend Best Practices Conference 2018.

  • 445