Skip to content

Commit 515ed0f

Browse files
jacob-ebeyForestry.io
authored andcommitted
Update from Forestry.io
Jacob Ebey updated src/posts/get-started.md
1 parent 71747f1 commit 515ed0f

File tree

1 file changed

+20
-95
lines changed

1 file changed

+20
-95
lines changed

src/posts/get-started.md

Lines changed: 20 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ title: Getting Started With Federated Modules
33
secondary_title: get up and running in 15 minutes
44
author: Jacob Ebey
55
date: 2020-03-29T16:04:26.000+00:00
6-
---
76

7+
---
88
# A Little Background
99

1010
If you've worked as a developer long enough, you've ran into the inevitable problem of sharing components between teams. Let's be real here, how often does this lead to a good experience for anyone?
@@ -15,14 +15,13 @@ I think [Zack Jackson](https://indepth.dev/webpack-5-module-federation-a-game-ch
1515
1616
If you would like to learn more about Webpack Module Federation, you can head over to the [Learn More](/learn-more) page.
1717

18-
1918
# What We Are Building
2019

2120
We are going to build out two separate Single Page Applications (SPA) that use Module Federation to share components during runtime.
2221

2322
`Application A` will contain a `SayHelloFromA` component that will be consumed by `Application B` while `Application B` will contain a `SayHelloFromB` component that will be consumed by `ApplicationA`. This looks like:
2423

25-
<Image alt="architecture diagram" size="large" src={getStartedDiagram} style={{ margin: "2rem auto" }} />
24+
![](/static/get-started-diagram.svg "Architecture Diagram")
2625

2726
This architecture will allow each SPA to be developed and deployed independantly along with instantly recieving updates from other federated applications with zero deployments.
2827

@@ -39,87 +38,27 @@ Start by creating a new project folder with the following `package.json` to allo
3938
**package.json**
4039

4140
<SyntaxHighlighter language="json" style={ghcolors}>
42-
{`{
43-
"name": "federation-example",
44-
"private": true,
45-
"workspaces": [
46-
"packages/*"
47-
],
48-
"scripts": {
49-
"start": "wsrun --parallel start",
50-
"build": "yarn workspaces run build",
51-
"dev": "wsrun --parallel dev"
52-
},
53-
"devDependencies": {
54-
"wsrun": "^5.2.0"
55-
}
56-
}`}
41+
{`{ "name": "federation-example", "private": true, "workspaces": [ "packages/*" ], "scripts": { "start": "wsrun --parallel start", "build": "yarn workspaces run build", "dev": "wsrun --parallel dev" }, "devDependencies": { "wsrun": "^5.2.0" } }`}
5742
</SyntaxHighlighter>
5843

5944
We will now create two folders for our SPAs to live in under a new `packages` directory called `application-a` and `application-b`, these will respectively contain the following `package.json` files:
6045

6146
**packages/application-a/package.json**
6247

6348
<SyntaxHighlighter language="json" style={ghcolors}>
64-
{`{
65-
"name": "application-a",
66-
"version": "1.0.0",
67-
"private": true,
68-
"scripts": {
69-
"start": "serve dist -p 3001",
70-
"build": "webpack --mode production",
71-
"dev": "concurrently \\"webpack --watch\\" \\"serve dist -p 3001\\""
72-
},
73-
"dependencies": {
74-
"react": "^16.13.1",
75-
"react-dom": "^16.13.1"
76-
},
77-
"devDependencies": {
78-
"@babel/core": "^7.8.6",
79-
"@babel/preset-react": "^7.8.3",
80-
"babel-loader": "^8.0.6",
81-
"concurrently": "^5.1.0",
82-
"html-webpack-plugin": "git://github.com/ScriptedAlchemy/html-webpack-plugin#master",
83-
"serve": "^11.3.0",
84-
"webpack": "git://github.com/webpack/webpack.git#dev-1",
85-
"webpack-cli": "^3.3.11"
86-
}
87-
}`}
49+
{`{ "name": "application-a", "version": "1.0.0", "private": true, "scripts": { "start": "serve dist -p 3001", "build": "webpack --mode production", "dev": "concurrently \\"webpack --watch\\" \\"serve dist -p 3001\\"" }, "dependencies": { "react": "^16.13.1", "react-dom": "^16.13.1" }, "devDependencies": { "@babel/core": "^7.8.6", "@babel/preset-react": "^7.8.3", "babel-loader": "^8.0.6", "concurrently": "^5.1.0", "html-webpack-plugin": "git://github.com/ScriptedAlchemy/html-webpack-plugin#master", "serve": "^11.3.0", "webpack": "git://github.com/webpack/webpack.git#dev-1", "webpack-cli": "^3.3.11" } }`}
8850
</SyntaxHighlighter>
8951

9052
**packages/application-b/package.json**
9153

9254
<SyntaxHighlighter language="json" style={ghcolors}>
93-
{`{
94-
"name": "application-b",
95-
"version": "1.0.0",
96-
"private": true,
97-
"scripts": {
98-
"start": "serve dist -p 3002",
99-
"build": "webpack --mode production",
100-
"dev": "concurrently \\"webpack --watch\\" \\"serve dist -p 3002\\""
101-
},
102-
"dependencies": {
103-
"react": "^16.13.1",
104-
"react-dom": "^16.13.1"
105-
},
106-
"devDependencies": {
107-
"@babel/core": "^7.8.6",
108-
"@babel/preset-react": "^7.8.3",
109-
"babel-loader": "^8.0.6",
110-
"concurrently": "^5.1.0",
111-
"html-webpack-plugin": "git://github.com/ScriptedAlchemy/html-webpack-plugin#master",
112-
"serve": "^11.3.0",
113-
"webpack": "git://github.com/webpack/webpack.git#dev-1",
114-
"webpack-cli": "^3.3.11"
115-
}
116-
}`}
55+
{`{ "name": "application-b", "version": "1.0.0", "private": true, "scripts": { "start": "serve dist -p 3002", "build": "webpack --mode production", "dev": "concurrently \\"webpack --watch\\" \\"serve dist -p 3002\\"" }, "dependencies": { "react": "^16.13.1", "react-dom": "^16.13.1" }, "devDependencies": { "@babel/core": "^7.8.6", "@babel/preset-react": "^7.8.3", "babel-loader": "^8.0.6", "concurrently": "^5.1.0", "html-webpack-plugin": "git://github.com/ScriptedAlchemy/html-webpack-plugin#master", "serve": "^11.3.0", "webpack": "git://github.com/webpack/webpack.git#dev-1", "webpack-cli": "^3.3.11" } }`}
11756
</SyntaxHighlighter>
11857

11958
Install the dependancies with:
12059

12160
<SyntaxHighlighter language="bash" style={ghcolors}>
122-
{`> yarn`}
61+
{`> yarn`}
12362
</SyntaxHighlighter>
12463

12564
## Bootstrap The SPAs
@@ -129,57 +68,49 @@ Next up is bootstraping our SPA React applications. We need to create a `src` di
12968
**packages/application-{a,b}/src/index.js**
13069

13170
<SyntaxHighlighter language="javascript" style={ghcolors}>
132-
{`import('./bootstrap');`}
71+
{`import('./bootstrap');`}
13372
</SyntaxHighlighter>
13473

13574
**packages/application-{a,b}/src/bootstrap.jsx**
13675

13776
<SyntaxHighlighter language="javascript" style={ghcolors}>
138-
{bootstrapCodeSample}
77+
{bootstrapCodeSample}
13978
</SyntaxHighlighter>
14079

14180
We also need a `public` directory in each of the packages with the the following html template that we will modify per SPA later:
14281

14382
**packages/application-{a,b}/public/index.html**
14483

14584
<SyntaxHighlighter language="html" style={ghcolors}>
146-
{`<!DOCTYPE html>
147-
<html lang="en">
148-
<head>
149-
</head>
150-
<body>
151-
<div id="root"></div>
152-
</body>
153-
</html>
154-
`}
85+
{`<!DOCTYPE html> <html lang="en"> <head> </head> <body> <div id="root"></div> </body> </html>`}
15586
</SyntaxHighlighter>
15687

15788
Now we can implement our two `app.jsx` files for each application that will house our shared components:
15889

15990
**packages/application-a/src/app.jsx**
16091

16192
<SyntaxHighlighter language="javascript" style={ghcolors}>
162-
{appACodeSample}
93+
{appACodeSample}
16394
</SyntaxHighlighter>
16495

16596
**packages/application-b/src/app.jsx**
16697

16798
<SyntaxHighlighter language="javascript" style={ghcolors}>
168-
{appBCodeSample}
99+
{appBCodeSample}
169100
</SyntaxHighlighter>
170101

171102
And now finally, we'll add our base `webpack.config.js` for each application:
172103

173104
**packages/application-{a,b}/webpack.config.js**
174105

175106
<SyntaxHighlighter language="javascript" style={ghcolors}>
176-
{baseWebpackConfig}
107+
{baseWebpackConfig}
177108
</SyntaxHighlighter>
178109

179110
From the root of the application, you should now be able to access your two SPAs on [http://localhost:3001](http://localhost:3001) and [http://localhost:3002](http://localhost:3002) when runing:
180111

181112
<SyntaxHighlighter language="bash" style={ghcolors}>
182-
{`> yarn dev`}
113+
{`> yarn dev`}
183114
</SyntaxHighlighter>
184115

185116
# Start Federating
@@ -191,7 +122,7 @@ We'll start by adding the `ModuleFederationPlugin` to `Application A`, this will
191122
**packages/application-a/webpack.config.js**
192123

193124
<SyntaxHighlighter language="javascript" style={ghcolors}>
194-
{federationPluginA}
125+
{federationPluginA}
195126
</SyntaxHighlighter>
196127

197128
This specifies that `Application A` exposese it's App component to the world as a Federated Module called `SayHelloFromA`, while whenever you import from `application_b`, those modules should come from `Application B` at runtime.
@@ -201,27 +132,21 @@ We will do the same thing fro `Applicaiton B`, specifying that it exposes it's A
201132
**packages/application-b/webpack.config.js**
202133

203134
<SyntaxHighlighter language="javascript" style={ghcolors}>
204-
{federationPluginB}
135+
{federationPluginB}
205136
</SyntaxHighlighter>
206137

207138
The last step before we can start to utilize the exposed components is to specify for the runtime where the Remote Entries for the Containers you wish to consume are located. We do this by simply adding a script tag to the HTML template of the remotes you wish to consume.
208139

209140
**packages/application-a/public/index.html**
210141

211142
<SyntaxHighlighter language="html" style={ghcolors}>
212-
{`<head>
213-
<!-- The remote entry for Application B -->
214-
<script src="http://localhost:3002/remoteEntry.js"></script>
215-
</head>`}
143+
{`<head> <!-- The remote entry for Application B --> <script src="http://localhost:3002/remoteEntry.js"></script> </head>`}
216144
</SyntaxHighlighter>
217145

218146
**packages/application-b/public/index.html**
219147

220148
<SyntaxHighlighter language="html" style={ghcolors}>
221-
{`<head>
222-
<!-- The remote entry for Application A -->
223-
<script src="http://localhost:3001/remoteEntry.js"></script>
224-
</head>`}
149+
{`<head> <!-- The remote entry for Application A --> <script src="http://localhost:3001/remoteEntry.js"></script> </head>`}
225150
</SyntaxHighlighter>
226151

227152
The remote entry files are tiny mappings for webpack to resolve the individually imported modules without trasfering unnessesary info. They are also responsible for enabling the sharing of libraries that the packages use, in this case, when `Application A` requests `Application B`'s SayHelloFromB component, we do not send the React or ReactDOM over the wire as `Application A` already has a copy of it.
@@ -235,15 +160,15 @@ Starting with `Application A`, we can render the `SayHelloFromB` component like
235160
**packages/application-a/src/bootstrap.jsx**
236161

237162
<SyntaxHighlighter language="javascript" style={ghcolors}>
238-
{applicationAConsumesB}
163+
{applicationAConsumesB}
239164
</SyntaxHighlighter>
240165

241166
`Application B` will look very similar, just importing from `application_a` instead:
242167

243168
**packages/application-b/src/bootstrap.jsx**
244169

245170
<SyntaxHighlighter language="javascript" style={ghcolors}>
246-
{applicationBConsumesA}
171+
{applicationBConsumesA}
247172
</SyntaxHighlighter>
248173

249174
# A Few Notes
@@ -256,4 +181,4 @@ Visiting `Application B` for the first time, you'll notice we have already cache
256181

257182
<Image alt="'Application B' network log" size="large" src={bNetworkLog} style={{ margin: "2rem auto" }} />
258183

259-
**You have just created your first Webpack 5 Federated projects. Now go out and build something awesome!**
184+
**You have just created your first Webpack 5 Federated projects. Now go out and build something awesome!**

0 commit comments

Comments
 (0)