[webpack] webpack.config.js 훑어보기

소면(Somyeon)
12 min readMar 27, 2021

웹팩은 자바스크립트 모듈 번들러(bundler)이다. bundle은 묶음이란 뜻을 가지고 있는데, 웹팩은 여러 자바스크립트 모듈을 하나의 자바스크립트 파일로 묶어주는 역할을 한다.

웹팩 4.0 버전 이상부터 웹팩은 기본적으로 프로젝트의 src/index.js 파일을 dist/main.js 파일로 번들링해준다. 하지만 우리의 프로젝트는 저마다 다른 구성을 이루고 있고, 모든 프로젝트를 동일한 조건으로 번들링한다는 것은 거의 불가능할 것이다. 웹팩에서는 이러한 환경을 위해 각 프로젝트의 루트 폴더에 webpack.config.js 파일을 생성하도록 하고 있다. webpack.config.js 파일에 내 프로젝트에 적용된 다양한 옵션을 설정하면 웹팩이 해당 파일을 자동으로 읽고 이에 맞게 번들링을 해준다.

wepback.config.js 파일에서는 아래의 옵션을 설정할 수 있다.

  • entry
  • output
  • module
  • plugins
  • resolve
  • mode
  • devtool
  • target
  • externals

webpack 5 버전을 중심으로 주로 사용되는 옵션을 알아보자.

Entry

entry는 웹팩이 어떠한 파일을 기준으로 삼고 번들링할 것인지 설정한다. 웹팩은 entry로 지정된 파일이 다른 어떠한 모듈을 import 하고 있는지 확인하고 함께 번들링 한다.

module.exports = {
entry: ‘./src/index.js’
};

네이밍

entry에 객체를 전달하면 번들링한 결과물의 이름을 설정해줄 수도 있다. 각 key는 번들링되는 파일의 이름을 의미하고 value는 해당 파일의 엔트리 파일을 지정한다.

// home.js, about.js, concat.js 파일을 home, about, concat 이름의 파일로 번들링한다.module.exports = {
entry: {
home: './home.js',
about: './about.js',
contact: './contact.js',
},
};

다중 엔트리 포인트

entry에 배열을 전달하면 여러 파일을 엔트리로 지정할 수 있다.

module.exports = {
entry: {
home: ['./home.js', './about.js', './contact.js'],
},
};

엔트리 기술자 (descriptor)

entry에 객체를 전달하면 엔트리에 추가할 옵션을 설정할 수 있다.

module.exports = {
entry: {
catalog: {
import: './catalog.js',
filename: 'pages/[name].js',
dependOn: 'shared',
},
shared: ['react', 'react-dom', 'redux', 'react-redux'],
},
};
  • import : 엔트리 파일을 지정한다.
  • filename : 기본적으로 번들링한 결과물의 경로와 이름은 output 옵션에서 작성하지만 entry 에서도 지정할 수 있다. 파일명에 [name]을 입력하면 위에서 지정한 번들링한 결과물의 이름을 적용할 수 있다.
  • dependOn : 기본적으로 모든 번들링한 결과물은 entry가 의존하고 있는 모듈의 코드를 포함하고 있다. dependOn 옵션을 사용하면 해당 옵션의 모듈을 공유할 수 있다.
// app 파일은 react-vendors의 모듈을 직접 포함하지 않지만 react-vendors 파일의 모듈을 공유한다.module.exports = {
//...
entry: {
app: {
import: './app.js',
dependOn: 'react-vendors'
},
'react-vendors': [
'react',
'react-dom',
'prop-types'
],
},
};

context

contextentryloaders 옵션의 기본 디렉토리를 절대경로로 설정한다. 웹팩에서는 기본적으로 현재 디렉토리를 기본 디렉토리로 적용하고 있기에 실무에서는 잘 사용하지 않는 듯하다. 하지만 context를 설정해주면 webpack.config.js파일의 경로가 현재 경로에 의존하지 않을 수 있기에 웹팩 공식 문서에서는 이를 명시적으로 설정할 것을 권유하고 있다.

