웹팩은 모든 파일을 모듈(module)로 바라보고 있다. 그렇기 때문에 import
구문을 통해 모든 파일들을 자바스크립트 코드안으로 가져올 수 있는 것이다.
그럼 과연 로더는 무엇일까?
로더는 타입스크립트 같은 다른 언어를 자바스크립트 문법으로 변환해 주거나 이미지를 data URL 형식의 문자열로 변환한다. 뿐만 아니라 CSS 파일을 자바스크립트에서 직접 로딩할 수 있도록 해준다.
로더의 동작원리를 이해하기 위해 로더를 직접 만들어보자.
my-webpack-loader.js:
module.exports = function myWebpackLoader(content) {
console.log('webpackloader 실행됨');
return content;
};
로더는 함수로 만들 수 있는데 로더가 읽은 파일의 내용이 함수 인자 content
로 전달된다.
로더를 사용하려면 웹팩 설정파일의 module
객체에 추가해야한다.
webpack.config.js:
module: {
rules: [{
test: /\.js$/, // .js 확장자로 끝나는 모든 파일
use: [path.resolve('./myloader.js')] // 방금 만든 로더를 적용한다
}],
}
test
프로퍼티에는 로딩에 적용할 파일들의 패턴을 명시해준다. 정규표현식으로 지정해준다.
use
에는 이 패턴에 해당하는 파일에 적용할 로더를 설정하는 부분이다.
npm run build
로 웹팩을 실행해보자.
현재 .js파일이 두개이기 때문에 'webpackloader 실행됨' 이라는 문자열이 두번 찍힌 것을 확인할 수 있다.
앞에서 로더를 사용하는 방법과 원리를 살펴보았다. 자주 사용하는 로더들을 알아보자.
웹팩은 모든 파일들을 모듈로 보기 때문에 css-loader를 사용하면 자바스크립트 뿐만 아니라 스타일시트도 import로 불러올 수 있다.
app.js:
import "./app.css";
app.css:
body{
background-color : green;
}
CSS파일을 자바스크립트에서 불러와 사용하려면 CSS를 모듈로 변환하는 작업이 필요하다.
$ npm install -D css-loader
webpack.config.js:
module.exports = {
module: {
rules: [
{
test: /\.css$/, // .css 확장자로 끝나는 모든 파일
use: ["css-loader"], // css-loader를 적용한다
},
],
},
}
빌드 된 결과를 보면 css코드가 자바스크립트로 변환된 것을 알 수 있다.
모듈로 변경된 스타일시트는 돔에 추가되어야만 브라우저가 해석할 수 있다.
css-loader로 처리하면 자바스크립트 코드로만 변경되었을 뿐 돔에 적용한 것은 아니기 때문에 아직 적용이 안된 것 처럼 보인다
$ npm install -D style-loader
그리고 웹팩 config에 로더를 추가한다.
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"], // style-loader를 앞에 추가한다
},
],
},
}
CSS 뿐만 아니라 소스코드에서 사용하는 모든 파일을 모듈로 사용하게 할 수 있다. 파일을 모듈 형태로 지원하고 웹팩 아웃풋에 파일을 옮겨주는 것이 file-loader
가 하는 일이다.
css에서 url() 함수에 이미지 파일 경로를 지정할 수 있는데 웹팩은 파일로더를 이용해서 이 파일을 처리한다
테스트를 해보자.
app.css:
body {
background-image: url(bg.png);
}
웹팩은 엔트리 포인트인 app.js
가 로딩하는 app.css
파일을 읽을 것이다. 그리고 이 스타일시트는 url() 함수로 bg.png
를 사용하는데 이때 로더를 동작시킨다.
webpack.config.js:
module.exports = {
module: {
rules: [
{
test: /\.png$/, // .png 확장자로 마치는 모든 파일
loader: "file-loader", // 파일 로더를 적용한다
},
],
},
}
브라우저를 확인해보자. 아직 하얀 화면만 나올 뿐이다.
이유는 무엇일까?
CSS를 로딩하면
background-image:url(bg.png)
코드에 의해 동일 폴더에서 이미지를 찾으려고 시도할 것이다. 그러나 웹팩으로 빌드한 이미지 파일은 output인 dist폴더 아래로 이동했기 때문에 이미지 로딩에 실패한 것이다
file-loader 옵션을 조정해주자.
module.exports = {
module: {
rules: [
{
test: /\.png$/, // .png 확장자로 마치는 모든 파일
loader: "file-loader",
options: {
publicPath: "./dist/", // prefix를 아웃풋 경로로 지정
name: "[name].[ext]?[hash]", // 파일명 형식
},
},
],
},
}
publicPath
는 file-loader가 처리하는 파일을 모듈로 사용할 때 경로 앞에 추가되는 문자열이다.
파일을 사용할 때는 dist/bg.png
로 실행될 것이다.
name
옵션은 로더가 파일을 아웃풋에 복사할 때 사용하는 파일 이름이다.
사용하는 이미지 갯수가 많다면 네트워크 리소스를 이용하는 것은 부담이 있고 성능에 영향을 줄 수도 있다.
한 페이지에서 작은 이미지를 여러개 사용한다면 Data URI Scheme을 이용하는 방법이 나은 경우도 있다.
이미지를 Base64로 인코딩하여 문자열 형태로 소스코드에 넣는 형식이다.
url-loader는 이러한 처리를 자동화해준다.
$ npm instll -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: 2000 // 2kb 미만 파일만 data url로 처리
}
}
}
file-loader
와 옵션 설정이 비슷하고 마지막 limit 속성만 추가했다. 모듈로 사용한 파일중 크기가 2kb 미만인 파일만 url-loader를 적용하는 설정이다.
만약 이보다 크면 file-loader가 처리하는데 옵션 중 fallback 기본값이 file-loader이기 때문이다.
브라우저에서 data uri로 처리되었음을 확인할 수 있다.
이 글은 김정환님 블로그를 토대로 작성되었습니다.