@noths/global-components

A set of global components for NOTHS.

Usage no npm install needed!

<script type="module">
  import nothsGlobalComponents from 'https://cdn.skypack.dev/@noths/global-components';
</script>

README

NOTHS Global Components

npm version Depfu Depfu

Frontend global components used at www.notonthehighstreet.com

Components included

  • NOTHS Header
  • NOTHS Footer
  • NOTHS Copyright statement
  • NOTHS Navigation and Mega Dropdown

Background & context

Global components are components which will be on most pages of the site.

These components use mainly vanilla javascript and do not use any framework. This is to reduce the footprint on the consuming application.

The components are written in ES2015 and use Webpack for compilation and minification.

Component usage

Consuming

HTML

The NPM module includes pre bundled HTML files for Header, Footer and Copyright components. To include these copy the file contents from node_modules/@noths/global-components/compiled/dist/[header|footer|copyright].html and insert into your page where required.

React

import React from 'react';
import { Header, Footer, Copyright } from '@noths/global-components';

export class App extends React.Component {
  render() {
    return (
      <div id="app">
        <Header />
          <h1>hello world</h1>
        <Footer />
        <Copyright />
      </div>
    );
  }
}

NOTE: These components are created using dangerouslySetInnerHTML of their counterpart HTML component. There is no JS logic in them, it's simply a wrapper to aid integrating components into React apps.

Consuming statically

React

To avoid having multiple verbose imports use the babel import plugin to rewrite them:

import Footer from '@noths/global-components/compiled/static/react/footer';
import Header from '@noths/global-components/compiled/static/react/header';
// becomes
import { Header, Footer } from '@noths/global-components';

Setup the babel import plugin:

// Install the plugin
npm install babel-plugin-import

// Add the following import config (you may have to update your .babelrc file to .babelrc.js):
module.exports = {
  ...
  plugins: [
    ...
    [
      'import',
      {
        libraryName: '@noths/global-components',
        libraryDirectory: 'compiled/static/react'
      },
    ],
  ],
};

The following functions are available as helpers to get the CDN path for the static stylesheet and script files:

globalsUrls(env) [development, qa, staging, oldstaging, production]

Returns the global static files CDN URLs for that environment (globally shared across services e.g. css resets etc.)

import { globalsUrls } from '@noths/global-components/helpers/static-files';

<html>
  <head>
    <link rel="stylesheet" type="text/css" href={globalsUrls(process.env.NODE_ENV).css} />
    ...
  </head>
</html>;

globalComponentsUrls(env) [development, qa, staging, oldstaging, production]

Returns the static files CDN URLS for the environment that includes all the components in a single bundle.

import { globalComponentsUrls } from '@noths/global-components/helpers/static-files';

<html>
  <head>
    <link rel="stylesheet" type="text/css" href={globalComponentsUrls(process.env.NODE_ENV).css} />
  </head>
  <body>
    ...
    <script src={globalComponentsUrls(process.env.NODE_ENV).js} />
  </body>
</html>;

Usage example with a Next.js app:

// _document.js
import Document, { Head, Main, NextScript } from 'next/document';
import { globalsUrls, globalComponentsUrls } from '@noths/global-components/helpers/static-files';

const env = process.env.NODE_ENV;
export default class ExtendedDoc extends Document {
  render() {
    <html>
      <Head>
        <link
          rel="stylesheet"
          type="text/css"
          href={globalsUrls(env).css}
        />
        <link
          rel="stylesheet"
          type="text/css"
          href={globalComponentsUrls(env).css}
        />
        ...
      </Head>
      <body>
        <Header />
        <Main />
        <Footer />
        <Copyright />
        <NextScript />
        ...
        <script src={globalComponentsUrls(env).js} />
      </body>
    </html>;
  }
}

_NOTE: These components are created using `dangerouslySetInnerHTML` of their counterpart HTML component. There is no JS logic in them, it's simply a wrapper to aid integrating components into React apps._

#### No framework

The NPM module includes pre bundled HTML, CSS and JS static files for the Header, Footer and Copyright components.

```js
// HTML
'node_modules/@noths/global-components/compiled/static/html/[header|footer|copyright].html';

// CSS & JS
'node_modules/@noths/global-components/compiled/static/css/global.css';
'node_modules/@noths/global-components/compiled/static/[css|js]/all-components.[css|js]';

Triggering the Mobile Navigation

The Header components handles triggering the Mobile navigation when the burger menu is click by default. But if you need to toggle the Mobile navigation from another element you will need to fire a TOGGLE_NAVIGATION event.

Here is an example:

  const event = document.createEvent('Event');
  event.initEvent('TOGGLE_NAVIGATION', true, true):
  document.dispatchEvent(event);

Installation

Prerequisites

  • NodeJS 8

Setup & run

Install dependencies

npm install

Build and start

npm run build_and_start

Build and start for development which will watch your files and rebuild if there are any changes.

npm run watch

Testing

There are two different types of tests in the project.

Unit tests

Unit tests use Mocha and Chai.

To run unit tests:

npm run test
npm run test:build // Ensure npm run build is run beforehand

End to end tests (e2e)

End to end tests use cypress.

To run e2e tests:

npm run test:features

There may be cases where feature tests runs fine locally but not in CircleCI. In order to debug the failing CI test(s), we can store cypress screenshots and videos as CircleCI artifacts. This store_artifact step is not a part of this repo's circleci/config.yml so screenshots are not stored as artifacts by default. To get this feature, maually add the store_artifacts steps as below in the features section of Configuration File i.e config.yml. Configuration File could be accessed by tapping on the ... dots on each pipeline build.

  - store_artifacts:
      path: packages/global-components/cypress/videos
  - store_artifacts:
      path: packages/global-components/cypress/screenshots

After adding the above lines, do commit and save and rerun the build. At the end of the build process, click on features job from the status and the screenshots and the videos can be accessed from the Artifacts tab.

Mocks

There are a number of API's that get mocked as part of the e2e tests. Theses mocks are stored in server/dev-mocks.js.

Releases

The project is hosted on NPM with the name @noths/global-components.

To Publish a Beta Package

npm run build

npm run publish:beta

To upload static files to S3: in AWS S3 console, select the buckets for qa-static-files/frontend-packages/global-components. Create a new folder with the version number that matches the beta package number just generated. Then upload the javascript and css files that have been generated locally in the dist/static folder.

TODO

  • Still using styles-toolkit even though the repo has been deprecated and deleting
  • No support for static assets i.e. pushing images to a CDN