// 사용되는 entry와 loader 파일 경로를 /디렉토리/app/으로 설정한다.const path = require('path');module.exports = {
context: path.resolve(__dirname, 'app'),
};

Output

output 옵션은 번들링한 결과물의 옵션을 설정한다.

module.exports = {
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'public/assets'),
publicPath: '/assets/',
},
};

filename

번들링한 결과물의 이름을 지정한다. [name]을 사용하면 entry에서 전달한 객체의 key로 파일명이 설정된다. (웹팩에서는 대괄호 []를 이용하여 템플릿 문자열을 사용할 수 있다. [name]이 이외에도 [id], [hash]를 이용하여 파일명을 설정할 수 있다.)

path

번들링한 결과물이 저장되는 경로를 지정한다.

publicPath

웹팩으로 output.path의 경로에 번들링 되는 결과물을 브라우저에서 접근할 때 publicPath에 설정한 경로로 접근할 수 있다. 또한 webpack.config 파일에 설정한 loader(file-loader, url-loader 등)에서 처리하는 파일(폰트, 이미지 등)의 경로에 prefix로 적용되는 경로를 설정한다. publicPath 옵션에 상대경로를 지정하면 HTML 페이지에 상대적인 경로로 되며, CDN 서버나, 프로토콜, 혹은 절대 경로 또한 publicPath의 옵션으로 지정할 수 있다.

// 브라우저에서 '/assets/app.js' 파일을 요청하면 '/public/assets/app.js' 경로에 있는 파일을 불러온다.module.exports = {
output: {
filename: 'app.js',
path: path.resolve(__dirname, 'public/assets'),
publicPath: '/assets/',
},
};

Module

웹팩은 원래 자바스크립트와 json 파일 밖에 해석하지 못하지만 loader를 이용하면 HTML, CSS, Image등 다른 형식의 파일을 해석하고 모듈로 변환시킬 수 있다. loadermodule속성의 rules에 로더의 속성이 담긴 객체가 배열로 적용된다.

// css 파일을 해석하고 html에 inline-style로 추가해주는 로더를 추가한다. css-loader가 먼저 적용된 뒤 style-loader가 적용된다.module.exports = {
module: {
rules: [{
test: /\.css$/,
exclude: /node_modules/,
use: ['style-loader, 'css-loader'],
}],
},
};
  • test : loader를 이용하여 변환될 파일의 확장자를 설정한다. 주로 정규표현식을 이용하여 적용한다.
  • use : 어떠한 loader를 사용할지 작성한다. 배열에 여러 개의 loader를 적용할 수 있는데 오른쪽에서 왼쪽 순으로 loader가 적용된 후 컴파일 된다.
  • exclude : loader가 적용되지 않을 파일을 설정한다. 주로 정규표현식을 이용하여 적용한다.

use에 배열 대신 객체를 적용하면 아래와 같이 loader의 옵션을 설정할 수 있다.

// babel loader를 추가한다.module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
{'targets': 'defaults'}
]
}
}
}
]
}
}
  • loader : 적용할 loader를 설정한다.
  • options : loader에 적용되는 옵션을 설정한다. @babel/presets-env 는 최신 자바스크립트를 target에 설정한 하위 브라우저에서도 동작할 수 있도록 변환해준다.

Plugins

plugins 옵션은 웹팩 번들링 과정을 커스터마이징 하는데 사용되는 플러그인을 배열로 적용한다. loader는 파일을 해석하고 변환하는 과정에 작용하지만 plugins는 번들링한 결과물에 작용한다. 웹팩은 webpack.[plugin-name] 의 이름을 가진 플러그인들을 내장하고 있다.

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

Resolve

resolve 옵션은 웹팩이 모듈을 어떻게 해석할지 설정한다. 예를 들어 파일 내에서 lodash 모듈을 import한다면 resolve 옵션을 이용해 어디서 lodash 모듈을 가져올지 변경할 수 있다.

