하루에 한 문제

웹팩 로더 본문

Dev/JavaScript

웹팩 로더

dkwjdi 2021. 4. 27. 12:20

웹팩은 모든 파일을 모듈로 바라본다. 자바스크립트로 만든 모듈 뿐만아니라 스타일시트, 이미지, 폰트까지 전부 모듈로 보기 때문에 import 구문을 사용하면 자바스크립트 코드 안으로 가져올수 있다.

 

이것이 가능한 이유는 웹팩의 로더 덕분이다. 로더는 타입스크립트 같은 다른 언어를 자바스크립트 문법으로 변환해주거나 이미지를 data URL 형식의 문자열로 변환한다. 뿐만 아니라 CSS파일을 자바스크립트에서 직접 로딩할 수 있도록 해준다.

 

커스텀 로더 만들어보기

로더를 사요하기 전 동작원리를 이해하기 위해 로더를 직접 만들어 보자.

 

my-webpack-loader.js

module.exports = function myloader(content) {
  console.log("로더 동작")
  return content
}
  • 함수로 만들수 있는데 로더가 읽은 파일의 내용이 함수 인자 content로 전달된다.
  • 로더가 동작하는지 확인하는 용도로 로그만 찍고 곧장 content를 돌려 준다.
  • 로더를 사용하려면 웹팩 설정파일의 module 객체에 추가한다.

 

webpack.config.js

const path = require("path")

module.exports = {
  mode: "development",
  entry: {
    main: "./src/app.js",
  },
  output: {
    path: path.resolve("./dist"),
    filename: "[name].js",
  },
  module: {
    rules: [
      {
        test: /\.js$/, //로더가 처리해야할 파일들의패턴 (정규표현식)
        use: [
          path.resolve('./my-webpack-loader.js') //로더파일을 적용
        ]
      }
    ]
  }
}
  • module.rules 배열에 모듈을 추가하는데 test와 use로 구성된 객체를 전달한다.
  • test에는 로딩에 적용할 파일을 지정한다. 파일명 뿐만아니라 파일 패턴을 정규표현식으로 지정할수 있는데 위 코드는 .js 확장자를 갖는 모든 파일을 처리하겠다는 의미다.
  • use에는 이 패턴에 해당하는 파일에 적용할 로더를 설정하는 부분이다.
  • 방금 만든 myloader 함수의 경로를 지정한다.

이제 npm run build로 웹팩을 실행해 보자.

  • 터미널에 '로더 동작' 문자열이 찍힌다. myloader() 함수가 동작한 것이다.
  • 빌드결과를 살펴보면 이전과 동일하다. 로더가 뭔가를 처리하기 위해서 간단한 변환 작업을 추가해 보자.
  • 소스에 있는 모든 console.log() 함수를 alert() 함수로 변경하도록 말이다.

 

my-webpack-loader.js

module.exports = function myWebpackLoader(content) {
    return content.replace('console.log(', 'alert(');
};

실행을 하게 되면 콘솔에 찍히던 3이라느 숫자가 alert창에 찍힌다.

 

 

자주 사용하는 로더

 

1. css-loader

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

 

app.js

import "./style.css"

 

style.css

body {
 background-color : green;
}
  • CSS 파일을 자바스크립트에서 불러와 사용하려면 CSS를 모듈로 변환하는 작업이 필요하다.
  • 바로 css-loader가 우리 코드에서 CSS 파일을 모듈처럼 불러와 사용할 수 있게 만들어준다.

 

우선 이렇게 하고 npm run build를 통해 실행해보자.

아마 위와 같은 오류가 뜰것이다.

웹팩이 app.css를 읽다가 ??모르겠는데?? 하고 오류를 낸것이다.

웹팩이 css파일을 모듈로 가져오기 위해서는 로더가 필요하다!

 

우선 로더를 설치해보자.

npm install -D css-loader

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

 module: {
    rules: [
      {
        test: /\.css$/, //로더가 처리해야할 파일의 패턴(정규표현식)
        use: [
          'css-loader'
        ]
      }
    ]
  }

자 이제 다시 npm run build를 통해 실행해보자! 아마 오류없이 실행이 될것이다.

