- By reusing your own components you can save development time, keep your UI consistent across applications and let your whole team build together.
- No need to create a UI library for reusable components across apps.
- Create Shared UI App to create UI components. Deploy Shared UI App and Dynamically load a React Component from that URL using remote-component.
- You can also add shared styles and common files in Shared App which you want to reuse.
- The RemoteComponent React Component takes a URL as a prop. The URL is loaded and processed. This file must be a valid CommonJS Module that exports the component as default.
- While the URL is loading, the fallback will be rendered. This is a similar pattern to React.Suspense. If no fallback is provided, then nothing will be rendered while loading.
- Once loaded, there will either be an error a Component. The rendering will first be handled by the render callback function. If there is no render callback and err exists, a generic message will be shown.
- The Component will be rendered either to the render callback if one exists, otherwise, it will be rendered as a standard component.
- To use UI Components in all the apps you have to follow this for all the apps.
- Install remote-component
$ npm install @paciolan/remote-component --save- Remote Components will require some dependencies to be injected into them. At the minimum, we'll be injecting the React dependency.
- The web application can include dependencies and inject them into the RemoteComponent. At a minimum, you will probably need the react dependency.
- Create a file remote-component.config.js in the root of the web application.
- If you are using any library or package that the Ui component is using then you have to add that dependency in this file.
- ex: If you are using Material-UI to create a UI component then you have to add material-ui as a dependency in this file like this:
["@material-ui/core"]: require("@material-ui/core")
/** * remote-component.config.js * Dependencies for Remote Components */ module.exports = { resolve: { react: require("react") } };- Create a file named RemoteComponent.js in the src folder.
- Export RemoteComponent with the requires from remote-component.config.js. This will inject the dependencies into the RemoteComponent.
/* * src/components/RemoteComponent.js */ import { createRemoteComponent, createRequires } from "@paciolan/remote-component"; import { resolve } from "../remote-component.config.js"; const requires = createRequires(resolve); export const RemoteComponent = createRemoteComponent({ requires });- Usage:
- Create a file that exports al UI components.
import { RemoteComponent } from "./RemoteComponent"; const element = document.getElementById("app"); const url = "https://raw.githubusercontent.com/Paciolan/remote-component/master/examples/remote-components/HelloWorld.js"; const HelloWorld = props => <RemoteComponent url={url} render={({ err, Component }) => err ? <div>{err.toString()}</div> : <Component {...props} /> } /> ); export default HelloWorld; - Now you can import HelloWorld component in your app like this:
import { HelloWorld } from "./index"; - To use UI components in all the apps you have to add this configuration in all the apps.
- To Create a Shared UI app follow this configuration.
- Create a Folder named Shared.
- Create a folder named src/UI(Or name you want).
- Create Components in the UI folder.
- Ex: To create a Label component in src folder create a file Label.js
import React from 'react'; import Typography from '@material-ui/core/Typography'; export default function Title(props) { return ( <Typography component="h2" variant="h6" color="primary" gutterBottom> {props.children} </Typography> ); } - UI Component Label is created.
- Create package.json at the root of the app.
- Add all dependencies in the package.json which is required to create UI component.
- Ex: Title Component is required material-ui, So Install material-ui first.
- If you want common CSS across all the apps or any common file that is used by all the apps then you can add it in the src folder.
- This file must be a valid CommonJS Module that exports the component as default, So we have to convert es6 files to commonjs.
- Create .babelrc in the root folder.
{ "presets": [ "minify", "@babel/preset-react", "@babel/env" ], "plugins": [ "@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-object-rest-spread" ] } - Install "@babel/preset-react", "@babel/env", "@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-object-rest-spread".
- Add scripts in package.json to convert es6 files to commonJs module using babel.
"scripts": { "build": "babel ./src --out-dir build --extensions '.ts,.tsx,.js,.jsx' && cp ./src/index.css build/", "start": "serve --port 5000 --cors build" }, - When you run npm run build, It will convert all files from src directory and add it in build directory and copy index.css file in the build folder.
- Now to use shared components and styles you have to serve build folder.
- You can get components js file from http://localhost:5001/UI/Label.js
- There are 2 apps created in this repo app1 and app2 which are using the shared app for reusable components.
- Created Remore-Component.jsx and remote-component-config.js files and are the same for both apps.
/** * remote-component.config.js * * Dependencies for Remote Components */ module.exports = { resolve: { react: require("react"), ["@material-ui/core"]: require("@material-ui/core"), ["@material-ui/icons"]: require("@material-ui/icons"), ["@material-ui/core/Link"]: require("@material-ui/core/Link"), ["@material-ui/core/styles"]: require("@material-ui/core/styles"), ["@material-ui/core/Typography"]: require("@material-ui/core/Typography"), ["recharts"]: require("recharts") } }; import { createRemoteComponent } from "@paciolan/remote-component/dist/lib/createRemoteComponent"; import { createRequires } from "@paciolan/remote-component/dist/lib/createRequires"; import { resolve } from "./remote-component.config.js"; const requires = createRequires(resolve); export const RemoteComponent = createRemoteComponent({ requires }); - Created indexShared.js file for add all UI components.
import React from "react"; import { RemoteComponent } from "./RemoteComponent"; const Title = (props) => { const url1 = "http://localhost:5000/ui/Title.js"; return ( <RemoteComponent url={url1} render={({ err, Component }) => err ? <div>{err.toString()}</div> : <Component {...props} /> } /> ); }; export { Title }; const Deposits = (props) => { const url = "http://localhost:5000/ui/Deposits.js"; return ( <RemoteComponent url={url} render={({ err, Component }) => err ? <div>{err.toString()}</div> : <Component {...props} /> } /> ); }; export { Deposits }; const Chart = (props) => { const url = "http://localhost:5000/ui/Chart.js"; return ( <RemoteComponent url={url} render={({ err, Component }) => err ? <div>{err.toString()}</div> : <Component {...props} /> } /> ); }; export { Chart }; const Orders = (props) => { const url = "http://localhost:5000/ui/Orders.js"; return ( <RemoteComponent url={url} render={({ err, Component }) => err ? <div>{err.toString()}</div> : <Component {...props} /> } /> ); }; export { Orders }; const listItems = (props) => { const url = "http://localhost:5000/ui/listItems.js"; return ( <RemoteComponent url={url} render={({ err, Component }) => err ? <div>{err.toString()}</div> : <Component {...props} /> } /> ); }; export { listItems }; - imported all UI components in Dashboard.js file
import { Title, Deposits, Chart, Orders } from "./indexShared"; - Created a Shared folder for reusable components.
- Created the Common/ui folder and added all reusable components in ui folder.
- Created index.css file in the Common folder to reuse the same style in all the apps.
- Clone the repo
- Open each app and run npm install.
- Open Shared app and run npm run build
- Run all the apps by npm start
app1: http://localhost:3001 app2: http://localhost:3002 shared: http://localhost:5000 - UI components Chart, Deposits, Orders, and Title are shared with both the apps.
