자주사용하는 로더,플러그인
자주 사용하는 로더
1css-loader
웹팩은 모든것을 모듈로 바라보기 때문에 자바스크립트 뿐만 아니라 스타일시트로 import 구문으로 불러 올수 있다.
CSS 파일을 자바스크립트에서 불러와 사용하려면 CSS를 모듈로 변환하는 작업이 필요하다. css-loader가 그러한 역할을 가능하게 해준다
app.js:
import "./style.css"
style.css:
body {
background-color: green;
}
설치
$ npm install -D css-loader
webpack.config.js:
module.exports = {
module: {
rules: [
{
test: /\.css$/, // .css 확장자로 끝나는 모든 파일
use: ["css-loader"], // css-loader를 적용한다
},
],
},
}
2 style-loader
모듈로 변경된 스타일 시트는 돔에 추가되어야만 브라우져가 해석할 수 있다. css-loader로 처리하면 자바스크립트 코드로만 변경되었을 뿐 돔에 적용되지 않았기 때문에 스트일이 적용되지 않았다.
style-loader는 자바스크립트로 변경된 스타일을 동적으로 돔에 추가하는 로더이다.
설치
$ npm install -D style-loader
.
package.json:
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"], // style-loader를 앞에 추가한다
},
],
},
}
배열로 설정하면 뒤에서부터 앞으로 순서대로 로더가 동작한다. 위 설정은 모든 .css 확장자로 끝나는 모듈을 읽어 들여 css-loader를 적용하고 그 다음 style-loader를 적용한다.
3 file-loader
소스코드에서 사용하는 모든 파일을 모듈로 사용하게끔 할 수 있다. 파일을 모듈 형태로 지원하고 웹팩 아웃풋에 파일을 옮겨주는 것이 file-loader가 하는 일이다. CSS에서 url() 함수에 이미지 파일 경로를 지정할 수 있는데 웹팩은 file-loader를 이용해서 이 파일을 처리한다.
style.css:
body {
background-image: url(bg.png);
}
webpack.config.js:
module.exports = {
module: {
rules: [
{
test: /\.png$/, // .png 확장자로 마치는 모든 파일
loader: "file-loader", // 파일 로더를 적용한다
},
],
},
}
웹팩이 .png 파일을 발견하면 file-loader를 실행할 것이다. 로더가 동작하고 나면 아웃풋에 설정한 경로로 이미지 파일을 복사된다.(파일명이 해쉬코드로 변경 되었다. 캐쉬 갱신을 위한 처리로 보인다.)
file-loader 옵션을 조정해서 경로를 바로 잡아 주어야 한다.
module.exports = {
module: {
rules: [
{
test: /\.png$/, // .png 확장자로 마치는 모든 파일
loader: "file-loader",
options: {
publicPath: "./dist/", // prefix를 아웃풋 경로로 지정
name: "[name].[ext]?[hash]", // 파일명 형식
},
},
],
},
}
publicPath 옵션: file-loader가 처리하는 파일을 모듈로 사용할 때 경로 앞에 추가되는 문자열이다.
name 옵션: 로더가 파일을 아웃풋에 복사할때 사용하는 파일 이름이다. 기본적으로 설정된 해쉬값을 쿼리스트링으로 옮겨서 'bg.png?6453a9c65953c5c28aa2130dd437bbde' 형식으로 파일을 요청하도록 변경했다.
4url-loader
사용하는 이미지 갯수가 많다면 네트웍 리소스를 사용하는 부담이 있고 사이트 성능에 영향을 줄 수도 있다. 만약 한 페이지에서 작은 이미지를 여러 개 사용한다면 Data URL Schema을 이용하는 방법이 더 나은 경우도 있다. 이미지를 Base64로 인코딩하여 문자열 형태로 소스코드에 넣는 형식이다.url-loader는 이러한 처리를 자동화해주는 녀석이다.
설치
$ npm install -D url-loader
webpack.config.js
{
test: /\.png$/,
use: {
loader: 'url-loader', // url 로더를 설정한다
options: {
publicPath: './dist/', // file-loader와 동일
name: '[name].[ext]?[hash]', // file-loader와 동일
limit: 5000 // 5kb 미만 파일만 data url로 처리
}
}
}
5babel-loader
실무 환경에서는 바벨을 직접 사용하는 것보다는 웹팩으로 통합해서 사용하는 것이 일반적이다. 로더 형태로 제공하는데 babel-loader가 그것이다.
설치
npm install -D babel-loader
webpack.config.js
// webpack.config.js:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader", // 바벨 로더를 추가한다
},
],
},
}
.js 확장자로 끝나는 파일은 babel-loader가 처리하도록 설정했다. 사용하는 써드파티 라이브라리가 많을수록 바벨 로더가 느리게 동작할 수 있는데 node_modules 폴더를 로더가 처리하지 않도록 예외 처리했다
폴리필 사용 설정을 했다면 core-js도 설치해야한다. 웹팩은 바벨 로더가 만든 아래 코드를 만나면 core-js를 찾을 것이기 때문이다.
require("core-js/modules/es6.promise")
require("core-js/modules/es6.object.to-string")
설치
npm i core-js
6sass-loader
Sass / SCSS 파일을로드하고 CSS로 컴파일합니다.
설치
npm i sass-loader node-sass
webpack.config.js
module: {//로더 js뿐만아닌 다른파일도 모듈로처리해서 번들해줌
rules: [
{
test: /\.(scss|css)$/, //로더가 처리해야될 파일들의 패턴(정규표현식)
use: [
process.env.NODE_ENV === "production"
? MiniCssExtractPlugin.loader
:"style-loader", //style-loader:자바스크립트파일에서 css파일을 불러올수 있음(html파일에서 css직접불러오기 안해도됨)
"css-loader", //css파일을 만나면 css-loader가 처리함
"sass-loader" //sass,scss파일 처리
],
},
],
},
자주 사용하는 플러그인
1BannerPlugin
결과물에 빌드 정보나 커밋 버전같은 걸 추가할 수 있다.
webpack.config.js
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.BannerPlugin({
banner: '이것은 배너 입니다',
})
]
생성자 함수에 전달하는 옵션 객체의 banner 속성에 문자열을 전달한다.
웹팩 컴파일 타임에 얻을 수 있는 정보, 가령 빌드 시간이나 커밋정보를 전달하기위해 함수로 전달할 수도 있다.
new webpack.BannerPlugin({
banner: () => `빌드 날짜: ${new Date().toLocaleString()}`,
})
배너 정보가 많다면 별로 파일로 분리하자.
const banner = require("./banner.js")
new webpack.BannerPlugin(banner)
빌드 날짜 외에서 커밋 해쉬와 빌드한 유저 정보까지 추가해 보자.
banner.js:
const childProcess = require("child_process")
module.exports = function banner() {
const commit = childProcess.execSync("git rev-parse --short HEAD")
const user = childProcess.execSync("git config user.name")
const date = new Date().toLocaleString()
return (
`commitVersion: ${commit}` + `Build Date: ${date}\n` + `Author: ${user}`
)
}
2DefinePlugin
어플리케이션은 개발환경과 운영환경으로 나눠서 운영한다. 가령 환경에 따라 API 서버 주소가 다를 수 있다. 같은 소스 코드를 두 환경에 배포하기 위해서는 이러한 환경 의존적인 정보를 소스가 아닌 곳에서 관리하는 것이 좋다. 배포할 때마다 코드를 수정하는 것은 곤란하기 때문이다.
웹팩은 이러한 환경 정보를 제공하기 위해 DefinePlugin을 제공한다.
webpack.config.js
const webpack = require("webpack")
export default {
plugins: [new webpack.DefinePlugin({})],
}
빈 객체를 전달해도 기본적으로 넣어주는 값이 있다. 노드 환경정보인 process.env.NODE_ENV 인데 웹팩 설정의 mode에 설정한 값이 여기에 들어간다. "development"를 설정했기 때문에 어플리케이션 코드에서 process.env.NODE_ENV 변수로 접근하면 "development" 값을 얻을 수 있다.
app.js
console.log(process.env.NODE_ENV) // "development"
이 외에도 웹팩 컴파일 시간에 결정되는 값을 전역 상수 문자열로 어플리케이션에 주입할 수 있다.
new webpack.DefinePlugin({
TWO: "1+1",
})
TWO라는 전역 변수에 1+1 이란 코드 조각을 넣었다. 실제 어플리케이션 코드에서 이것을 출력해보면 2가 나올 것이다.
app.js
console.log(TWO) // 2
코드가 아닌 값을 입력하려면 문자열화 한 뒤 넘긴다.
new webpack.DefinePlugin({
VERSION: JSON.stringify("v.1.2.3"),
PRODUCTION: JSON.stringify(false),
MAX_COUNT: JSON.stringify(999),
"api.domain": JSON.stringify("http://dev.api.domain.com"),
})
app.js:
console.log(VERSION) // 'v.1.2.3'
console.log(PRODUCTION) // true
console.log(MAX_COUNT) // 999
console.log(api.domain) // 'http://dev.api.domain.com'
빌드 타임에 결정된 값을 어플리이션에 전달할 때는 이 플러그인을 사용하자.
3HtmlWebpackPlugin
HtmlWebpackPlugin은 HTML 파일을 후처리하는데 사용한다. 빌드 타임의 값을 넣거나 코드를 압축할수 있다.
설치
$ npm install -D html-webpack-plugin
이 플러그인으로 빌드하면 HTML파일로 아웃풋에 생성될 것이다.
src/index.html:
<!DOCTYPE html>
<html>
<head>
<title>타이틀<%= env %></title>
</head>
<body>
<!-- 로딩 스크립트 제거 -->
<!-- <script src="dist/main.js"></script> -->
</body>
</html>
타이틀 부분에 ejs 문법을 이용하는데 <%= env %> 는 전달받은 env 변수 값을 출력한다. HtmlWebpackPlugin은 이 변수에 데이터를 주입시켜 동적으로 HTML 코드를 생성한다.
또한 웹팩으로 빌드한 결과물을 자동으로 로딩하는 코드를 주입해 준다. 때문에 스크립트 로딩 코드도 제거했다.
webpack.config.js:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports {
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // 템플릿 경로를 지정
templateParameters: { // 템플릿에 주입할 파라매터 변수 지정
env: process.env.NODE_ENV === 'development' ? '(개발용)' : '',
},
})
]
}
환경 변수에 따라 타이틀 명 뒤에 "(개발용)" 문자열을 붙이거나 떼거나 하도록 했다.
NODE_ENV=development 로 설정해서 빌드하면 빌드결과 "타이틀(개발용)"으로 나온다.
NODE_ENV=production 으로 설정해서 빌드하면 빌드결과 "타이틀"로 나온다.
개발 환경과 달리 운영 환경에서는 파일을 압축하고 불필요한 주석을 제거하는 것이 좋다.
webpack.config.js:
new HtmlWebpackPlugin({
minify: process.env.NODE_ENV === 'production' ? {
collapseWhitespace: true, // 빈칸 제거
removeComments: true, // 주석 제거
} : false,
}
환경변수에 따라 minify 옵션을 켰다. NODE_ENV=production npm run build로 빌드하면 아래처럼 코드가 압축된다. 물론 주석도 제거 되었다.
정적파일을 배포하면 즉각 브라우져에 반영되지 않는 경우가 있다. 브라우져 캐쉬가 원인일 경우가 있는데 이를 위한 예방 옵션도 있다.
webpack.config.js:
new HtmlWebpackPlugin({
hash: true, // 정적 파일을 불러올때 쿼리문자열에 웹팩 해쉬값을 추가한다
})
hash: true 옵션을 추가하면 빌드할 시 생성하는 해쉬값을 정적파일 로딩 주소의 쿼리 문자열로 붙여서 HTML을 생성한다.
4 CleanWebpackPlugin
CleanWebpackPlugin은 빌드 이전 결과물을 제거하는 플러그인이다.
설치
$ npm install -D clean-webpack-plugin
webpack.config.js:
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
module.exports = {
plugins: [new CleanWebpackPlugin()],
}
5 MiniCssExtractPlugin
스타일시트가 점점 많아지면 하나의 자바스크립트 결과물로 만드는 것이 부담일 수 있다. 번들 결과에서 스트일시트 코드만 뽑아서 별도의 CSS 파일로 만들어 역할에 따라 파일을 분리하는 것이 좋다. 브라우져에서 큰 파일 하나를 내려받는 것 보다, 여러 개의 작은 파일을 동시에 다운로드하는 것이 더 빠르다.
개발 환경에서는 CSS를 하나의 모듈로 처리해도 상관없지만 프로덕션 환경에서는 분리하는 것이 효과적이다. MiniCssExtractPlugin은 CSS를 별로 파일로 뽑아내는 플러그인이다.
설치
$ npm install -D mini-css-extract-plugin
webpack.config.js:
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
module.exports = {
plugins: [
...(process.env.NODE_ENV === "production"
? [new MiniCssExtractPlugin({ filename: `[name].css` })]
: []),
],
}
프로덕션 환경일 경우만 이 플러그인을 추가했다. filename에 설정한 값으로 아웃풋 경로에 CSS 파일이 생성될 것이다.
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
process.env.NODE_ENV === "production"
? MiniCssExtractPlugin.loader // 프로덕션 환경
: "style-loader", // 개발 환경
"css-loader",
],
},
],
},
}
플러그인에서 제공하는 MiniCssExtractPlugin.loader 로더를 추가한다.
NODE_ENV=production npm run build로 결과를 확인해보자.
dist/main.css가 생성되었고 index.html에 이 파일을 로딩하는 코드가 추가되었다.