Webpack5์ Module Federation
Module Federation
์ด๋ 2020๋
10์์ release๋ webpack5์ ํฌํจ๋์ด ์๋ ์๋ก์ด ๊ธฐ๋ฅ์ด๋ค. (๊ณต์๋ฌธ์)
์์ฝํ๋ฉด, module federation
์ ์ฌ๋ฌ ๋ถ๋ฆฌ๋ build ํ์ผ์ ํ๋์ host์ฑ์์ ๋ถ๋ฌ์์ ๋์ ์ผ๋ก ์คํ์ํฌ ์ ์๋ ๊ธฐ์ ์ด๋ค.
์ด์ ํฌ์คํธ์์ ์ธ๊ธํ์๋ Micro-frontend
๋ฅผ ๊ตฌํํ ์ ์๋ ๊ธฐ์ ์ด๋ค.
๊ฐ๊ฐ์ ๋ถ๋ฆฌ๋ ์๋น์ค๋ฅผ buildํ์ฌ ๊ทธ ๊ฒฐ๊ณผ๋ฌผ์ ๋์ ์ผ๋ก ๋ถ๋ฌ์์ ์ฌ์ฉํ๋๋ฐ ์ด ๋ถ๋ฌ์ค๋ build์ฑ์ ๋ณดํต remote
๋ผ๊ณ ์ง์นญํ๋ฉฐ,
remote
๋ค์ ๋ถ๋ฌ์ ์ฌ์ฉํ๋ main์ฑ์ ๋ณดํต host
๋ผ๊ณ ์ง์นญํ๋ค. ์ฌ์ฉํ ์ ์๋ remote
๋ ๋ณต์๊ฐ๋ ๊ฐ๋ฅํ๋ฉฐ, ์๋ฐฉํฅ์ผ๋ก๋ module federation
์ด ๊ฐ๋ฅํ๋ค.
remote
์์ component๋ฅผ export ํ๋ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ๋ค.
// webpack.config.js
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'remote_from_a',
filename: 'remote_from_a_entry.js', // ํด๋น ์ด๋ฆ์ผ๋ก ๋น๋๊ฒฐ๊ณผ๋ฅผ import ํ๋๋ก ํ๋ค.
exposes: {
'./RemoteButton': './src/button', // expose ํด์ ์ฌ์ฉํ ์ ์๋ ์ปดํฌ๋ํธ
},
shared: ['react', 'react-dom', 'react-router-dom'],
}),
],
}
์์ ์ ํ๋ก์ ํธ์ ./src/button
์ ์๋ button์ RemoteButton
๋ผ๋ ์ด๋ฆ์ผ๋ก ๋ค๋ฅธ ์ฑ์์ ์ฌ์ฉํ ์ ์๋๋ก exposes
ํด์ฃผ๊ณ ์๋ค. ๋ํ ๋ค๋ฅธ๊ณณ์์ ์ฌ์ฉํ๊ธฐ ์ํด remote_from_a_entry.js
๋ผ๋ ์ด๋ฆ์ผ๋ก ๋น๋๊ฒฐ๊ณผ๋ฌผ ์ด๋ฆ์ ๋ช
๋ช
ํ๋ค.
shared๋ ์์กด์ฑ module์ ์ด๋ป๊ฒ ๊ณต์ ํ ์ง ์ ์ํ๋ค. ๋ ๋ง์ shared property๋ ๊ณต์๋ฌธ์์ Sharing hints์์ ๋ณผ ์ ์๋ค.
remote
์ฑ์ component๋ฅผ ์ฌ์ฉํ ๋์๋ ์๋์ฒ๋ผ ๋ถ๋ฌ์์ ์ฌ์ฉํ ์ ์๋ค.
// webpack.config.js
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'host',
filename: 'host_entry.js', // ํด๋น ์ด๋ฆ์ผ๋ก ๋น๋๊ฒฐ๊ณผ๋ฅผ import ํ๋๋ก ํ๋ค.
remotes: {
remote_from_a: 'remote_from_a',
},
shared: ['react', 'react-dom', 'react-router-dom'],
}),
],
}
// app.js
<head>
<script src="http://localhost:3001/remote_from_a_entry.js"></script>
</head>
<body>
<div id="root"></div>
</body>
// component
const ButtonFromRemoteA = React.lazy(() => import('remote_from_a/RemoteButton'))
const Example = () => {
return (
<div>
<React.Suspense fallback="Loading....">
<ButtonFromRemoteA />
</React.Suspense>
</div>
)
}
export default Example
Module federation์ ๋์จ์ง ๊ทธ๋ฆฌ ์ค๋๋์ง๋ ์์ ๊ธฐ๋ฅ์ด๋ผ ๋ง์ ๋ ํผ๋ฐ์ค์ best practice๊ฐ ์์ด ๊ตฌ๊ธ๋ง์ ํด๋ ๋น์ทํ ๋ด์ฉ์ด ๋ง๋ค. (์ค์ ๋ก production ํ๊ฒฝ์์ ๋์
ํ๊ณ ์๋ ํ์ฌ๊ฐ ์๋ค๊ณ ๋ ํ์ง๋ง..)
ํํ ๋ฆฌ์ผ์ ์งํํ๋ฉด์ ์์์น ๋ชปํ ์ฌ๋ฌ ๋ถ๊ฐ์ ์ธ ์ด์๋ค๋ ์์๊ณ , ๊ธฐ์กด์ ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ ์ ์ฉ์ด ์๋๋ ๊ฒฝ์ฐ๋ ์์๋ค. emotion.js
๋ฅผ ์ฌ์ฉํ ๋ hooks
์๋ฌ ๋ฑ ์ด๋ ค์์ด ๋ง์ ํด๊ฒฐํ๋๋ฐ ์๊ฐ์ ๋ง์ด ์์๋ค.
๊ทธ๋ฌ๋ฉด์ webpack์ ๋ํด ๋ ์๊ฒ๋ ๋ถ๋ถ๋ ์์ง๋ง, module federation์ผ๋ก ํ์ฌ ํ๋ก์ ํธ์ ์ํคํ
์ณ๋ฅผ migrationํ๋๊ฒ์ ์ด๋ ค์ธ ๊ฒ์ด๋ผ ํ๋จํด ํ์ฌ๋ holdingํ ์ํ์ด๋ค.
์์ผ๋ก ๋ง์ ๋ ํผ๋ฐ์ค์ ์ปค๋ฎค๋ํฐ๋ค์ด ์๊ธฐ๋ฉด ์ธ์ ๊ฐ ๋ค์ ๋์ ํด ๋ณผ ๊ณํ์ด๋ค.
์ธ๋ถ์ ์ธ ๋ด์ฉ์ webpack ๊ณต์๋ฌธ์์ ์์ธํ ๋์์๋ค.
์ฐธ๊ณ ๋ฌธ์
https://thekevinwang.com/2021/03/26/micro-frontends-nextjs
https://blog.wanzargen.me/38
https://betterprogramming.pub/micro-frontends-using-webpack-5-module-federation-3b97ffb22a0d
https://www.simform.com/blog/micro-frontend-architecture/#section4