웹팩 입문: 1. HTML, CSS 사용하기
소스코드
https://github.com/shlee1353/webpack-example/tree/01_html_css
1. 웹팩이란?
서버 사이드 템플릿 시대를 지나 단일 페이지 애플리케이션(Single Page Application, SPA) 개발이 점차 인기를 얻으면서 자바스크립트의 코드량이 과거에 비해 기하급수적으로 증가하게 되었습니다. 많게는 수천, 수만 줄이나 하는 자바스크립트 코드에서 특정 코드를 찾아 수정하기란 쉽지 않은 일입니다. 그래서, 개발 초기 단계에서 API 기능과 UI 컴포넌트에 맞게 자바스크립트 코드를 분리하게 되었습니다. 하지만, 분리해 놓은 여러개의 자바스크립트 파일들을 한 개씩 따로 불러온다면 웹 페이지 로딩시 속도 저하 문제가 발생할 수 있습니다. 그렇기 때문에 웹팩을 사용하여 수 많은 자바스크립트 파일들을 하나의 js 파일로 번들링하는 작업이 필요하게 되었습니다.
그럼 기존 html과 css를 Webpack을 통해 어떻게 사용할 수 있을까요? 이 질문에 대한 답변을 알아보기 전에, 랜더링 프로세스와 관련된 간단한 배경지식이 필요합니다. 브라우저의 랜더링 과정은 다음과 같습니다.
- HTML 마크업을 처리하고 DOM 트리 빌드
- CSS 마크업을 처리하고 CSSOM 트리 빌드
- DOM 및 CSSOM이 결합되어 렌더링 트리 형성
- 레이아웃을 실행하여 각 노드의 기하학적 형태 계산
- 개별 노드를 화면에 페인트
여기서, html과 css는 렌더링 차단 리소스로 취급이 되어, DOM과 CSSOM이 생성되기 전까지 브라우저는 모든 콘텐츠의 랜더링을 중단합니다. 만약, css가 늦게 로딩 될 경우, 최초 랜더링 시간이 길어져 성능 이슈가 발생합니다. 아래 예시처럼, css ‘미디어 유형’과 ‘미디어 쿼리’를 사용하면 이러한 문제점을 해결할 수 있지만 일반적이지는 않습니다.
<link href="style.css" rel="stylesheet">
<link href="print.css" rel="stylesheet" media="print">
<link href="other.css" rel="stylesheet" media="(min-width: 40em)">
알다시피, 자바스크립트는 DOM 및 CSSOM을 쿼리하고 수정할 수 있으며, CSSOM이 준비될 때까지 실행이 일시 중지됩니다. 결국, Webpack을 통한 번들링 작업은 브라우저 랜더링 시 로딩되는 외부 소스파일들을 단일 js파일로 만들어 주기 때문에 성능향상에 큰 도움을 줍니다. 이제부터 Webpack에서 html과 css를 다루는 방법에 대해 설명하도록 하겠습니다. 설치부터 사용까지 직접 해보시는 걸 추천드립니다.
2. 웹팩설치 및 설정
// npm, node 설치확인
npm -v
node -v// 폴더 생성 및 이동
mkdir webpack_example && cd webpack_example// npm 초기화 및 웹팩 설치
npm init// 웹팩 모든버전 보기
npm view webpack versions --json// 웹팩 특정버전 설치
npm install --save-dev webpack@3.8.1
package.json 파일은 아래와 같으며, npm install 명령어를 통해 필요한 패키지를 설치할 수 있습니다.
// package.json
{
"name": "webpack_example",
"version": "1.0.0",
"description": "webpack project starter.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^3.8.1"
}
}
다음으로, webpack.config.js 파일을 생성합니다. 이 파일을 통해서 config 객체를 정의하여 module.exports를 통해 외부로 노출시킬 수 있습니다. config파일은 기본적으로 entry, output, module, plugins를 제공합니다. entry는 bundling을 위한 진입점을 나타냅니다. output은 bundling 결과물을 어떻게할지를 설정합니다.
// webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
filename: './dist/app.bundle.js'
}
}
기존 package.json 파일에서 scripts 부분을 수정하여 명령어를 쉽게 실행할 수 있습니다. npm run dev 를 실행하면 dist 폴더에 app.bundle.js 파일이 생성된 것을 확인할 수 있습니다. 아직까지, 브라우저에서 확인 할 수 있는 html 파일은 없으며, 이를 자동으로 생성하기 위해 html-webpack-plugin 설치가 필요합니다.
// package.json
...
"scripts": {
"dev": "webpack -d --watch"
},
...
3. 플러그인 사용
기본적으로, bundle한 css, js파일들은 html파일에 직접 추가해야하는 번거로움이 있습니다. html-webpack-plugin를 사용하면 이 과정을 자동화 할 수 있습니다. Webpack의 성능을 향상 시키고 개발을 편리하게 만들어 주는 것이 플러그인의 역할입니다. 사용 전 설치가 필요합니다.
npm i html-webpack-plugin --save-dev
설치가 완료되면 webpack.config.js파일을 수정합니다.
// webpack.config.js
var HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {
entry: './src/index.js',
output: {
path: __dirname + '/dist',
filename: 'app.bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
title: 'Project Demo',
minify: {
collapseWhitespace: true
},
hash: true,
template: './src/index.html'
})
]
}
우선, require()를 사용해 설치된 플러그인을 가져옵니다. template 옵션에 html파일 경로를 적어주며, 이 파일에는 css파일과 js파일을 불러오는 태그가 없습니다. dist폴더로 bundle된 index.html파일에 자동으로 들어가게 됩니다. 현재까지 디렉토리구조는 다음과 같습니다.
webpack_example
ㄴdist
ㄴapp.bundle.js
ㄴindex.html
ㄴnode_modules
ㄴsrc
ㄴindex.js
ㄴindex.html
ㄴpackage.json
이제 css를 추가하도록 하겠습니다. webpack.config.js파일에 module옵션은 bundling을 진행할 때 처리해야하는 task들을 실행할 때 사용합니다. 여기에, style-loader와 css-loader를 추가하면 됩니다. loader는 node기반으로 제작된 유틸리티이며, .css, .scss, .ts 타입의 파일들(non-javascript)을 컴파일합니다. css-loader는 css파일을 찾아 문자열로 정리해주며, style-loader는 정리된 문자열을 index.html파일 <style>태그에 넣어줍니다.
npm install css-loader style-loader --save-dev
각각의 loader를 설치한 후 webpack.config.js파일을 수정합니다. test는 css파일에 적용하는 것을 나타내며, use는 여러개의 loader를 동시에 사용할 때 사용합니다. 마지막으로, src/index.js파일에서 require(‘./app.css’) 하면 bundling에 추가되어 dist/index.html파일 header에 <style>로 들어갑니다.
// webpack.config.js
var HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {
entry: './src/index.js',
output: {
path: __dirname + '/dist',
filename: 'app.bundle.js'
},
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: 'Project Demo',
minify: {
collapseWhitespace: true
},
hash: true,
template: './src/index.html'
})
]
}
지금까지 Webpack에서 html, css 사용에 대해 간단히 알아봤습니다. 실제로 개발 및 배포를 하기 위해서는 수정된 파일을 브라우저에서 바로 확인 할 수 있어야 합니다. Webpack에서는 두 가지 인터페이스를 사용할 수 있습니다. 하나는 Webpack-CLI 기본인터페이스 이며 다른 하나는 webpack-dev-server 입니다. 여기에서는 개발모드로 좋은 webpack-dev-server에 대해 알아보도록 하겠습니다. 포트에서 실행이되며 express(node.js) 서버이며 내부적으로 Webpack을 호출되는데 실시간로딩 (Hot Module Replacement)같은 추가 기능을 사용할 수 있습니다. 우선, webpack-dev-server를 설치합니다.
npm install webpack-dev-server --save-dev
설치가 완료되면, webpack.config.js파일에 devServer 설정을 추가합니다.
// webpack.config.js
var HtmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path');module.exports = {
entry: './src/index.js',
output: {
path: __dirname + '/dist',
filename: 'app.bundle.js'
},
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader']
}
]
},
devServer: {
contentBase: path.join(__dirname, "./dist/"),
port: 9000
},
plugins: [
new HtmlWebpackPlugin({
title: 'Project Demo',
minify: {
collapseWhitespace: true
},
hash: true,
template: './src/index.html'
})
]
}
다음으로, package.json파일에서 scripts 내용을 수정하도록 하겠습니다.
// package.json
...
"scripts": {
"dev": "webpack-dev-server --hot --inline"
},
...
inline은 전체 페이지 실시간 로딩 옵션이며, hot은 파일이 수정될 경우 그 부분에 대해 리로드를 해주는 옵션입니다. 이제 npm run dev 명령어를 통해 개발 환경을 편리하게 실행 시킬 수 있습니다. 지금까지 webpack 설치 및 환경설정 후 html과 css 사용방법을 알아봤습니다.