[TIL] Webpack

krkorklo·2022년 9월 7일
0

TIL

목록 보기
21/29
post-thumbnail

1. Webpack

모듈이란

프로그래밍 관점에서 특정 기능을 가지는 작은 코드 단위
→ 비슷한 기능들을 하나의 의미있는 파일로 관리하는 것이 모듈!

Webpack에서의 모듈

웹 어플리케이션을 구성하는 모든 자원을 의미
→ HTML, CSS, JavaScript, Image, Font 등의 파일 하나하나가 모두 모듈

모듈 번들링이란

웹 어플리케이션을 구성하는 수많은 자원들을 하나의 파일로 병합 및 압축해주는 동작

빌드 = 번들링 = 변환

2. Webpack의 등장 배경

1) 파일 단위의 자바스크립트 모듈 관리

<!-- index.html -->
<html>
  <head>
    <script src="./src/hello.js"></script>
    <script src="./src/world.js"></script>
  </head>
  <body>
    <h1>WEBPACK</h1>
    <div id="root"></div>
    <script>
      document.querySelector("#root").innerHTML = word;
    </script>
  </body>
</html>
/* src/hello.js */
var word = "hello";
/* src/world.js */
var word = "world";

hello.jsworld.js에서 word 변수를 중복으로 선언하는 경우 덮어쓰이는 현상 발생
→ 파일 단위로 변수를 관리하고자하는 욕구

ex. AMD, Common.js

2) 웹 개발 작업 자동화 도구

  • 프론트엔드 개발 업무를 할 때 텍스트 편집기에서 코드를 수정한 후 브라우저에서 새로고침 필요
  • HTML, CSS, JavaScript 압축
  • 이미지 압축
  • CSS 전처리기 변환
    → 자동화 도구 필요

ex. Grunt, Gulp

3) 웹 어플리케이션의 빠른 로딩 속도와 높은 성능

대부분의 사용자들은 5초 이내로 웹 사이트가 표시되지 않으면 집중력을 잃음
→ 로딩 속도를 높이기 위해 브러우저에서 서버로 요청하는 파일 숫자를 줄이기

Webpack으로 해결하려는 문제

  1. 자바스크립트 변수 유효 범위
  • ES6의 Modules 문법과 웹팩의 모듈 번들링으로 해결
  1. 브라우저별 HTTP 요청 숫자의 제약
  • HTTP 요청 숫자를 줄여 웹 어플리케이션의 성능을 높이고 사용자가 사이트를 조작할 시간을 앞당겨줄 필요
  1. 사용하지 않는 코드의 관리
  2. Dynamic Loading & Lazy Loading 미지원
  • Require.js와 같은 라이브러리를 쓰지 않으면 동적으로 모듈을 로딩할 수 없음
    → 웹팩의 Code Splitting 기능으로 원하는 모듈을 원하는 타이밍에 로딩!

3. Webpack의 주요 개념

entry

웹팩에서 웹 자원을 변환하기 위해 필요한 최초 진입점이자 자바스크립트 파일 경로

  • entry 속성에 지정된 파일에는 웹 애플리케이션의 전반적인 구조와 내용이 담겨져 있어야 함
  • 웹팩이 entry로 지정된 파일을 가지고 웹 애플리케이션에서 사용되는 모듈들 간의 관계를 이해하고 분석 (의존관계의 파일들까지 해석)
entry: {
  login: './src/LoginView.js',
  main: './src/MainView.js'
}

여러 개의 entry도 가능 (MPA에 적합)

output

웹팩을 돌리고 난 결과물의 파일 경로 (객체 형식으로 지정해야 함)

var path = require('path');

module.exports = {
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './dist')
  }
}

일반적으로 filename, path 정의

path.resolve()는 인자로 넘어온 경로들을 조합하여 유효한 파일 경로를 만들어주는 Nodejs API

filename 의 속성은 대괄호를 사용해서 엔트리 이름, 모듈 아이디, 해시 값 등을 넣을 수 있음

module.exports = {
  output: {
    filename: '[name].bundle.js'
  }
};

loader

웹팩이 웹 애플리케이션을 해석할 때 자바스크립트 파일이 아닌 웹 자원(HTML, css, image, 폰트 등)을 변환할 수 있도록 도와줌

  • loader를 추가하지 않으면 해당 파일들을 해석하기 위한 loader를 추가하라는 오류 발생

css Loader

npm 명령어로 css-loader 설치 후 정의 가능

module.exports = {
  entry: './app.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.css/,
        use: ['css-loader']
      }
    ]
  }
}
  • test : 로더를 적용할 파일 유형 (정규식)
  • use : 해당 파일에 적용할 로더의 이름

Sass Loader, TS Loader, Babel Loader, File Loader 등이 자주 사용

Loader 적용 순서

오른쪽에서 왼쪽!

module: {
  rules: [
    {
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 'sass-loader']
    }
  ]
}

Sass 로더로 전처리(scss 파일을 css 파일로 변환) → 웹팩에서 css 파일을 인식 → css 파일이 웹 애플리케이션에 인라인 스타일 태그로 추가

