본문으로 바로가기
mark-lab

웹팩 로더

03.웹팩 로더

3.로더

3.1 로더의 역할

웹팩이 js, png, sass, cjs 등 모두 모듈로 본다라고 했다. 이런것들 자바스크립트에서 모두 import해서 개발할수 있게끔 제공해준다. 이런 환경을 제공해주는 역할이 웹팩의 로더가 하는 역할이다.

=> 로더는 각 파일들을 모듈로 개발할 수 있게 지원해주는 역할을 한다.

3.2 커스텀 로더 만들어서 동작 이해하기

로더도 nodejs에서 동작하기에 module.export로 만든다.

module.exports = function myloader(content) {
  console.log('myloader가 동작함')
  return content
}

로더를 사용하기 위해 설정

module: {
    rules: [
      {
        test: /\.js$/, // .js 확장자로 끝나는 모든 파일
        use: [path.resolve("./myloader.js")], // 방금 만든 로더를 적용한다
      },
    ],
  },

module.rules 배열에 모듈을 추가하는데 test와 use로 구성된 객체를 전달한다.

test에는 로딩에 적용할 파일을 지정한다. 파일명 뿐만아니라 파일 패턴을 정규표현식으로 지정할수 있는데 위 코드는 .js 확장자를 갖는 모든 파일을 처리하겠다는 의미다.

use에는 이 패턴에 해당하는 파일에 적용할 로더를 설정하는 부분이다. 방금 만든 myloader 함수의 경로를 지정한다.

로더를 실행하면 콘솔에 myloader가 동작함 이라는 메세지가 두번 찍힌다.

로더는 각 파일별로 작동을 한다. js 확장자로 끝나는 모든 파일에 적용되기 때문에 app.js, math.js 모두 동작하였기에 2번 찍히게 된다.

4. 자주 사용하는 로더

로더의 동작 원리를 보았으니 자주 사용하는 로더를 소개하자!

4.1 css-loader 웹팩은 모든것을 모듈로 바라보기 때문에 자바스크립트 뿐만 아니라 스타일시트로 import 구문으로 불러 올수 있다.

//app.js
import './style.css'
body {
  background-color: green;
}

CSS 파일을 자바스크립트에서 불러와 사용하려면 CSS를 모듈로 변환하는 작업이 필요하다. css-loader가 그러한 역할을 하는데 우리 코드에서 CSS 파일을 모듈처럼 불러와 사용할 수 있게끔 해준다.

먼저 로더를 설치 하자.

$ npm install -D css-loader

웹팩 설정에 로더를 추가한다.

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/, // .css 확장자로 끝나는 모든 파일
        use: ['css-loader'], // css-loader를 적용한다
      },
    ],
  },
}

웹팩은 엔트리 포인트부터 시작해서 모듈을 검색하다가 CSS 파일을 찾으면 css-loader로 처리할 것이다. use.loader에 로더 경로를 설정하는 대신 배열에 로더 이름을 문자열로 전달해도 된다.

빌드 한 결과 CSS코드가 자바스크립트로 변환된 것을 확인할 수 있다.

=> css가 렌더링 되진 않아 HTML코드가 브라우저 렌더링 되는 과정을 보면 HTML코드가 파싱이되어 DOM으로 만들어진다. CSS코드도 마찬가지이다. CSS코드를 파싱해서 CSSOM(Tree)로 만들어야 한다. 브라우저는 DOM과 CSSOM을 통해 렌더트리를 만들고 화면에 렌더링을 한다.

하지만 현재 자바스크립트에 있는 CSS코드가 브라우저에 의해서 파싱되지 않은 상태이다.

이를 렌더링 하기 위해 style-loader가 있다.

4.2 style-loader

모듈로 변경된 스타일 시트는 돔에 추가되어야만 브라우져가 해석할 수 있다. css-loader로 처리하면 자바스크립트 코드로만 변경되었을 뿐 돔에 적용되지 않았기 때문에 스트일이 적용되지 않았다.