alias

파일 내에서 모듈을 쉽게 import하거나 require할 수 있도록 설정한다. 아래와 같이 설정해 준다면,

module.exports = {
resolve: {
alias: {
Utilities: path.resolve(__dirname, 'src/utilities/'),
Templates: path.resolve(__dirname, 'src/templates/'),
},
},
};

상대 경로로 모듈을 import하는 대신

import Utility from '../../utilities/utility';

아래와 같이 import할 수 있다.

import Utility from 'Utilities/utility';

extensions

모듈을 import 할 때 확장자를 적지 않더라도 extensions 옵션의 확장자를 왼쪽에서 오른쪽으로 적용할 수 있다. 이 옵션을 적용하면 기존 웹팩에 적용된 extensions가 적용되지 않는다.

아래와 같이 적용한다면,

module.exports = {
resolve: {
extensions: ['.wasm', '.mjs', '.js', '.json'],
},
};

아래와 같이 모듈을 import 할 수 있다. 웹팩은 extensions 옵션의 왼쪽에서부터 오른쪽으로 확장자를 적용해 해당하는 모듈을 import 한다.

import File from '../path/to/file';

Mode

웹팩이 번들링하는 모드를 설정할 수 있다. production 혹은 development를 설정한다.

아래와 같이 wepback.config.js 파일에 mode 옵션을 설정하거나

module.exports = {
mode: 'development',
};

cli에서 아래와 같이 webpack을 실행할 수도 있다.

webpack --mode=development

Devtool

source map의 스타일을 설정한다. source map은 원본 파일과 번들링한 파일을 매핑해주는 기능이다. 빌드 시에는 모든 파일이 압축되는데 source map은 압축된 파일이 원본 파일의 어느 부분에 해당하는지 알게 해준다. source map을 이용하면 개발 시 오류가 발생했을 때 디버깅을 쉽게 할 수 있다.

source map 스타일은 다양하며 모드에 따라 설정할 수 있다. 아래 링크에서 전체 source map 옵션을 확인할 수 있다.

https://webpack.js.org/configuration/devtool/#devtool

Target

번들링한 자바스크립트의 타겟 버전을 설정한다. node혹은 web을 지정할 수 있으며, nodeweb의 각 버전 또한 지정할 수 있다.

module.exports = {
target: 'node12.18',
};

target의 값이 배열로 설정될 경우 공통 기능의 하위 버전으로 번들링한다.

아래와 같이 설정할 경우 webES5만 사용한다.

module.exports = {
target: ['web', 'es5'],
};

아래와 같이 서로 다른 환경의 타겟을 같이 설정할 수 없다.

module.exports = {
// ...
target: ['web', 'node'],
};

번들링한 결과물이 IE11에서도 실행될 수 있도록 target: ['web', 'es5'] 을 설정했더니 webpack-dev-server에서 HMR이 동작하지 않는 오류가 발생했다. target: 'es5' 도 동일하게 동작하지 않았고 target: 'web'HMR이 정상적으로 동작하였다.

https://webpack.js.org/configuration/devtool/

externals

번들링할 때 제외시킬 파일을 설정한다. externals에 설정한 모듈을 import할 경우 번들링 단계에서 해당 모듈이 존재하지 않더라도 에러가 발생하지 않는다. 런타임 환경에서 추가된 외부 라이브러리를 entry 파일에서 사용할 경우 externals 옵션을 설정하면 된다.

예를들어 html 파일에 jQuery 스크립트 파일을 임베딩할 경우,

<script
src="https://code.jquery.com/jquery-3.1.0.js"></script>

아래와 같이 externals 옵션을 설정한다.

// 파일에서 import(‘jquery’)를 하면 global.jQuery를 가져온다.module.exports = {
externals: {
jquery: 'jQuery',
},
};

entry 파일 내부에선 아래와 같이 import 해서 사용할 수 있다.

import $ from 'jquery';

$('.my-element').animate(/* ... */);

--

--