L&L March 2022
Steve Olsen
GOALS:
What's all the ado?
Modules (internal)
vs.
Libraries (external)
Dependencies
i.e. "highly-decoupled code"
For an example experience, see:
https://www.youtube.com/watch?v=0_qhdOeMuhk
*General tools, where any dependants don't affect them.*
PR: link
"so many modules!"
*widget: smart components
*libs: pure functions/code
*layouts: adapt to their container size
Sharing is caring!
branchA.branchB.leaf
import @/branch-a/branch-b/leaf
/src/
/ui/
/pages/
/checkout/
index.ts
Page.ts << imports ./select-box-auto
/select-box-auto/...
/src/
/ui/
/common/
/components/
/select-box-auto/...
/pages/
/checkout/
index.ts
Page.ts << imports ../../common/components/select-box-auto
/sign-up/
index.ts
Page.ts << imports ../../common/components/select-box-auto
/src/
/ui/
/pages/
/checkout/
index.ts
Page.ts << imports ./cart
/cart/...
/src/
/ui/
/common/
/widgets/
/cart/...
/pages/
/checkout/
index.ts
Page.ts << imports ../../common/widgets/cart
/orders/
index.ts
Page.ts << imports ../../common/widgets/cartgeneralize
specialize
all your code is share to us
// Assuming NextJS
package.json
/pages/... <<< routing {URL:Page} and {URL:API}
/src/
/api/... <<< define HTTP API handlers
/common/ <<< eg. libs, frmt, types, validators, etc.
/libs/
/ui/
/common/... <<< Atlas, etc.
/widgets/
/components/
/libs/
/[vertical]/
/pages/...
/widgets/...
/components/...
folder structure
// Assuming yarn workspaces
package.json
/apps/ <<< self bundled / deployable units
/web-uni/...
/web-money/...
/web-travel/...
/web-shop/...
/packages/ <<< sharable units
/@web-common/... <<< eg. libs, types, validators, etc.
/@web-[vertical]/
/pages/...
/widgets/...
/components/...
Each /apps/* deploys its own bundle
folder structure
packages/@web-uni/nav
packages/@web-uni/nav
app/web-uni/pages
packages/
@web-snapmoney/ components/
cta-activate/...
packages/
@web-snaptravel/ widgets/
bookings/...
packages/
@web-snapshop/ widgets/
daily-deals/...
packages/
@web-common/ components/
cta-ad/...
<html>
<head>
<script src="./app/main.js"></script>
<script src="./app/nav.js"></script>
<script src="./app/travel.js"></script>
<script src="./app/shop.js"></script>
<script src="./app/money.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>verticals = travel, shop, money, .....
import React, { Suspense, lazy } from "react";
...
const MoneyPage = lazy(() => import("./pkg-money/Home"));
...
<Suspense fallback={<div>Loading...<div>}>
<Switch>
<Route exact={true} path="/money" component={MoneyPage} />ES "async loading" other packages
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const mode = process.env.NODE_ENV || 'production';
module.exports = {
mode,
entry: './src/index',
devtool: 'source-map',
optimization: {
minimize: mode === 'production',
},
resolve: {
extensions: ['.jsx', '.js', '.json'],
},
module: {
rules: [ /* ... */ ],
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
}),
new ModuleFederationPlugin({
name: 'remote', // this name needs to match with the entry name
// ...
}),
],
};// Assuming yarn workspaces
package.json
/packages/
/@pkg-main-app/
/@pkg-common/ <<< eg. libs, types, validators, etc.
/@pkg-[vertical]/
/pages/
/widgets/
/components/
Each package is self-hosted and deployed
Folder structure
Note: Libs/Components:
<html>
<head>
<script src="./app/main.js"></script>
<script src="./app/nav.js"></script>
<script src="./app/travel.js"></script>
<script src="./app/shop.js"></script>
<script src="./app/money.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>localhost
localhost
stagging
Questions?