그런데 이렇게 모듈로 css를 모듈로 불러오면 html에서는 어떻게 뜨게될까?

실행해봤다면 알겠지만 background-color 가 적용이 안된다.... 크롬에서 F12를 통해 확인해보면

body에 css가 들어가지 않았다!

 

 

2.style-loader

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

자바스크립트에만 코드가 있기 때문에 브라우저에 나오지 않는 것이다.... 이때 사용가능한것이 style-loader이다

자바스크립트로 변경된 스타일 코드를 html에 넣어주는 로더이다!

 

먼저 설치를 해보자

npm install -D style-loader

 

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

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"], // style-loader를 앞에 추가한다
      },
    ],
  },
}

 

 

그 후 html을 보면 body가 잘 들어간 것을 확인할 수 있다!

배열로 설정하면 뒤에서부터 앞으로 순서대로 로더가 동작한다.

위 설정은 모든 .css 확장자로 끝나는 모듈을 읽어 들여 css-loader를 적용하고 그 다음 style-loader를 적용한다.

 

3. file-loader

CSS 뿐만 아니라 소스코드에서 사용하는 모든 파일을 모듈로 사용하게끔 할 수 있다.

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

 

style.css

body {
  background-image: url(bg.png);
}
  • 배경 이미지를 bg.png 파일로 지정했다.
  • 웹팩은 엔트리 포인트인 app.js가 로딩하는 style.css 파일을 읽을 것이다.
  • 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'로 변경하여 사용할 것이다.

 

npm run build를 실행하고 dist 폴더로 가보면 위의 설정되로 bg.png가 있는 것을 확인할 수 있다.

 

4. url-loader

사용하는 이미지 갯수가 많다면 네트웍 리소스를 사용하는 부담이 있고 사이트 성능에 영향을 줄 수도 있다. 만약 한 페이지에서 작은 이미지를 여러 개 사용한다면 Data URI Scheme 이용하는 방법이 더 나은 경우도 있다. 이미지를 Base64로 인코딩하여 문자열 형태로 소스코드에 넣는 형식이다.

아래와 같은 형태로 경로를 넣는것이 아니고 문자열로 바꾼 이미지를 직접 넣어준다.

 

먼저 로더를 설치한다.

npm install -D url-loader

그리고 웹팩 설정을 추가한다. 

{
  test: /\.png$/,
  use: {
    loader: 'url-loader', // url 로더를 설정한다
    options: {
      publicPath: './dist/', // file-loader와 동일
      name: '[name].[ext]?[hash]', // file-loader와 동일
      limit: 20000 // 20kb 미만 파일만 data url로 처리
    }
  }
}
  • file-loader와 옵션 설정이 거의 비슷하고 마지막 limit 속성만 추가했다.
  • 모듈로 사용한 파일중 크기가 20kb 미만인 파일만 url-loader를 적용하는 설정이다.
  • 만약 이보다 크면 file-loader가 처리한다.
  • 빌드 결과를 보면 small.png 파일이 문자열로 변경되어 있는 것을 확인 할 수 있다.
  • 반면 20kb 이상인 bg.png는 여전히 파일로 존재한다.

 

기존의 dist폴더를 확인해보면 nyancat이라는 폴더가 있었지만

dist폴더를 삭제한 뒤 다시 npm run build를 실행하면 파일의 크기가 20kb미만인 nyancat.jpg는 dataurl형식으로 변경되었기 때문에 파일안에 없는 것을 확인할 수 있다.

html에서 확인해보면 아래처럼 나온다!

 

 

참고

jeonghwan-kim.github.io/js/2017/05/22/webpack-file-loader.html

jeonghwan-kim.github.io/series/2019/12/10/frontend-dev-env-webpack-basic.html#4-%EC%9E%90%EC%A3%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EB%A1%9C%EB%8D%94

 

'Dev > JavaScript' 카테고리의 다른 글

바벨 (babel)  (1) 2021.04.28
웹팩 플러그인  (0) 2021.04.27
프론트엔드 개발에 Node.js가 필요한 이유  (1) 2021.04.26
자바스크립트 런타임 : 콜스택과 메모리 힙  (0) 2021.04.20
V8 작동원리  (0) 2021.04.20
Comments