style-loader는 자바스크립트로 변경된 스타일을 동적으로 돔에 추가하는 로더이다. CSS를 번들링하기 위해서는 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를 적용한다.

4.3 file-loader

CSS 뿐만 아니라 소스코드에서 사용하는 모든 파일을 모듈로 사용하게끔 할 수 있다. 파일을 모듈 형태로 지원하고 웹팩 아웃풋에 파일을 옮겨주는 것이 file-loader가 하는 일이다. 가령 CSS에서 url() 함수에 이미지 파일 경로를 지정할 수 있는데 웹팩은 file-loader를 이용해서 이 파일을 처리한다.

//style.css:
 
body {
  background-image: url(bg.png);
}

배경 이미지를 bg.png 파일로 지정했다.

웹팩은 엔트리 포인트인 app.js가 로딩하는 style.css 파일을 읽을 것이다. 그리고 이 스타일시트는 url() 함수로 bg.png를 사용하는데 이때 로더를 동작시킨다.

//webpack.config.js:
 
module.exports = {
  module: {
    rules: [
      {
        test: /\.png$/, // .png 확장자로 마치는 모든 파일
        loader: 'file-loader', // 파일 로더를 적용한다
      },
    ],
  },
}

웹팩이 .png 파일을 발견하면 file-loader를 실행할 것이다. 로더가 동작하고 나면 아웃풋에 설정한 경로로 이미지 파일을 복사된다. 아래 그림처럼 파일명이 해쉬코드로 변경 되었다. 캐쉬 갱신을 위한 처리로 보인다.

웹팩 번들 결과 웹팩 번들 결과 하지만 이대로 index.html 파일을 브라우져에 로딩하면 이미지를 제대로 로딩하지 못할 것이다. 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가 처리하는 파일을 모듈로 사용할 때 경로 앞에 추가되는 문자열이다. output에 설정한 'dist' 폴더에 이미지 파일을 옮길 것이므로 publicPath 값을 이것으로로 지정했다. 파일을 사용하는 측에서는 'bg.png'를 'dist/bg.png'로 변경하여 사용할 것이다.

또한 name 옵션을 사용했는데 이것은 로더가 파일을 아웃풋에 복사할때 사용하는 파일 이름이다. 기본적으로 설정된 해쉬값을 쿼리스트링으로 옮겨서 'bg.png?6453a9c65953c5c28aa2130dd437bbde' 형식으로 파일을 요청하도록 변경했다.

=> file-loader를 하기 전에 css-loader에서 background에 url을 셋팅햇으나 바로 적용이 됬다. 버전이 변경되면서 추가되었나?

4.4 url-loader

사용하는 이미지 갯수가 많다면 네트웍 리소스를 사용하는 부담이 있고 사이트 성능에 영향을 줄 수도 있다. 만약 한 페이지에서 작은 이미지를 여러 개 사용한다면 Data URI Scheme을 이용하는 방법이 더 나은 경우도 있다. 이미지를 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로 처리
    }
  }
}

file-loader와 옵션 설정이 거의 비슷하고 마지막 limit 속성만 추가했다. 모듈로 사용한 파일중 크기가 5kb 미만인 파일만 url-loader를 적용하는 설정이다. 만약 이보다 크면 file-loader가 처리하는데 옵션 중 fallback 기본값이 file-loader이기 때문이다.

빌드 결과를 보면 small.png 파일이 문자열로 변경되어 있는 것을 확인 할 수 있다. 반면 5kb 이상인 bg.png는 여전히 파일로 존재한다.

브라우저에서도 확인하면 스타일스트에 small.png가 Data url형태로 변환되어 있다.

아이콘처럼 용량이 작거나 사용 빈도가 높은 이미지는 파일을 그대로 사용하기 보다는 Data URI Scheeme을 적용하기 위해 url-loader를 사용하면 좋겠다.