Lighthouse ํผํฌ๋จผ์ค ์ ์ ์ฌ๋ฆฌ๊ธฐ 2: Webpack์ ํ์ฉํ Preload, Lazy Load, Minify (feat. Vue)
- Vue ์ฑ Preload ์ค์ ํ๊ธฐ
- SPA๋ฅผ ๋น ๋ฅด๊ฒ: Webpack์ ๋ฒ๋ค๋ง ์๋ฆฌ, ์ฝ๋ ์ชผ๊ฐ๊ธฐ(Code Splitting)
- ๋์ ์ํฌํธ:
import()
, ์ ์ ์ํฌํธ - Vue์์ ๋ผ์ฐํธ ๊ธฐ๋ฐ ๋ฒ๋ค ์ชผ๊ฐ๊ธฐ: Webpack ๋์ ์ํฌํธ ํ์ฉ, ๋ฒ๋ค ๋ค์ด๋ฐ๊ณผ ๊ทธ๋ฃจํ
SplitChunksPlugin
์ผ๋ก ์จ๋ํํฐ ๋ชจ๋ ๋ฒ๋ค๋ง ์ค๋ณต ์ ๊ฑฐํ๊ธฐwebpack-bundle-analyzer
๋ฅผ ์ฌ์ฉํ์ฌ JavaScript ๋ฒ๋ค ๋ถ์ํ๊ธฐ
Vue ์ฑ์ vue-cli-service build
์คํฌ๋ฆฝํธ๋ก ๋น๋ํ๋ฉด dist/
๊ฒฝ๋ก ๋ด์ ์๋์ ๊ฐ์ด ์ฑ ๋ฒ๋ค์ด ๊ตฌ์ฑ๋ฉ๋๋ค.
index.html
js/app.js
js/chunk-vendors.js
css/app.css
css/chunk-vendors.css
image-name.png
์ด CSS, JavaScript, ์ด๋ฏธ์ง ํ์ผ๋ค์ ๋ค์๊ณผ ๊ฐ์ด index.html
๋ฌธ์์ ์๋์ผ๋ก ์ฝ์
๋ฉ๋๋ค. ์๋ ์ฝ๋์์ ์ ์ ์๋ฏ์ด ์ด๊ธฐ ์ฑ ๋ ๋๋ง์ ํ์ํ ๋ชจ๋ ๋ฆฌ์์ค ํ์ผ์ preload
, modulepreload
์์ฑ์ด ์๋์ผ๋ก ๋ถ์ฌ๋ฉ๋๋ค.
<head>
<link href="/css/app.e39cad8a.css" rel="preload" as="style" />
<link href="/js/app.39144f4c.js" rel="modulepreload" as="script" />
<!-- .. -->
</head>
์ด๋ vue-cli-service build
๋ช
๋ น์ด๊ฐ ์คํ๋ ๋ ๋ด๋ถ์ ์ผ๋ก @vue/preload-webpack-plugin
ํ๋ฌ๊ทธ์ธ์ด ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ด๊ณ ์, Webpack ์ค์ ํ์ผ์ธ vue.config.js
์์ ์๋์ ๊ฐ์ด Preload ์ค์ ์ ์ปค์คํ
ํ ์ ์์ต๋๋ค. ์ด ์์๋ Vue ์ปค๋ฎค๋ํฐ์ How to preload CSS in Vue ํ์ด์ง์์ ๊ฐ์ ธ์์ต๋๋ค.
// vue.config.js
module.exports = {
chainWebpack(config) {
config.plugins.delete("prefetch");
config.plugin("preload").tap((options) => {
options[0].include = "allChunks";
return options;
});
},
};
2. SPA๋ฅผ ๋น ๋ฅด๊ฒ: Webpack์ JavaScript ๋ฒ๋ค๋ง ์๋ฆฌ, Webpack์ ์ฝ๋ ์ชผ๊ฐ๊ธฐ(Code Splitting)
CSR(Client Side Rendering)์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ SPA ๋ฐฉ์์ ๋จ์ ์ค ํ๋๋ ์ด๊ธฐ ์คํ ์๋๊ฐ ๋๋ฆฌ๋ค๋ ๊ฒ์ด์์ต๋๋ค. ์ฑ์ ์ด๊ธฐ ์คํํ๋ ์์ ์ ๋ชจ๋ JavaScript ์ฝ๋๊ฐ ํฌํจ๋ ๊ฑฐ๋ํ ๋ฒ๋ค(app.js
ํ์ผ ๋ฑ)์ ๋ก๋ํด์ผํ๊ธฐ ๋๋ฌธ์
๋๋ค. ์ด๋ Webpack๊ณผ ๊ฐ์ ๋ฒ๋ค๋ฌ๊ฐ SPA๋ฅผ ๋น๋ํ๋ ๋ฐฉ์์ ๋ฐ๋ฅธ ๊ฒฐ๊ณผ์
๋๋ค. Webpack์ JavaScript ๋ฒ๋ค์ ๊ตฌ์ฑํ ๋ import
๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ชจ๋ JavaScript ๋ชจ๋๋ค์ด ์๋ก ์ฐ๊ฒฐ๋์ด ์๋ ์์กด์ฑ ๊ทธ๋ํ๋ฅผ ๋ง๋ค๊ณ ์, ์ด ์์กด์ฑ ๊ทธ๋ํ์ ๊ธฐ๋ฐํ์ฌ ์ต์ข
๋ฒ๋ค์ ๊ฐ ๋ชจ๋์ ํฌํจ์ํฌ์ง ์ ์ธํ ์ง ๊ฒฐ์ ํฉ๋๋ค.
์ฌ์ง์ถ์ฒ : Lazy loading and code splitting in Vue.js
์ด๋ ๋ค๋ณด๋, ์ฑ์ ์ด๋ค ๋ผ์ฐํธ๋ฅผ ์์ฒญํ๋์ง ๋ชจ๋ JavaScript ๋ชจ๋๊ณผ ์์กด ๊ด๊ณ๊ฐ ํฌํจ๋ ๊ฑฐ๋ํ ๋ฒ๋ค์ด ๋ก๋๋ฉ๋๋ค. ํ์ง๋ง ๊ฐ ๋ผ์ฐํธ์์ ์ฌ์ฉ๋๋ ๋ชจ๋๋ค์ ๊ทธ ์ค ์ผ๋ถ๊ฒ ์ฃ . ์๋์ ๊ฐ์ด Chrome ๊ฐ๋ฐ์๋๊ตฌ์ Coverage
ํญ์์ ์ค์ ๋ก ์ฌ์ฉ๋์ง ์๋ ๋ฆฌ์์ค์ ๋น์จ์ ํ์ธํ ์ ์์ต๋๋ค. ๋ถ์์์ผ๋ก ํ์๋ ๋ถ๋ถ์ด ์ฌ์ฉ๋์ง ์๋ ๋ฆฌ์์ค๋ฅผ ๋ํ๋
๋๋ค.
Webpack์ ์ฝ๋ ์ชผ๊ฐ๊ธฐ(Code Splitting) ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋๋ฉด์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๊ฒ ๋์์ต๋๋ค. Webpack์ ๊ธฐ๋ฅ์ ์ฌ์ฉํด์ ํ๋์ JavaScript ํ์ผ(๋ฒ๋ค)์ด ์๋ ์ฌ๋ฌ ๊ฐ์ ํ์ผ๋ค๋ก ์ฑ์ ๋น๋ํ๊ณ , ๊ฐ ๋ฒ๋ค์ ํ์ํ ์์ ์ ๋ฐ๋ก ๋ก๋ํ ์ ์๊ฒ ๋์๊ธฐ ๋๋ฌธ์ ๋๋ค. ํนํ ์ฑ์ ์ต์ด ๋ ๋๋ง์ ํ์ํ JavaScript ์ฝ๋๋ง์ด ํฌํจ๋ ๋ฒ๋ค๋ง ๋จผ์ ๋ก๋ํจ์ผ๋ก์จ FCP๋ฅผ ๊ฐ์ ํ ์ ์๊ฒ ๋์์ต๋๋ค!
JavaScript ๋ชจ๋์ ๊ธฐ๋ณธ ์ํฌํธ ๋ฌธ๋ฒ์ ์๋์ ๊ฐ์ต๋๋ค. ์ด๋ ์ ์ ์ํฌํธ ๋ฐฉ์์
๋๋ค. ์๋์ ๊ฐ์ด moduleA
๋ฅผ ์ํฌํธํ๋ฉด Webpack์ ์์กด์ฑ ๊ทธ๋ํ์์ main.js
์ ๋
ธ๋ ์ค ํ๋๋ก ์ถ๊ฐ๋๊ณ , ์ฑ์ ์ต์ข
JavaScript ๋ฒ๋ค์ธ app.js
์ ํฌํจ๋๋ฏ๋ก ์ฑ์ ์ด๊ธฐ ์คํ ์ ํจ๊ป ๋ก๋๋ฉ๋๋ค. ๋ง์ฝ ์ฑ์ ์ต์ด ๋ ๋๋ง์ ์ด ๋ชจ๋์ด ์ฌ์ฉ๋์ง ์๋๋ค๋ฉด, ์ด ๋ชจ๋์ app.js
๋ฒ๋ค์์ ์ ์ธ์ํค๊ณ ๋ณ๋์ ๋ฒ๋ค๋ก ๋ฌถ๋ ๊ฒ์ด ์ข๊ฒ ์ฃ .
// main.js
import moduleA from "a";
Webpack์ ์ฝ๋ ์ชผ๊ฐ๊ธฐ ๊ธฐ๋ฅ ์ค ํ๋์ธ ๋์ ์ํฌํธ ๋ฌธ๋ฒ import()
๋ฅผ ์ฌ์ฉํ๋ฉด, ์ด๊ธฐ ๋ ๋๋ง์ ์ฌ์ฉ๋์ง ์๋ JavaScript ๋ชจ๋๋ค์ ๋ค๋ฅธ ๋ฒ๋ค๋ก ๋ถ๋ฆฌํ ์ ์์ต๋๋ค. ์๋์ ๊ฐ์ด moduleA
๋ฅผ ๋์ ์ผ๋ก ์ํฌํธํ๋ฉด, ์ด ๋ชจ๋๊ณผ ์ด ๋ชจ๋์์ ์์กดํ๋ ๋ชจ๋๋ค ๋ชจ๋ app.js
๋ฒ๋ค์ ํฌํจ๋์ง ์๊ณ ๋ณ๋์ ๋ฒ๋ค๋ก ๋ถ๋ฆฌ๋ฉ๋๋ค. ์ด ๋ณ๋๋ก ๋ถ๋ฆฌ๋ Chunk ๋ฒ๋ค์ ์ฑ ์ด๊ธฐ ์คํ์ ๋ก๋๋์ง ์๊ณ ์, ํด๋น ๋ชจ๋์ด ํ์ํด์ง๋ฉด ๊ทธ์ ์์ผ "๊ฒ์ผ๋ฅด๊ฒ" ๋ก๋๋ฉ๋๋ค.
// main.js
if (isSubmitted) {
// `import()` ๋ฉ์๋๋ `Promise` ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค๋ ์ ์ ์ ์ํ์๊ณ ์.
const moduleA = await import("a.moduleA");
const module = moduleA.default;
// ..
์ฐธ๊ณ ๋ก ๋์ ์ํฌํธ ๋ฌธ๋ฒ์ ECMAScript 2020 ๋ช ์ธ์ ํฌํจ๋์์ต๋๋ค.
Webpack์ ๋์ ์ํฌํธ ๋ฉ์๋์ธ import()
๋ฅผ ์ฌ์ฉํ ๋, ๋ง๋ฒ ์ฃผ์์ ์ฌ์ฉํ์ฌ ํน์ ๋ชจ๋๋ง Preload์ฉ ๋ฒ๋ค์ ํฌํจ์ํฌ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์๋์ ๊ฐ์ด App
์ปดํฌ๋ํธ์์ CriticalComponent
์ปดํฌ๋ํธ๋ฅผ ๋์ ์ผ๋ก ์ํฌํธํ ๋ webpackPreload: true
์ฃผ์์ ์ฌ์ฉํ๋ฉด, App
์ปดํฌ๋ํธ๊ฐ ๋ก๋๋๋ ์์ ์ CriticalComponent
์ปดํฌ๋ํธ๋ ํจ๊ป ์์ฒญ๋์ด ๋์์ ๋ก๋ฉ์ด ์์๋ฉ๋๋ค. Webpack ๊ณต์๋ฌธ์์์ ์์ธํ ๋ด์ฉ์ ํ์ธํ ์ ์์ต๋๋ค.
// App.js
import(/* webpackPreload: true */ "CriticalComponent");
์ด ๊ธฐ๋ฅ์ Webpack 4.6.0 ๋ฒ์ ๋ถํฐ ์ง์ํฉ๋๋ค. ์ด์ ๋ฒ์ ์ Webpack์ ์ฌ์ฉํด์ผํ๋ค๋ฉด preload-webpack-plugin ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
4. Vue์์ ๋ผ์ฐํธ ๊ธฐ๋ฐ ๋ฒ๋ค ์ชผ๊ฐ๊ธฐ: Webpack ๋์ ์ํฌํธ ํ์ฉ, ๋ฒ๋ค ๋ค์ด๋ฐ๊ณผ ๊ทธ๋ฃจํ
์ด๋ฒ์๋ Vue ์ฑ์ ์ปดํฌ๋ํธ๋ค์ ๋ผ์ฐํธ๋ณ๋ก ๋์ ๋ก๋ํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํฉ๋๋ค. ์ผ๋ช ๋ผ์ฐํธ ๊ธฐ๋ฐ ๋ฒ๋ค ์ชผ๊ฐ๊ธฐ์ธ๋ฐ์, ์ฌ์ฉ์๊ฐ ํน์ URL์ ๋ํด ๋ผ์ฐํ ์ ์์ฒญํ๋ฉด ํด๋น ๋ผ์ฐํธ์ ํ์ํ ์ปดํฌ๋ํธ๋ง ๋ก๋ํ ์ ์๊ฒ ํ๋๊ฒ๋๋ค. ์์์ ์ดํด๋ณธ Webpack์ ๋์ ์ํฌํธ๋ฅผ ํ์ฉํด์์. ์์ธํ ๋ด์ฉ์ ๊ณต์๋ฌธ์์ธ Lazy Loading Routes๋ฅผ ์ฐธ๊ณ ํ์ธ์.
๋ง์ฝ ์ปดํฌ๋ํธ ์ํฌํธ๊ฐ ์๋์ ๊ฐ์ด ์์ฑ๋์ด์๋ค๋ฉด, ์ปดํฌ๋ํธ๋ค์ ์ ์ ์ผ๋ก ์ํฌํธํ๊ณ ์๋๊ฒ๋๋ค. ์ค์ ๋ก ์ฌ์ฉ์๊ฐ /about
๊ฒฝ๋ก์ ์ ๊ทผํ์ง ์๋๋ผ๋, About
์ปดํฌ๋ํธ๋ ์ฑ์ด ์คํ๋ ๋ ๋ฌด์กฐ๊ฑด ๋ก๋๋ฉ๋๋ค.
// router.js
import Home from './Home.vue'
import About from './About.vue'
const routes = [
{ path: '/', component: Home }
{ path: '/about', component: About }
]
์ ์ฝ๋๋ ์๋์ ๊ฐ์ด Webpack์ import()
๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ ๋ฐ๊ฟ ์ ์์ต๋๋ค. ์ด์ ์ฌ์ฉ์๊ฐ /about
๊ฒฝ๋ก์ ์ ๊ทผํ๊ธฐ ๋๋ฌธ์ About
์ปดํฌ๋ํธ๊ฐ ์ค์ ๋ก ์ฌ์ฉ๋์ด์ผ ํ ๋๋ง About
์ปดํฌ๋ํธ๊ฐ ํฌํจ๋ ๋ฒ๋ค์ด ๋ก๋๋ฉ๋๋ค.
// router.js
const Home = () => import('./Home.vue')
const About = () => import('./About.vue')
const routes = [
{ path: '/', component: Home }
{ path: '/about', component: About }
]
๋ง์ฝ webpackChunkName
์ฃผ์์ ์ฌ์ฉํ๋ฉด, ํด๋น ๋ชจ๋์ด ํฌํจ๋ ๋ฒ๋ค์ ์ํ๋ ์ด๋ฆ์ ๋ถ์ฌํ๊ณ ๋ค๋ฅธ ๋ฒ๋ค๋ก๋ถํฐ ๋ถ๋ฆฌํ ์ ์์ต๋๋ค. ์๋์ ๊ฐ์ด ๋ ์ปดํฌ๋ํธ์ home
์ด๋ผ๊ณ ์ง์ ํ๋ฉด, Home
๊ณผ About
์ปดํฌ๋ํธ๋ home.js
๋ฒ๋ค์ ํจ๊ป ํฌํจ๋ฉ๋๋ค.
const Home = () => import(/* webpackChunkName: "home" */ "./Home.vue");
const About = () => import(/* webpackChunkName: "home" */ "./About.vue");
์ฑ์ ๋น๋ํ๋ฉด ๋ฉ์ธ ๋ฒ๋ค์ธ app.js
์ ๋ณ๋๋ก chunk-vendors.js
๋ฒ๋ค์ด ์๊น๋๋ค. ์ด ๋ฒ๋ค์ node_modules
์ ํฌํจ๋ ๋ชจ๋ ์จ๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ชจ๋๋ค์ ๋ด๊ณ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด moment
๋ชจ๋์ 2 ๊ฐ์ ๋ผ์ฐํธ์์ ์ฌ์ฉํ๊ณ , ๊ฐ ๋ผ์ฐํธ๋ณ๋ก ๋ฒ๋ค์ ๊ตฌ์ฑํ๋ค๊ณ ๊ฐ์ ํด๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฌํ ๊ฒฝ์ฐ moment
๋ชจ๋์ 2 ๊ฐ์ ๋ฒ๋ค์ ์ค๋ณต ์กด์ฌํ๊ฒ ๋ฉ๋๋ค! Webpack 4๋ถํฐ ์ง์ํ๋ SplitChunksPlugin
์ ์จ๋ํํฐ ๋ชจ๋์ ์ค๋ณต์ ๊ฑฐ๋ฅผ ์๋์ผ๋ก ์ํํฉ๋๋ค.
Vue ์ฑ์ Webpack ์ค์ ํ์ผ์ธ vue.config.js
ํ์ผ์ ์ฌ์ฉํ๋ค๋ฉด ์๋์ ๊ฐ์ด configureWebpack
ํ๋์์ ์ค์ ํด์ค ์ ์์ต๋๋ค. ์ค์ ํ์ง ์๋๋ผ๋ ์๋์ ๊ฐ์ ๋ํดํธ ์ค์ ๊ฐ์ด ๋ฐ์๋๋ฏ๋ก ์ฐธ๊ณ ํด์ฃผ์๊ณ ์, ๋ณ๋์ฌํญ์ด ์์ ์ ์์ผ๋ฏ๋ก ๊ณต์๋ฌธ์๋ฅผ ํ์ธํด์ฃผ์ธ์.
// vue.config.js
module.exports = {
// ..
configureWebpack: {
optimization: {
splitChunks: {
chunks: 'async',
minSize: 20000,
minRemainingSize: 0,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
},
};
๋ณดํต์ splitChunks.chunks
์์ฑ์ ๊ฑด๋๋ฆฌ๋ ๊ฒ์ผ๋ก ์ถฉ๋ถํฉ๋๋ค. ์ค์ ๊ฐ์ ๋ฐ๋ผ ๊ฐ๊ฐ ์ด๋ป๊ฒ ๋ฒ๋ค๋ง ์ต์ ํ(์ค๋ณต์ ๊ฑฐ)๊ฐ ์ด๋ฃจ์ด์ง๋์ง ์ค๋ช
ํ๊ธฐ ์ํด ๊ฐ๋จํ ์์ ๋ฅผ ๊ฐ์ ธ์์ต๋๋ค. ๋ค์๊ณผ ๊ฐ์ด static-module
์ ์ ์ ์ํฌํธํ๊ณ , dynamic-module
๋ชจ๋์ ๋์ ์ผ๋ก ์ํฌํธํ๋ ์ฑ์ด ์๋ค๊ณ ๊ฐ์ ํด๋ณด๊ฒ ์ต๋๋ค.
// app.js
import staticModule from 'static-module';
async function getDynamicModule() {
await import('dynamic-module')
}
getDynamicModule()
๋ค์์ ๊ฐ ์ค์ ๊ฐ์ ๋ฐ๋ฅธ ๋ฒ๋ค๋ง ๊ฒฐ๊ณผ๋ฌผ์ ๊ฐ๋จํ ๋ํ๋ธ ๊ฒ์
๋๋ค. ์ฌ๊ธฐ์์ async
๋ ๋น๋๊ธฐ ๋ฐฉ์์ผ๋ก ๋์ ์ํฌํธํ๋ ๋ชจ๋์ ์๋ฏธํฉ๋๋ค.
async
(๋ํดํธ)
bundle.js
(app.js
+static-module
)chunk.js
(dynamic-module
)
initial
app.js
bundle.js
(static-module
)chunk.js
(dynamic-module
)
all
app.js
bundle.js
(static-module
+dynamic-module
)
all
์ ์ ์ ์ํฌํธ๋ฅผ ํ๋ , ๋์ ์ํฌํธ๋ฅผ ํ๋ ๋ชจ๋ ์จ๋ํํฐ ๋ชจ๋๋ค์ ๋ชจ์์ ๊ณตํต ์์กด์ฑ์ด ์๋ ๊ฒฝ์ฐ ์ค๋ณต์ ์ ๊ฑฐํ๊ฒ ๋ค๋ ์๋ฏธ์
๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ์ด ๋ฒ๋ค ์ฌ์ด์ฆ๋ฅผ ๊ฐ์ฅ ๋ง์ด ์ค์ผ ์ ์์ฃ . ๋ค์์ ๊ณต์๋ฌธ์์ ์ค๋ช
์
๋๋ค.
Providing all can be particularly powerful, because it means that chunks can be shared even between async and non-async chunks.
// vue.config.js
module.exports = {
// ..
configureWebpack: {
optimization: {
splitChunks: {
chunks: "all",
},
},
},
};
๊ฐ๋ น moment
๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ชจ๋์ /home
, /about
2 ๊ฐ์ ๋ผ์ฐํธ์์ ๊ณตํต์ผ๋ก ์ฌ์ฉํ๋ค๊ณ ํด๋ด
์๋ค. ์ถ๊ฐ๋ก, ๊ฐ ๋ผ์ฐํธ์ ๋ํ ๋ทฐ ์ปดํฌ๋ํธ๋ ๋์ ์ผ๋ก ์ํฌํธ๋๋ฉฐ webpackChunkName
์ฃผ์์ ์ฌ์ฉํ์ฌ ๋ฒ๋ค๋ช
์ ๊ฐ๊ฐ home
, about
์ผ๋ก ์ค์ ํ๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค. ์ด์ moment
๋ชจ๋์ด ํฌํจ๋ ๋ฒ๋ค์ ์๋์ ๊ฐ์ด ์๋์ผ๋ก ๋ค์ด๋ฐ๋ฉ๋๋ค.
home~about.js
splitChunks.automaticNameDelimiter
์์ฑ์ ์ ๋ฒ๋ค๋ช
์์ ~
์ ํด๋นํ๋ ๋ถ๋ถ์ ๊ด์ฌํฉ๋๋ค. ์ด ์์ฑ์ ๋ํดํธ ๊ฐ์ ~
์
๋๋ค.
webpack-bundle-analyzer
๋ ์ฑ ๋ฒ๋ค ๊ฒฐ๊ณผ๋ฌผ์์ ์ด๋ค ๋ชจ๋์ด ์ด๋์ ๋ ๋น์ค์ ์ฐจ์งํ๋์ง ๋ถ์ํ๊ณ ์๊ฐํํด์ ๋ณด์ฌ์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค. ์๋์ ๊ฐ์ด webpack-bundle-analyzer
๋ฅผ ๊ฐ๋ฐ์ฉ์ผ๋ก ์ค์นํ์๊ณ ์,
yarn add -D webpack-bundle-analyzer
Vue์ Webpack ์ค์ ํ์ผ์ธ vue.config.js
์์ ํ๋ฌ๊ทธ์ธ์ผ๋ก ์ถ๊ฐํฉ๋๋ค.
// vue.config.js
const BundleAnalyzerPlugin =
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
module.exports = {
// ..
plugins: [new BundleAnalyzerPlugin()],
};
์ด์ vue-cli-service build
๋ฅผ ์คํ์์ผ ์ฑ์ ๋น๋ํ๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ๋ถ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
- Webpack and Dynamic Imports: Doing it Right
- Lazy loading and code splitting in Vue.js
- Vue.js Router Performance
- Lazy Loading Routes | Vue Router
- How to Reduce Your Vue.JS Bundle Size With Webpack - Jennifer Bland
- Code Splitting With Vue.js And Webpack - Anthony Gore
- 3 Code Splitting Patterns For VueJS and Webpack - Anthony Gore
- Webpack: What is the difference between "all" and "initial" options in optimization.splitChunks.chunks | Stack Overflow
- The 100% correct way to split your chunks with Webpack
- SPA ์ด๊ธฐ ๋ก๋ฉ ์๋ ๊ฐ์ ํ๊ธฐ
- ์นํฉ5(Webpack) ์ค์ ํ๊ธฐ | zerocho.com