mono-components

About this package
This package is only used in the mononoth, through an automated hypernova integration.
See the related hypernova-app repo.

Description
General Aim
The Aim of this package is to have a point of contact between the shared-components
package and the Mononoth to facilitate the disintegration of existing Mononoth-pages and allow for progressive iteration of new functionality.
Most of the development happens in shared-components, where we iterate on React components that can be shared between all frontend-services and the mononoth. However, there will be a number of functions that should not be part of shared-components because they will only ever be used in the Mononoth. This package takes responsibility for owning that functionality.
End Goal
mono-components
should never be seen as a place where functionality will reside forever.
The aim of adding functionality inside of this package is to evolve components from shared-components so that they can be used in a disintegrated page as well other frontend-services.
Once the affected page is disintegrated into a frontend-service, any associated functionality in mono-components ceases to exist. At which point the relevant page is also removed from the mononoth.
Noths Stream Ownership
Owned by all Streams
Owned Routes or Domains
Routes aren't "owned" but this package affects the following routes in the Mononoth.
Consumer:
- /search (and all related search pages: category, partner, departments)
- /checkout
API Dependencies
none
Used NOTHS NPM Packages
- @noths/global-components
- @noths/shared-components
- @noths/code-style
- @noths/eslint-config
Installation & Development
Installation
npm i
Developing in mono-components only
# Run in dev mode (watches files & hot-reloads client-code)
npm run dev
Hybrid Development with shared-components & mono-components
Preparation:
npm run bootstrap
cd packages/shared-components
npm link
cd ../mono-components
npm link @noths/shared-components
Next up, you'll want to watch shared-component changes while developing in mono-components.
In terminal 1 (mono-components):
cd packages/mono-components
npm run dev
In terminal 2 (shared-components):
cd packages/shared-components
npm run watch
Now, if you make changes to something inside shared-components, after some time it should hot-reload in your browser. If you watch the logs in both terminals you should see terminal 2 update and then terminal 1 and finally the browser.
Hybrid Development with Mononoth & mono-components & shared-components
Preparation:
NOTE:
Don't link with lerna during this process!
This method is in an experimental state for and all the node_modules
removing might be overkill, if you can improve this method, be my guest! Make sure your suggested method really works, then make a PR :)
cd packages/shared-components
npm run experimental:hardlink:rome
cd ../mono-components
npm run experimental:hardlink:rome
npm run experimental:hardlink:rome
Any generated package-lock
-files should not be commited.
Next up, you'll want to watch shared-component changes while developing in the Mononoth.
This is quite slow, so only do this when necessary. It is recommended to do most of your development in mono-components using the first Hybrid approach. That approach offers hot-reload and much faster development.
In terminal 1 (notonthehighstreet):
- change the file
notonthehighstreet/config/application/defaults/other.yml
(uncomment/recomment the lines concerning hypernova)
- Run the required command(s) to start the mononoth.
In terminal 2 (hypernova-app):
npm run start:dev
In terminal 3 (shared-components):
npm run watch
In terminal 4 (mono-components):
npm run build
For information about dev-toolkit, refer to the documentation.
Development Workflow in mono-components
mkdir ./src/client/pages/my_page
touch ./src/server/views/my_page.hbs
And add the following content to my_page.hbs
<!-- NOTE: This template is for development only and will not be used in production. -->
<!-- Rendered Component HTML -->
{{{ renderComponent 'MyPage_ExampleComponent' props='{ ... }' }}}
<!-- CSS for faking component placement in the Mononoth -->
<style>
.MONO-MyPage_ExampleComponent{
position: relative;
display: block;
float: left;
border: 2px dashed #42A5F5;
}
</style>
mkdir ./src/client/pages/my_page/ExampleComponent
touch ./src/client/pages/my_page/ExampleComponent/index.js
- Add a new component to
./src/client/index.js
export { default as MyPage_ExampleComponent } from './pages/my_page/ExampleComponent';
- Add new page route to
./src/settings.js
{ route: '/my_page', components: ['ExampleComponent'] },
You're now ready to start developing your ExampleComponent
.
npm run dev
How to use in the Mononoth
You will only be able to use components in the Mononoth that have been defined in src/client/index.js
.
In order to use these components, you will need to:
- publish the
@noths/mono-components
package
- bump the version of the package in hypernova-app
- create a PR with the version bump
- verify that everything works as expected in QA
- release to production by merging the PR
In order to test your components in development with the Mononoth after bumping the version in hypernova-app
, you will need to uncomment/comment-out the lines in the mononoth that specifies where the integration file will be served from before starting the Mononoth and the hypernova-app
server.
Main steps of how to render a component in the Mononoth:
In your .erb
view file:
<%= render_react_component(
'Search_Sidebar',
exampleProp: 'exampleText',
filters: { ... }
) if hypernova_enabled? %>
At the end of your view layout file:
<%= include_hypernova_integration_script %>
In the controller that renders your view using the above layout:
class ExampleController
include HypernovaRenderHelper
around_action :hypernova_render_support, if: :hypernova_enabled?
...
end
A note on caching
You must ensure that your rendered mono-component is not inside a fragment-cached block. These blocks usually start with the <% cache
-prefix.
You might also want to look into other forms of Rails caching such as "Action Caching".
In essence, you must "carve out" a path to your component that will not be cached through Rails in any way. The handling of component cache is done in hypernova itself.
A note on component-props
In order to render your component correctly, you will need to collect some data from the Mononoth to pass into your component as props. How to get this data will vary, it is suggested you find someone who is comfortable in working with Rails to help with this.
How to test
It is a bit difficult to test hypernova renders since they are async. We can however do some basic checks.
require 'feature_spec_helper'
describe 'shared/_search_sidebar', type: :view do
let(:component_name) { "Search_Sidebar" }
let(:props) do
{
exampleProp: 'exampleText',
filters: { ... }
}
end
let(:component_placeholder) { "dummy text" }
before(:each) do
allow(view).to receive(:current_filters).and_return({})
allow(view).to receive(:filter_groups).and_return({ price: [] })
allow(view).to receive(:render_react_component).with(component_name, props).and_return(component_placeholder)
end
context "with feature flag on" do
it do
allow(view).to receive(:feature_on?).with(:hypernova).and_return(true)
render
expect(view).to have_received(:render_react_component).with(component_name, props)
expect(rendered).to include(component_placeholder)
end
end
context "with feature flag off" do
it do
render
expect(view).not_to have_received(:render_react_component).with(component_name, props)
expect(rendered).not_to include(component_placeholder)
end
end
end
Building for Production
npm run build
Publishing
Release version
Please refer to the frontend-packages Readme for the release process of patch, minor or major versions.
Releasing a Beta version
While logged into npm with your username, run:
npm run prerelease
Testing & Code-Style
npm test
npm run format
npm run lint
Feature-Test Workflow
none as of now
Error Logging
No logging is being used in this package.
CI
CI is done via lerna in frontend-packages root
Analytics
No Analytics is being done in this package.