Webpack 정리
2018-04-19
Webpack 은 무엇인가?
- 서로 연관 관계가 있는 웹 자원들을 js, css, img 와 같은 스태틱한 자원으로 변환해주는 모듈 번들러
Webpack 을 사용하는 이유 & 배경
- 새로운 형태의 Web Task Manager
- 기존 Web Task Manager (Gulp, Grunt)의 기능 + 모듈 의존성 관리
- 예) minification 을 webpack default cli 로 실행 가능
webpack -p
- 자바스크립트 Code based Modules 관리
- 자바스크립트 모듈화의 필요성: AMD, Commong.js ES6(Modules)
- 기존 모듈 로더들과의 차이점: 모듈 간의 관계를 청크(chunk) 단위로 나눠 필요할 때 로딩
- 현대의 웹에서 JS 역할이 커짐에 따라, Client Side에 들어가는 코드량이 많아지고 복잡해짐
- 복잡한 웹 앱을 관리하기 위해 모듈 단위로 관리하는 Common.js, AMD, ES6 Modules 등이 등장
- 가독성이나 다수 모듈 미병행 처리등의 약점을 보완하기 위해 Webpack 등장
자바스크립트 모듈화 문제란?
<!-- script 태그로 간단히 자바스크립트 모듈화를 시도 하는 예제 -->
<script src="module1.js"></script>
<script src="library1.js"></script>
<script src="module2.js"></script>
<script src="module3.js"></script>
- 상기 모듈 로딩 방식의 문제점: 전역변수 충돌, 스크립트 로딩 순서, 복잡도에 따른 관리 문제
- 이를 해결하기 위해 모듈로더들과 웹팩 등장
Webpack 의 철학
- Everything is Module
- 모든 웹 자원(js, css, html)은 모듈 형태로 로딩 가능
require('base.css');
require('main.js');
- Load only ‘what’ you need and ‘when’ you need
- 필요할 때 필요한 것만 로딩하여 사용
Webpack Entty
- webpack 으로 묶은 모든 라이브러리들을 로딩할 시작점 설정
- a, b, c라이브러리를 모두 번들링한 bundle.js 를 로딩한다.
- 1개 또는 2개 이상의 엔트리 포인트를 설정할 수 있다.
// entry 설정 예
{
entry: './public/src/index.js' // String
entry: ['./public/src/index.js'] // Array
entry: {
index: './public/src/index.js' // Object
}
}
// Entry 유형
var config = {
// #1 - 간단한 entry 설정
entry: './path/to/my/entry/file.js'
// #2 - 앱 로직용, 외부 라이브러리용
entry: {
app: './src/app.js'
vendors: './src/vendors.js'
}
// #3 - 페이지당 불러오는 js 설정
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js'
}
}
Multiple Entryt Points
- 복수개 엔트리 포인트에 대한 설정 예시
// webpack.config.js
module.exports = {
entry: {
Profile: './profile.js',
Feed: './feed.js'
},
output: {
path: '[name].js' // 위에 지정한 entry 키의 이름에 맞춰서 결과 산출
}
}
// 번들파일 Profile.js 를 <script src="build/Profile.js"></script>로 HTML에 삽입
Webpack output
- entry 에서 설정하고 묶은 파일의 결과값을 설정
var path = require('path');
module.exports = {
entry: {
// ...
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
// filename: '[name].js'
}
}
Output Name Options
output: {
filename: '[name].js' // 1
filename: '[hash].js' // 2
filename: '[chunkhash].js' // 3
}
참고 API
path.join()
- 해당 API가 동작되는 OS의 파일 구분자를 이용하여 파일 위치를 조합.
path.join('/foo', 'bar', 'baz/asdf');
// retrun: '/foo/bar/baz/asdf'
path.resolve()
join()
의 경우 문자열만 합치지만,resolve()
의 경우 으론쪽에서 왼쪽으로 파일 위치를 구성해가며 유효한 위치를 찾는다.- 만약 결과 값이 유효하지 않으면 현재 디렉토리가 사용된다. 반환되는 위치 값은 항상 absolute URL이다.
path.resolve('/foo/bar', './baz');
// return: 'foo/bar/baz'
path.resolve('/foo/bar', '/tmp/file/');
// return: '/tmp/file'
path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
// if the current working directory is /home/myself/node,
// this returns '/home/myself/node/wwwroot/static_files/gif/image.gif'
Webpack Loader
- 웹팩은 자바스크립트 파일만 처리 가능하도록 되어 있다.
- loader를 이용하여 다른 형태의 웹 자원들을(img, css, …) js로 변환하여 로딩
module.exports ={
entry: {},
output: {},
module: {
rules: [
{ test: /\.css$/ , use: ['style-loader', 'css-loader'] }
]
}
}
- loader 에서 모듈 로딩 순서는 배열의 요소 오른쪽에서 왼쪽으로 진행된다.
{
test: /backbone/,
use: [
'expose-loader?Backbone',
'imports-loader?+=underscore,jquery'
// 순서대로 1 jquery, 2 underscore 로딩
]
}
- 위 설정파일을 webpack으로 번들링한 결과
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
var _ = __webpack_require__(0);
var jquery = __webpack_require(1);
Babel Loader - ES6
- preset: Babel 플러그인 리스트
module: {
reles: [{
test: /\.js$/,
use: [{
loader: 'babel-loader',
options: {
presets: [
['es2015', 'react', {modules: false}] // Tree shaking: 모듈에서 사용되 않으면 추가하지 않음
]
}
}]
}]
}
Webpack resolve
- Webpack 의 모듈 번들링 관점에서 봤을 때, 모듈 간의 의존성을 고려하여 모듈을 로딩해야 한다.
- 따라서, 모듈을 어떤 위치에서 어떻게 로딩할지에 관해 정의를 하는 것이 바로 Module Resolution
// 일반적인 모듈 로딩 방식
import foo from 'path/to/module'
// 또는
require('path/to/module');
- 절대경로를 이용한 파일 로딩
- 파일의 경로를 모두 입력해준다.
import '/home/me/file'; import 'C:\\User\\me\\file';
- 파일의 경로를 모두 입력해준다.
- 상대경로를 이용한 파일로딩
- 해당 모듈이 로딩되는 시점의 위치에 기반하여, 상대 경로를 절대 경로로 인식하여 로딩.
import '../src/file1' import './file2'
- 해당 모듈이 로딩되는 시점의 위치에 기반하여, 상대 경로를 절대 경로로 인식하여 로딩.
Resolve Optioin
- Config 파일에
resolve
를 추가하여 모듈 로딩에 관련된 옵션 사용 - alias
- 특정 모듈을 로딩할때
alias
옵션을 이용하면 별칭으로 더 쉽게 로딩이 가능.
alias: { Utilities: path.resolve(__dirname, 'src/path/utilities/') } import Utility from '../../src/path/utilities/utility'; // alias 사용시 '/src/path/utilities/' 대신 'Utilities' 사용 import Utility from 'Utilities/utility';
- 특정 모듈을 로딩할때
- Modules
require()
import ''
등의 모듈 로딩시에 어느 폴더를 기준할 것인지 정하는 옵션
modules: [node_modules] // default
modules: [path.resolve(__dirname, 'src'), 'node_modules'] // src/node_modules
webpack 빌드를 위한 개발 서버 구성
webpack-dev-server
: webpack 자체에서 제공하는 개발 서버이고 빠른 리로딩 기능 제공webpack-dev-middleware
: 서버가 이미 구성된 경우에는 webpack 을 미들웨어로 구성하여 서버와 연결
Webpack Dev Server
- 페이지 자동고침을 제공하는 webpack 개발용 node.js 서버