Skip to content

Commit

Permalink
Converted pets to contacts
Browse files Browse the repository at this point in the history
  • Loading branch information
ChadLefort committed Feb 5, 2021
1 parent 853fc59 commit 94448a2
Show file tree
Hide file tree
Showing 96 changed files with 537 additions and 552 deletions.
11 changes: 11 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
stage("Building Distributed Tasks for Only Affected Apps") {
echo "Building Distributed Tasks for Only Affected Apps"
}

stage("Run Distributed Tasks") {
echo "Run Distributed Tasks"
}

stage("Build and Deploy Docker Containers") {
echo "Build and Deploy Docker Containers"
}
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Micro Frontend with Webpack 5 Module Federation

This is the same pets demo application that I have in other repos, but this one demonstrates [Webpack 5 Module Federation](https://webpack.js.org/concepts/module-federation/). Both `remote/nav` and `remote/pets` are federated modules. The idea being that the federated modules are features that build up app functionality and require frequent updates. While everything in `shared` directory are libraries that can help build up a federated module (utilities and shared components). The host application that serves these modules is in `apps/cats`. The application also features the concept of injectable redux reducers.
This is the a demo application that demonstrates [Webpack 5 Module Federation](https://webpack.js.org/concepts/module-federation/). Both `mfe/nav` and `mfe/contacts` are federated modules. The idea being that the federated modules are features that build up app functionality and require frequent updates. While everything in `shared` directory are libraries that can help build up a federated module (utilities and shared components). The host application that serves these modules is in `apps/connect`. The application also features the concept of injectable redux reducers.

I put this all together in a monorepo using NX. I find this to be a better workflow than splitting modules into separate repos. Having both applications and modules living together in the same repo while using some monorepo tooling (Lerna/NX/Rush) to manage it all is a great developer experience in my opinion. Instead of fighting with `npm link`, managing multiple repos, and running multiple commands, just running one command to get started with development is very nice.

Expand All @@ -22,10 +22,10 @@ pnpm i && pnpm run start

Then navigate to `http:https://localhost:1337`

If you want to just run a shared module you can do either of these if you have NX installed globally. From the root directory run the following and just replace `remote_nav` or the directory with the module you want to run:
If you want to just run a shared module you can do either of these if you have NX installed globally. From the root directory run the following and just replace `mfe_nav` or the directory with the module you want to run:

```
nx run remote_nav:start
nx run mfe_nav:start
cd shared/nav && pnpm run start
```

Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions apps/cats-e2e/cypress.json → apps/connect-e2e/cypress.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"modifyObstructiveCode": false,
"supportFile": "./src/support/index.ts",
"video": true,
"videosFolder": "../../dist/cypress/apps/cats-e2e/videos",
"screenshotsFolder": "../../dist/cypress/apps/cats-e2e/screenshots",
"videosFolder": "../../dist/cypress/apps/connect-e2e/videos",
"screenshotsFolder": "../../dist/cypress/apps/connect-e2e/screenshots",
"chromeWebSecurity": false,
"experimentalNetworkStubbing": true
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@pet-tracker/cats-e2e",
"name": "@fake-company/connect-e2e",
"version": "1.0.0",
"private": true,
"license": "UNLICENSED",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { getToolbarAppName } from '../support/app.po';

describe('cats', () => {
describe('connect', () => {
beforeEach(() => {
cy.visit('/');
cy.route2('GET', '/api/auth', { fixture: 'auth.json' });
cy.route2('GET', '/api/pets?type=Cat', { fixture: 'pets.json' });
cy.route2('GET', '/api/contacts?type=Cat', { fixture: 'contacts.json' });
});

it('should contain app name in toolbar', () => {
getToolbarAppName().contains('Cats');
getToolbarAppName().contains('Connect');
});
});
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
10 changes: 5 additions & 5 deletions apps/cats/package.json → apps/connect/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@pet-tracker/cats",
"name": "@fake-company/connect",
"version": "1.0.0",
"main": "src/index.tsx",
"license": "UNLICENSED",
Expand All @@ -11,10 +11,10 @@
"dependencies": {
"@material-ui/core": "4.11.3",
"@material-ui/icons": "4.11.2",
"@pet-tracker/auth": "1.0.0",
"@pet-tracker/common-ui": "1.0.0",
"@pet-tracker/types": "1.0.0",
"@pet-tracker/utils": "1.0.0",
"@fake-company/auth": "1.0.0",
"@fake-company/common-ui": "1.0.0",
"@fake-company/types": "1.0.0",
"@fake-company/utils": "1.0.0",
"@reduxjs/toolkit": "1.5.0",
"axios": "0.21.1",
"react": "16.14.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Cats</title>
<title>Connect</title>
</head>
<body>
<div id="root"></div>
Expand Down
11 changes: 5 additions & 6 deletions apps/cats/src/app/App.tsx → apps/connect/src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import { orange } from '@material-ui/core/colors';
import { Auth } from '@pet-tracker/auth';
import { Layout, Theme } from '@pet-tracker/common-ui';
import { Auth } from '@fake-company/auth';
import { Layout, Theme } from '@fake-company/common-ui';
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';

import { Providers } from './Providers';
import { Routes } from './Routes';

const Nav = React.lazy(() =>
import('remote_nav/features/core/components/Nav').then((module) => ({ default: module.Nav }))
import('mfe_nav/features/core/components/Nav').then((module) => ({ default: module.Nav }))
);

export const App: React.FC = () => (
<Providers>
<Router>
<Theme primaryColor={orange[400]}>
<Theme>
<Auth>
<Layout nav={<Nav title="Cats" />}>
<Layout nav={<Nav title="Connect" />}>
<Routes />
</Layout>
</Auth>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Provider } from 'react-redux';
import { store } from './store';

const PetsProvider = React.lazy(() =>
import('remote_pets/features/core/components/PetsProvider').then((module) => ({
import('mfe_contacts/features/core/components/PetsProvider').then((module) => ({
default: module.PetsProvider
}))
);
Expand Down
12 changes: 6 additions & 6 deletions apps/cats/src/app/Routes.tsx → apps/connect/src/app/Routes.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { PetType } from '@pet-tracker/types';
import { PetType } from '@fake-company/types';
import React, { Suspense } from 'react';
import { Route, Switch } from 'react-router-dom';

import { store } from './store';

const EditPet = React.lazy(() =>
import('remote_pets/features/core/components/EditPet').then((module) => ({ default: module.EditPet }))
import('mfe_contacts/features/core/components/EditPet').then((module) => ({ default: module.EditPet }))
);

const AddPets = React.lazy(() =>
import('remote_pets/features/core/components/AddPets').then((module) => ({ default: module.AddPets }))
import('mfe_contacts/features/core/components/AddPets').then((module) => ({ default: module.AddPets }))
);

const ViewPet = React.lazy(() =>
import('remote_pets/features/core/components/ViewPet').then((module) => ({ default: module.ViewPet }))
import('mfe_contacts/features/core/components/ViewPet').then((module) => ({ default: module.ViewPet }))
);

const ViewPets = React.lazy(() =>
import('remote_pets/features/core/components/ViewPets').then((module) => ({ default: module.ViewPets }))
import('mfe_contacts/features/core/components/ViewPets').then((module) => ({ default: module.ViewPets }))
);

const PetsProvider = React.lazy(() =>
import('remote_pets/features/core/components/PetsProvider').then((module) => ({
import('mfe_contacts/features/core/components/PetsProvider').then((module) => ({
default: module.PetsProvider
}))
);
Expand Down
4 changes: 2 additions & 2 deletions apps/cats/src/app/store.ts → apps/connect/src/app/store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { authRootReducer } from '@pet-tracker/auth';
import { InjectStore } from '@pet-tracker/types';
import { authRootReducer } from '@fake-company/auth';
import { InjectStore } from '@fake-company/types';
import { Reducer, combineReducers, configureStore } from '@reduxjs/toolkit';

const staticReducers = {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
19 changes: 7 additions & 12 deletions apps/cats/webpack.config.ts → apps/connect/webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import HtmlWebpackPlugin from 'html-webpack-plugin';
import path from 'path';
import { container, WebpackOptionsNormalized } from 'webpack';

const DashboardPlugin = require('@module-federation/dashboard-plugin');
const webpackConfig = (_env: { production: string; development: string }, argv: WebpackOptionsNormalized) => {
const { name, dependencies } = require('./package.json');
const entry = './src/index.ts';
Expand All @@ -24,14 +23,14 @@ const webpackConfig = (_env: { production: string; development: string }, argv:

config.plugins = config.plugins?.concat([
new container.ModuleFederationPlugin({
name: '@pet-tracker/cats',
name: '@fake-company/connect',
remotes: {
remote_nav: isDevelopment
? 'remote_nav@http:https://localhost:1338/remoteEntry.js'
: 'remote_nav@http:https://localhost/nav/remoteEntry.js',
remote_pets: isDevelopment
? 'remote_pets@http:https://localhost:1339/remoteEntry.js'
: 'remote_pets@http:https://localhost/pets/remoteEntry.js'
mfe_nav: isDevelopment
? 'mfe_nav@http:https://localhost:1338/mfeEntry.js'
: 'mfe_nav@http:https://localhost/nav/mfeEntry.js',
mfe_contacts: isDevelopment
? 'mfe_contacts@http:https://localhost:1339/mfeEntry.js'
: 'mfe_contacts@http:https://localhost/contacts/mfeEntry.js'
},
shared: {
...dependencies,
Expand All @@ -40,10 +39,6 @@ const webpackConfig = (_env: { production: string; development: string }, argv:
}),
new HtmlWebpackPlugin({
template: './public/index.html'
}),
new DashboardPlugin({
filename: 'dashboard.json',
dashboardURL: 'http:https://localhost:3000/api/update'
})
]);

Expand Down
31 changes: 12 additions & 19 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,31 @@ services:
ports:
- 80:80
networks:
- pt-network
- fake-company-network
json-server:
build: ./tools/json-server
ports:
- '4000:4000'
networks:
- pt-network
mf-dashboard:
container_name: mf-dashboard-container
image: scriptedalchemy/mf-dashboard:latest
ports:
- '3000:3000'
networks:
- pt-network
pt-cats:
build: ./apps/cats
- fake-company-network
fake-company-connect:
build: ./apps/connect
ports:
- '1337:1337'
networks:
- pt-network
pt-nav:
build: ./remote/nav
- fake-company-network
fake-company-nav:
build: ./mfe/nav
ports:
- '1338:1338'
networks:
- pt-network
pt-pets:
build: ./remote/pets
- fake-company-network
fake-company-contacts:
build: ./mfe/contacts
ports:
- '1339:1339'
networks:
- pt-network
- fake-company-network
networks:
pt-network:
fake-company-network:
driver: bridge
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions remote/pets/jest.config.js → mfe/contacts/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ const { compilerOptions } = require('../../tsconfig.base.json');
module.exports = {
preset: 'ts-jest',
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/../../' }),
displayName: 'remote_pets',
coverageDirectory: '../../coverage/shared/pets'
displayName: 'mfe_contacts',
coverageDirectory: '../../coverage/shared/contacts'
};
8 changes: 4 additions & 4 deletions remote/pets/package.json → mfe/contacts/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "remote_pets",
"name": "mfe_contacts",
"version": "1.0.0",
"main": "src/index.ts",
"license": "UNLICENSED",
Expand All @@ -14,9 +14,9 @@
"dependencies": {
"@material-ui/core": "4.11.3",
"@material-ui/icons": "4.11.2",
"@pet-tracker/common-ui": "1.0.0",
"@pet-tracker/types": "1.0.0",
"@pet-tracker/utils": "1.0.0",
"@fake-company/common-ui": "1.0.0",
"@fake-company/types": "1.0.0",
"@fake-company/utils": "1.0.0",
"@reduxjs/toolkit": "1.5.0",
"axios": "0.21.1",
"final-form": "4.20.1",
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion remote/pets/src/App.tsx → mfe/contacts/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PetType } from '@pet-tracker/types';
import { PetType } from '@fake-company/types';
import React from 'react';
import { Provider } from 'react-redux';
import { BrowserRouter as Router } from 'react-router-dom';
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { PetForm } from './Form';
import { withTheme } from '@pet-tracker/common-ui';
import { withTheme } from '@fake-company/common-ui';

const story = {
component: PetForm,
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { Action, ThunkAction, combineReducers, configureStore } from '@reduxjs/toolkit';
import { createSelectorHook, useDispatch } from 'react-redux';

import { petsReducer } from '../features/core/pets.slice';
import { contactsReducer } from '../features/core/contacts.slice';

export const injectableReducer = combineReducers({ core: petsReducer });
export const injectableReducer = combineReducers({ core: contactsReducer });

export const petsRootReducer = {
pets: injectableReducer
export const contactsRootReducer = {
contacts: injectableReducer
};

// just for types and test
export const store = configureStore({ reducer: petsRootReducer });
export const store = configureStore({ reducer: contactsRootReducer });

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
Expand Down
16 changes: 16 additions & 0 deletions mfe/contacts/src/features/core/components/AddContacts.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import { AddContacts } from './AddContacts';
import { contactsRootReducer, RootState } from '../../../common/reducer';
import { ContactType } from '@fake-company/types';
import { withProvider } from '@fake-company/utils';
import { withTheme } from '@fake-company/common-ui';

const story = {
component: AddContacts,
title: 'AddContacts',
decorators: [withTheme, withProvider<RootState>(contactsRootReducer)]
};

export default story;

export const primary = () => <AddContacts type={ContactType.Cat} />;
Loading

0 comments on commit 94448a2

Please sign in to comment.