April 10th 2019
이 포스팅은 개인적인 학습을 위해 번역을 했습니다. 오역이 없게 하려 노력했지만, 번역한 일부 내용이 틀릴수도 있습니다. 그래도 학습에 도움이 되셨으면 좋겠습니다. :)
가장 인기있는 모듈 번들러인 Webpack이 대대적인 업데이트를 진행했습니다. what’s new? 성능 향상, 무설정, 강력한 default 기능
Webpack은 매우 강력한 기능을 가지고 있지만, 배우는 것과 설정하는 것이 쉽지 않습니다. 중간, 대규모 단위의 애플리케이션 제작 시 webpack을 설정하는 것은 자연스럽지만, 소규모 앱을 빠르게 시작하고 싶을 때는 성가신 작업이 될 수 있습니다.
Webpack 4는 기본적으로 configutaion 파일 설정이 필요하지 않습니다.
새로운 폴더를 만들고, 해당 폴더로 이동합니다.
mkdir webpack-4-quickstart && cd $_
'npm init' 명령어로 package.json 파일을 초기화 합니다.
npm init -y
webpack을 설치합니다.
npm i webpack --save-dev
webpack-cli또한 설치가 필요합니다.
npm i webpack-cli --save-dev
다음으로 package.json 파일을 열고, 아래의 script를 추가합니다.
"scripts": {
"build": "webpack"
}
저장 후 파일을 닫습니다.
아래의 코드를 실행해 보세요.
npm run build
다음과 같은 에러 화면을 볼 수 있습니다.
ERROR in Entry module not found: Error: Can't resolve './src' in '~/webpack-4-quickstart'
webpack 4sms './src'경로에서 entry point를 찾고 있습니다. 간략히 설명하면, "entry point"는 webpack이 자바스크립트를 번들을 시작하기 위한 파일입니다.
이전 버전의 webpack에서는 webpack.config.js 파일에 entry point를 명시해 주어야 했습니다. Webpack 4는 entry point를 설정해 줄 필요는 없고, default 값으로 '/src/index.tsx'가 설정되어 있습니다. default 값을 테스트 해보는 것은 쉽습니다. './src/index.tsx' 파일을 생성해 봅시다.
console.log(`I'm a silly entry point`);
그리고 다음의 코드를 실행합니다.
npm run build
그러면, "~/webpack-4-quickstart/dist/main.js" 경로에 bundle 파일이 생깁니다. output 파일을 별도로 설정해 줄 필요가 없습니다. Webpack의 주요 장점 중 하나는 코드 분리이지만, webpack 4에서 설정 없이도 사용할 수 있는 기능은 작업을 빠르게 진행하는데 도움을 줍니다.
default로 webpack은 .src/index.js를 entry point로 삼고, ./dist/main.js의 경로로 번들링 합니다.
webpack을 사용할 때, development용, production용 두 개의 configuration 파일을 생성하는 것이 일반적입니다.
규모가 큰 프로젝트의 경우 두 개의 파일이 필요할 수 있지만, webpack 4에서 별도의 설정으로 위의 작업을 대신해 한 개의 파일로 처리가 가능합니다.
webpack4에서 production 모드와 development 모드를 도입했습니다. "npm run build" 명령어를 실행해 보면 아래와 같은 경고 문구를 볼 수 있을 것입니다.
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/
이제 package.json 파일을 열고, script section에 아래의 문구를 추가해 봅시다.
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
}
그리고 아래 명령어를 다시 실행합니다.
npm run dev
그리고 './dist/main.js'를 확인해 보면, minified 되지 않은 파일을 확인할 수 있습니다. 이번에는 아래의 명령어로 실행해 봅시다.
npm run build
이번에는 minifiled bundle을 확인할 수 있습니다. Production mode에서는 code minification, scope hosting, tree-shaking 등의 최적화 작업이 이루어 집니다.
반면, Development mode에서는 속도적인 측면에서 최적화 작업이 이루어지고, code minification 작업은 이루어지지 않습니다.
webpack 4에서 entry point, output을 별도로 설정하려면 아래와 같이 package.json 파일에서 설정할 수 있습니다.
"scripts": {
"dev": "webpack --mode development ./foo/src/js/index.tsx --output ./foo/main.js",
"build": "webpack --mode production ./foo/src/js/index.tsx --output ./foo/main.js"
}
모던 자바스크립트는 대부분 ES6를 기반으로 작성되지만, ES6가 모든 브라우저에 호환되지는 않습니다. 따라서, ES6를 변환에 주어야 하는데 이러한 변환 작업을 transpiling이라고 합니다. Transpiling을 통해 old browser도 ES6를 이해할 수 있게 됩니다.
Webpack은 위의 작업(transformation)에 대해서는 알지 못 합니다. 하지만 webpack에 'loader'라는것이 존재합니다.
babel-loader는 ES6를 ES5로 transpiling 해주는 webpack의 loader입니다.
Loader를 사용하기 위해서는 몇 가지 설지해야 하는 dependencies가 존재합니다. 예를 들어 아래와 같은 것들이 있습니다.
아래와 같이 설치해 봅시다.
npm i @babel/core babel-loader @babel/preset-env --save-dev
다음으로 babel 설정을 위해 프로젝트 폴더 안에 .babelrc 파일을 생성합니다.
{
"presets": ["@babel/preset-env"]
}
현 상태에서 babel-loader를 설정할 수 있는 두 가지 방법이 있습니다.
앞서 잠깐 언급했듯이, webpack 4는 설정없이 사용하는 툴로 소개되고 있습니다. webpack4의 "zero configuration"은 주요 컨셉은 아래와 같습니다.
하지만, webpack 4에서 loader를 사용하기 위해서는 설정 파일은 생성해야 합니다. webpack의 core team 중 한 명인 Sean Larkin은 아래와 같이 설명합니다.
우리는 너무 많은 기능을 default로 추가하는 것을 원치 않습니다. 다만, 우리는 다른 사용자들이 그러한 부분을 확장할 수 있도록 열어두고 있습니다. 향후(webpack 4.x or 5.0)에 이러한 것들을 preset이나 addon system을 통해서 어떻게 구현하기 위해 현재 작업중에 있습니다.
configuration 파일과 함께 babel-loader 사용하기 기존의 방법으로 babel-loader를 사용하기 위해 webpack 설정 파일을 생성하겠습니다. 아래와 같이 webpack.config.js 파일을 생성하세요.
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
}
};
entry point를 별도로 설정할 것이 아니라면, 추가로 설정할 필요는 없습니다.
다음으로 ./src/index.tsx 파일을 열고 ES6 코드를 작성해 봅니다.
const arr = [1, 2, 3];
const iAmJavascriptES6 = () => console.log(...arr);
window.iAmJavascriptES6 = iAmJavascriptES6;
아래의 명령어로 다시 번들링을 한 후 ./dist/main.js 파일을 확인해 봅니다.
npm run build
configuration 파일 없이 babel-loader 사용하기 --module-bind는 webpack loader를 사용하는 또다른 방법입니다. 이 flag는 command line에서 webpack을 사용할 수 있도록 해 줍니다. flag는 webpack 3에서부터 사용할 수 있었습니다.
configuration file없이 babel-loader를 사용하기 위해, package-json 파일의 npm script를 아래와 같이 수정할 수 있습니다.
"scripts": {
"dev": "webpack --mode development --module-bind js=babel-loader",
"build": "webpack --mode production --module-bind js=babel-loader"
}
React를 설치합니다.
npm i react react-dom --save-dev
다음으로 babel-preset-react를 설치합니다.
npm i @babel/preset-react --save-dev
.babelrc를 에서 preset 설정을 합니다.
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
.jsx파일을 읽도록 babel-loader를 설정할 수 있고, React component에서 jsx extension을 사용한다면 이 설정을 통해 작업을 수월하게 진행할 수 있습니다.
webpack.config.js 파일을 열고 loader를 다음과 같이 설정해 주세요.
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
}
};
위 설정의 테스트를 위해 아래와 같이 React component를 생성해 봅시다. (./src/App.js):
import React from 'react';
import ReactDOM from 'react-dom';
const App = () => {
return (
<div>
<p>React here!</p>
</div>
);
};
export default App;
ReactDOM.render(<App />, document.getElementById('app'));
생성한 App component를 ./src/index.js에서 import해 줍니다. 그리고 build 명령어를 다시 실행해 봅시다.
webpack이 HTML을 처리하기 위해서는 html-webpack-plugin, html-loader 두 component가 추가로 필요합니다.
아래와 같이 dependencies를 설치해 줍니다.
npm i html-webpack-plugin html-loader --save-dev
그리고 아래와 같이 webpack을 설정해 줍니다.
const HtmlWebPackPlugin = require('html-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
options: { minimize: true }
}
]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './src/index.html',
filename: './index.html'
})
]
};
다음으로 HTML 파일을 생성해 줍니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>webpack 4 quickstart</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
다시 빌드해 줍니다.
npm run build
./dist 폴더를 확인해 보면 HTML 파일이 있는 것을 확인할 수 있습니다. Javascript 파일을 HTML 파일에 추가할 필요 없이, 번들된 파일이 자동적으로 추가가 됩니다.
./dist/index.html 파일을 브라우저에서 열면 위에서 작성한 React Component를 확인할 수 있습니다.
webpack 4는 자바스크립트를 모듈 번들러이지만, HTML을 entry point로 추가할 계획을 가지고 있습니다.
저(글쓴이)는 Vue를 좋아하합니다. 많은 프로젝트에서 Vue를 사용하기 좋습니다. full SPA로 전환을 원치 않는 legacy web app을 작업한다고 생각해보세요. Vue를 사용하면 기존의 HTML을 폐기할 필요가 없습니다.
Webpack 프로젝트 안에서 Vue를 사용하려면, 다음의 라이브러리 설치를 해야합니다.
npm i vue --save-dev
테스팅을 위해서 src/index.js의 내용을 Vue instance로 변경해 보세요.
import Vue from 'vue';
const app = new Vue({
el: '#app',
data: {
message: 'hello Vue!'
}
});
다음으로 Vue를 번들링하기 위해서 webpack.config.js 파일을 설정해 줍니다.
resolve: {
alias: {
vue$: 'vue/dist/vue.esm.js';
}
}
(plugin seciton 바로 다음에 위의 명령어를 추가하면 됩니다)
이제 npm run build를 하면 HTML 파일에 Vue instance가 추가됩니다.
webpack 자체는 css를 파일로 추출할 수 없습니다. 과거에 이것은 extract-text-webpack-plugin의 몫이였습니다. 하지만 extract-text-webpack-plugin은 webpack 4에서 잘 동작하지는 않습니다. 이에 대응하기 위해 mini-css-extract-plugin을 사용할 수 있습니다.
plugin과 css-loader를 설치합니다.
npm i mini-css-extract-plugin css-loader --save-dev
다음으로 테스트를 위해 css 파일을 생성합니다.
// ./src/main.css
body {
line-height: 2;
}
그리고 아래와 같이 plugin과 loader를 설정합니다.
const HtmlWebPackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
options: { minimize: true }
}
]
},
{
test: /\.css/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './src/index.html',
filename: './index.html'
}),
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
})
]
};
마지막으로 css 파일을 entry point에 import합니다.
//
// PATH OF THIS FILE: ./src/index.tsx
//
import style from './main.css';
npm run build를 다시 실행 후 ./dist 폴더를 확인합니다. css 결과를 확인할 수 있습니다. 다시 말하면 extract-text-webpack-plugin는 webpack 4에서 작동하지 않으며, mini-css-extract-plugin을 사용해야 합니다.
코드를 수정할 때마다 npm run dev를 실행하는 것은 성가신 작업입니다. 이를 해결하기 위해 webpack의 개발 development server를 설정해 줄 수 있습니다. 일단 설정을 하게되면, 코드를 수정할 때마다 브라우저도 refresh하게 됩니다.
webpack dev server를 설정하기 위해 다음을 설치해 줍니다.
npm i webpack-dev-server --save-dev
npm run start를 실행해, 개발환경에서 좀 더 수월하게 webpack을 이용해 작업할 수 있습니다.