Skip to content

Latest commit

ย 

History

History
345 lines (233 loc) ยท 16.1 KB

lighthouse2-webpack.md

File metadata and controls

345 lines (233 loc) ยท 16.1 KB

Lighthouse ํผํฌ๋จผ์Šค ์ ์ˆ˜ ์˜ฌ๋ฆฌ๊ธฐ 2: Webpack์„ ํ™œ์šฉํ•œ Preload, Lazy Load, Minify (feat. Vue)


  1. Vue ์•ฑ Preload ์„ค์ •ํ•˜๊ธฐ
  2. SPA๋ฅผ ๋น ๋ฅด๊ฒŒ: Webpack์˜ ๋ฒˆ๋“ค๋ง ์›๋ฆฌ, ์ฝ”๋“œ ์ชผ๊ฐœ๊ธฐ(Code Splitting)
  3. ๋™์  ์ž„ํฌํŠธ: import(), ์ •์  ์ž„ํฌํŠธ
  4. Vue์—์„œ ๋ผ์šฐํŠธ ๊ธฐ๋ฐ˜ ๋ฒˆ๋“ค ์ชผ๊ฐœ๊ธฐ: Webpack ๋™์  ์ž„ํฌํŠธ ํ™œ์šฉ, ๋ฒˆ๋“ค ๋„ค์ด๋ฐ๊ณผ ๊ทธ๋ฃจํ•‘
  5. SplitChunksPlugin์œผ๋กœ ์จ๋“œํŒŒํ‹ฐ ๋ชจ๋“ˆ ๋ฒˆ๋“ค๋ง ์ค‘๋ณต ์ œ๊ฑฐํ•˜๊ธฐ
  6. webpack-bundle-analyzer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JavaScript ๋ฒˆ๋“ค ๋ถ„์„ํ•˜๊ธฐ

1. Vue ์•ฑ Preload ์„ค์ •ํ•˜๊ธฐ

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)

2-1. Webpack์˜ JavaScript ๋ฒˆ๋“ค๋ง ์›๋ฆฌ

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 ํƒญ์—์„œ ์‹ค์ œ๋กœ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๋ฆฌ์†Œ์Šค์˜ ๋น„์œจ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถ‰์€์ƒ‰์œผ๋กœ ํ‘œ์‹œ๋œ ๋ถ€๋ถ„์ด ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.



2-2. Webpack์˜ ์ฝ”๋“œ ์ชผ๊ฐœ๊ธฐ(Code Splitting)

Webpack์— ์ฝ”๋“œ ์ชผ๊ฐœ๊ธฐ(Code Splitting) ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜๋ฉด์„œ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Webpack์˜ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด์„œ ํ•˜๋‚˜์˜ JavaScript ํŒŒ์ผ(๋ฒˆ๋“ค)์ด ์•„๋‹Œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŒŒ์ผ๋“ค๋กœ ์•ฑ์„ ๋นŒ๋“œํ•˜๊ณ , ๊ฐ ๋ฒˆ๋“ค์„ ํ•„์š”ํ•œ ์‹œ์ ์— ๋”ฐ๋กœ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํŠนํžˆ ์•ฑ์˜ ์ตœ์ดˆ ๋ Œ๋”๋ง์— ํ•„์š”ํ•œ JavaScript ์ฝ”๋“œ๋งŒ์ด ํฌํ•จ๋œ ๋ฒˆ๋“ค๋งŒ ๋จผ์ € ๋กœ๋“œํ•จ์œผ๋กœ์จ FCP๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!


3. ๋™์  ์ž„ํฌํŠธ: import(), ์ •์  ์ž„ํฌํŠธ

3-1. import()

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 ๋ช…์„ธ์— ํฌํ•จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