Babel loader

  • JS es6 문법을 es5로 변환해주는 트랜스파일러
  • babel만으로는 es6의 내장메소드는 대체 불가
    plugin-transform-runtime : es6+의 문법들을 자체 구현한 함수로 트랜스파일
    • 인스턴스의 메소드는 제대로 트랜스파일링 되지 않는 이슈
      core-js@3

.babelrc vs babel.config.json

  • .babelrc : 서브셋 디렉토리 또는 파일에서 특정한 플러그인을 변형 할때 유용
  • babel.config.json : 여러 패키지 디렉토리를 가진 프로젝트에서 하나의 바벨 설정을 가져갈 때 유용

plugin

웹팩의 기본적인 동작에 추가적인 기능을 제공 (해당 결과물의 형태를 바꾸는 역할)

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin(),
    new webpack.ProgressPlugin()
  ]
}

4. Developer Tools

Webpack Dev Server

  • 웹팩의 빌드 대상 파일이 변경되었을때 코드를 저장하면 웹팩으로 빌드한 후 브라우저를 새로고침해주는 도구
  • 브라우저 새로고침 시간 뿐만 아니라 웹팩 빌드 시간을 줄여줌

특징

웹팩 데브 서버로 빌드하는 경우 빌드한 결과물이 메모리에 저장되고 파일은 생성하지 않기 때문에 빌드한 결과물이 파일 탐색기에 보이지 않음
→ 개발할 때만 사용하다가 개발이 완료되면 명령어를 사용해 결과물을 파일로 생성해야 함

프록시 설정

프록시 쓰지 않은 경우 웹팩 데브 서버와 API 서버 통신 시 CORS 에러 발생

// webpack.config.js
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'domain.com',
        changeOrigin: true
      }
    }
  }
};

프록시 서버를 사용하면 API 서버에서는 같은 도메인에서 온 요청으로 인식해 CORS 에러가 나지 않음

Hot Module Replacement

  • 브라우저를 새로고침하지 않아도 웹팩으로 빌드한 결과물이 웹 어플리케이션에 실시간으로 반영될 수 있게 도와주는 설정 (LiveReload)
  • React, AngularJS, Vue.js 등 대부분의 프레임워크에서 HMR을 사용할 수 있는 로더 지원
// webpack.config.js
module.exports = {
  devServer: {
    hot: true
  }
}

Source Map

  • 배포용으로 빌드한 파일과 원본 파일을 연결
  • 서버에 배포시 성능 최적화를 위해 웹 자원을 압축 → 에러가 나는 경우 소스 맵을 사용해 배포용 파일의 특정 부분이 원본 소스의 어느 부분인지 확인
// webpack.config.js
module.exports = {
  devtool: 'cheap-eval-source-map'
}

5. Advanced

웹팩 실행 모드 - mode

// webpack.config.js
module.exports = {
  mode: 'none',
  entry: '',
  // ...
}
  • none : 모드 설정 안함 - production 모드로 자동 설정
  • development : 개발 모드 - 개발자들이 보기 편하게 로그나 결과물
  • production : 배포 모드 - 성능 최적화를 위해 파일 압축 등 빌드 과정 추가

실행 모드에 따라 다른 웹팩 설정
개발할 때 사용할 웹팩 설정, 배포할 때 사용할 웹팩 설정 구분 필요

// webpack.config.js
module.exports = (env) => {
  let entryPath = env.mode === 'production'
    ? './public/index.js'
    : './src/index.js';

  return {
    entry: entryPath,
    output: {},
    // ...
  }
}
// package.json
{
  "build": "webpack",
  "development": "npm run build -- --env.mode=development",
  "production": "npm run build -- --env.mode=production"
}

Tree Shaking

  • 사용되지 않는 코드를 제거하는 최적화 과정
  1. ES6 모듈 포맷
import { sum } from '../utilFile';
  1. common.js로 컴파일되는 것 방지
"presets": [
  [
    "@babel/preset-env",
    { "modules": false }
  ],
],
  1. package.json에 sideEffects 속성
{
  "name": "...",
  "sideEffects": false,
}
  1. webpack production mode
module.exports = {
	mode: "production",
	...
}

Webpack Merge

  • 웹팩 설정 파일을 하나로 병합해주는 라이브러리
  • 실행 모드에 따라 조건문으로 설정을 구분하는 것보다 파일을 나누는 것이 더 권장되기 때문에 머지 사용
  • 공통 설정 파일
// webpack.common.js
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin(),
  ],
}

entry, output, plugins과 같이 실행 모드에 관계없는 코드

  • 개발용 설정 파일
// webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: { contentBase: './dist' }
});

개발자 도구나 웹팩 데브 서버 설정 추가

  • 배포용 설정 파일
// webpack.prod.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'production'
});

배포하기 전 웹 리소스 최적화를 위한 설정


참고자료
https://joshua1988.github.io/webpack-guide/guide.html

0개의 댓글