iot-manager v1.0.0
IoT Manager
IoT Shared Capability (Wombat) Device Manager web application.
Setup
Create new
.npmrcfile in project root.touch .npmrcAdd the following to the
.npmrcfile.registry=https://pkgs.dev.azure.com/BuiltEnvironmentEngineering/09552df7-02fe-4661-831c-bc01d67336e9/_packaging/iot-manager/npm/registry/ always-auth=true auto-install-peers=true strict-peer-dependencies=falseIf you are using preproxy configuration here then you will also need to add the following to your
.npmrcfileproxy=http://127.0.0.1:3128 https-proxy=http://127.0.0.1:3128Setup credentials according to these instructions. The technique is slightly different on Windows compared to Mac/Linux.
Once the process is done, your user
.npmrcfile will end up looking like the following example.; begin auth token //pkgs.dev.azure.com/BuiltEnvironmentEngineering/09552df7-02fe-4661-831c-bc01d67336e9/_packaging/iot-manager/npm/registry/:username=BuiltEnvironmentEngineering //pkgs.dev.azure.com/BuiltEnvironmentEngineering/09552df7-02fe-4661-831c-bc01d67336e9/_packaging/iot-manager/npm/registry/:_password=[BASE64_ENCODED_PERSONAL_ACCESS_TOKEN] //pkgs.dev.azure.com/BuiltEnvironmentEngineering/09552df7-02fe-4661-831c-bc01d67336e9/_packaging/iot-manager/npm/registry/:email=npm requires email to be set but doesn't use the value //pkgs.dev.azure.com/BuiltEnvironmentEngineering/09552df7-02fe-4661-831c-bc01d67336e9/_packaging/iot-manager/npm/:username=BuiltEnvironmentEngineering //pkgs.dev.azure.com/BuiltEnvironmentEngineering/09552df7-02fe-4661-831c-bc01d67336e9/_packaging/iot-manager/npm/:_password=[BASE64_ENCODED_PERSONAL_ACCESS_TOKEN] //pkgs.dev.azure.com/BuiltEnvironmentEngineering/09552df7-02fe-4661-831c-bc01d67336e9/_packaging/iot-manager/npm/:email=npm requires email to be set but doesn't use the value ; end auth tokenInstall
pnpm. Follow the installation instructions here.Install packages. Optionally connect to VPN if you can't connect to Azure without VPN.
pnpm installpnpm installwill install workspace dependencies such ashuskyandnxspecified in workspacepackage.jsonas well as all project dependencies in/packages/specified in theirpackage.jsonfile.Setup git hooks by running
pnpm -w prepare.This will tell
pnpmto runpreparescript specified in workspace levelpackage.jsonwhich sets up your git hooks which is used for running linters on changed files pre-commit.Setup local environment to sign-in with CAIMAN.
Local CAIMAN sign-in only works on http://idm-local.test.com:3000. This is because a URL must be whitelisted to work with CAIMAN for CORS purposes.
idm-local.test.comis the whitelisted URL for local development. See Authentication with CAIMAN for more details.Add
127.0.0.1 idm-local.test.comto your computer's hosts file and open the web app on http://idm-local.test.com:3000.# hosts file entry 127.0.0.1 idm-local.test.com
How to run
To run container app, we need to first build and generate compiled js code of core which will be located in iot-manager/packages/core/dist after running build in core. This will be used by the other projects. Second, we also need Auth MFE and device manager MFE running so webpack-dev-server can start serving entry point file to auth MFE (localhost:8082/remoteEntry.js) and device manager MFE (localhost:8083/remoteEntry.js) which will be consumed by container during runtime.
Using pnpm and nx
Simply run pnpm -w local:all
Alternatively without pnpm and nx you can do the following
- Go to
packages/coreandnpm run build - Go to
packages/authandnpm run local - Go to
packages/device-managerandnpm run local - Go to
packages/containerandnpm run local - Visit
localhost:8083to view and test device manager MFE in isolation - Visit
localhost:8082to view and test auth MFE in isolation - Visit
localhost:8081to view and test container app which also renders auth and device manager MFEs
Linters
How to setup git hooks
Run pnpm -w prepare in any directory as long as it is located in the iot-manager project/workspace. This will setup your git hooks and make sure eslint and stylelint are executed to check your js, jsx, ts, tsx, scss, and css files pre-commit.
How to run
Using pnpm and nx
Simply run
pnpm -w lint:all
pnpm -w stylelint:allTo run npm script for executing eslint in a single project anywhere in the workspace
pnpm nx lint {project-name i.e auth}
pnpm nx stylelint {project-name i.e auth}Alternatively without pnpm and nx you can do the following
npm run lint - Run this inside each individual project folders
packages/core
packages/auth
packages/device-manager
packages/containernpm run lint:fix - Run this inside each individual project folders as above. This goes through all .js, .ts and .tsx and automatically fix issues that it finds and report those it cannot fix.
TODO:
ā HMR for ts/js/stylesheets (not supported by webpack yet)
Styling
Class naming standard
For tailwind custom component class names and custom classes defined in stylesheets, we use https://css-tricks.com/abem-useful-adaptation-bem/ to avoid clashing class names between MFEs.
Use the atomic prefix when creating class names for components i.e. for class names used for components in components/atoms folder, prefix it with {projectName}-a-{blockName}__elementName -modifierName
Working with clean architecture
Clean architecture overview and example
Creating Repo and Service/Usecase/Interactor classes
Tests
Setup
WIP
How to run
Using pnpm and nx
Simply run
pnpm -w test:unit:allTo run npm script for executing unit tests in a single project anywhere in the workspace
pnpm nx test:unit {project-name i.e auth}Alternatively without pnpm and nx you can do the following
Run npm run test:unit in each individual project folder
CI/CD
Webpack prod config
webpack.prod.js contains your webpack prod deployment config. There will only be few differences in prod config vs development config.
- No
devServeras we are no longer hosting the app locally viawebpack-dev-server output.publicPathwill be different due to the same reason above and also because we might also want to tellwebpackto retrieve the MFE assets under a different base path in the same domain. For example, so you might want to set it to/auth/latest/which will tell webpack to retrieve the MFEremoteEntry.jsfrom${domain}/auth/latest/remoteEntry.jsinstead of${domain}/remoteEntry.jswhich you will be able to see in the generatedindex.htmlscript tag.
Publishing to Azure Artifacts
Libraries published on the Nexus repository needs to be re-published on Azure Artifacts so that the pipeline can run. This is important as Azure can't reach Nexus at this time.
Refer to Azure Artifacts for details on re-republishing libraries.
Deployment Pipeline Flow
- After code has been merged to
masterbranch, it triggers the pipeline - Pipeline checks where the changes are located (which MFE folder)
- Depending on where the changes are located, pipeline will go into the specific MFE folder
- Install dependencies
- Build and generate compiled code using
webpack, defaultwebpackoutput should be in/distfolder - Upload the content of
/distfolder to hosting service, and make sure when uploading/dist, it is uploaded to the correct folder based on what you have set as base asset path in yourwebpack.prod.jsoutput.publicPathi.e. ifoutput.publicPathis set to/container/latest/, then upload the/distcontent to that same path - Invalidate CDN cache so it stops serving stale
index.html/remoteEntry.js
FAQs
1. Is it safe to use unstable_HistoryRouter from react-router v6?
Yes, as mentioned in the react-router document, it is only prefixed with unstable_ because react-router does not have a mechanism to detect mis-matched history version which will be removed once they have fixed this. This can only happen when we add and install history dependency ourselves. By default when installing react-router, it also installs history in our node_modules, as long as we are aware of this and don't add history library in our package.json we should be fine.
2. How auth state is stored and shared across all MFEs
Auth state and logic
- Container app manages auth state
- Store auth state in either local (persisted after closing browser or tab) or session storage (disappears after closing tab or browser) after successful login
- When first time application is loaded, check local / session storage to see if user is authenticated i.e. valid jwt token exists
- If jwt token exists, container app needs to update its local react state for tracking auth state let's call it
isLoggedInand set this to true. - Container then simple passes
isLoggedInto other MFEs - Whenever user logs in via the auth MFE, it will need to notify container app. This can be done by passing callback fn from container app to auth MFE for auth MFE to call after successfully logging user in, this callback fn will simply change auth state in container app when called.
3 years ago