Preload ์ฃผ์„ ์‚ฌ์šฉํ•˜๊ธฐ

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 ๋™์  ์ž„ํฌํŠธ ํ™œ์šฉ, ๋ฒˆ๋“ค ๋„ค์ด๋ฐ๊ณผ ๊ทธ๋ฃจํ•‘

4-1. 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 }
]

4-2. ๋ฒˆ๋“ค ๋„ค์ด๋ฐ๊ณผ ๊ทธ๋ฃจํ•‘

๋งŒ์•ฝ webpackChunkName ์ฃผ์„์„ ์‚ฌ์šฉํ•˜๋ฉด, ํ•ด๋‹น ๋ชจ๋“ˆ์ด ํฌํ•จ๋œ ๋ฒˆ๋“ค์— ์›ํ•˜๋Š” ์ด๋ฆ„์„ ๋ถ€์—ฌํ•˜๊ณ  ๋‹ค๋ฅธ ๋ฒˆ๋“ค๋กœ๋ถ€ํ„ฐ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด ๋‘ ์ปดํฌ๋„ŒํŠธ์— home์ด๋ผ๊ณ  ์ง€์ •ํ•˜๋ฉด, Home๊ณผ About ์ปดํฌ๋„ŒํŠธ๋Š” home.js ๋ฒˆ๋“ค์— ํ•จ๊ป˜ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

const Home = () => import(/* webpackChunkName: "home" */ "./Home.vue");
const About = () => import(/* webpackChunkName: "home" */ "./About.vue");

5. SplitChunksPlugin์œผ๋กœ ์จ๋“œํŒŒํ‹ฐ ๋ชจ๋“ˆ ๋ฒˆ๋“ค๋ง ์ค‘๋ณต ์ œ๊ฑฐํ•˜๊ธฐ

5-1. SplitChunksPlugin

์•ฑ์„ ๋นŒ๋“œํ•˜๋ฉด ๋ฉ”์ธ ๋ฒˆ๋“ค์ธ 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,
					},
				},
			},
		},
	},
};

5-2. splitChunks.chunks

๋ณดํ†ต์€ 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",
			},
		},
	},
};

5-3. splitChunks.automaticNameDelimiter (๋ฒˆ๋“ค ๋„ค์ด๋ฐ)

๊ฐ€๋ น moment ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ชจ๋“ˆ์„ /home, /about 2 ๊ฐœ์˜ ๋ผ์šฐํŠธ์—์„œ ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. ์ถ”๊ฐ€๋กœ, ๊ฐ ๋ผ์šฐํŠธ์— ๋Œ€ํ•œ ๋ทฐ ์ปดํฌ๋„ŒํŠธ๋Š” ๋™์ ์œผ๋กœ ์ž„ํฌํŠธ๋˜๋ฉฐ webpackChunkName ์ฃผ์„์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฒˆ๋“ค๋ช…์„ ๊ฐ๊ฐ home, about์œผ๋กœ ์„ค์ •ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด์ œ moment ๋ชจ๋“ˆ์ด ํฌํ•จ๋œ ๋ฒˆ๋“ค์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์ž๋™์œผ๋กœ ๋„ค์ด๋ฐ๋ฉ๋‹ˆ๋‹ค.

  • home~about.js

splitChunks.automaticNameDelimiter ์†์„ฑ์€ ์œ„ ๋ฒˆ๋“ค๋ช…์—์„œ ~์— ํ•ด๋‹นํ•˜๋Š” ๋ถ€๋ถ„์— ๊ด€์—ฌํ•ฉ๋‹ˆ๋‹ค. ์ด ์†์„ฑ์˜ ๋””ํดํŠธ ๊ฐ’์€ ~์ž…๋‹ˆ๋‹ค.


6. webpack-bundle-analyzer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JavaScript ๋ฒˆ๋“ค ๋ถ„์„ํ•˜๊ธฐ

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๋ฅผ ์‹คํ–‰์‹œ์ผœ ์•ฑ์„ ๋นŒ๋“œํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ถ„์„ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.



References