DevOps/Webpack

webpack5 file-loader 동작 안함 (웹팩5 파일로더 안됨)

도잎 2023. 4. 13. 20:37
반응형

웹팩 버전 5, 파일로더 안되는 현상

 

요즘 회사 코드에 있는 웹팩 동작 방식이 궁금해 웹팩을 공부하고 있다. 자주 사용하는 loader를 먼저 하나씩 공부해보고 있었는데  css-loader, style-loader를 실행하는데까지는 문제가 없었다. 강의에서는 웹팩 4를 사용하고 있는데 나는 그래도 최근에 나온 것으로 해보고 싶어 5를 사용하며, 하나씩 맞춰나가는 중이다. 역시 강의대로 따라하니 file-loader와 url-loader가 적용이 안된다 ㅎ 

 

css 파일에 있는 백그라운드 이미지를 웹팩으로 빌드해서 index.html에 보여주는 구조였다. (app.css, app.js, index.html) 결과적으로 index.html에서 번들링 된 자바스크립트 파일을 불러오는데 그 안에 css가 포함되어있는 구조인 것이다.

 

// app.css

body {
  background-image: url(cherry.jpg);
}
// app.js

import "./app.css";

console.log('실행 확인');
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Webpack Template</title>
  </head>
  <body>
    <script src="dist/main.js"></script>
  </body>
</html>

 

이미지 빌드를 위해 file-loader를 깔았고, 강의해서 알려준대로 webpack.config.js 파일에 file-loader 규칙을 추가했다.

 

// 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")],
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.jpg$/,
        loader: "file-loader",
        options: {
          publicPath: "./dist/",
          name: "[name].[ext]?[hash]",
        },
      },
    ],
  },
};

 

 

이렇게 설정해한 후, 빌드를 하고 index.html을 실행시켜보면 파일 경로가 이상하다. 크롬 개발자도구에서 확인해보니 아래와 같이 나온다. 웹팩 file-loader를 사용하니 file:///C:/Users/choij/webpack부터 시작하는 경로로 설정이 되면서 인식이 안된다 ㅎ 그래서 이건 뭔가 webpack 버전의 문제일 것 같아 webpack 5에서 file-loader가 안되는 이유를 찾기 시작했다.

 

body {
    background-image: url(file:///C:/Users/choij/webpack/webpack-sample-code/webpack-sample/dist/1f52df4….jpg);
}

 

찾아보니 webpack 5부터는 file-loader와 url-loader 대신에 Asset Modules을 사용할 수 있다고한다. Asset Modules를 통해 사용할 수 있기 때문에 file-loader와 충돌이 일어나거나 제대로 지원이 안되는 것 같다. 그래서 Asset Modules를 사용하여 빌드해봤다.

 

const path = require("path");

module.exports = {
  // ... 생략
  module: {
    rules: [
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: "asset/resource",
      },
    ],
  },
};

 

간단하게 이렇게만 바꿔주니 빌드했을 때 index.html에 백드라운드 이미지가 아주 잘 나온다~ 웹팩 4와 5 사이에 많은 것이 바뀐 것 같은데 5버전에 맞춰 하나씩 해결해나가는 중이다. 강의 질문에 file-loader가 안된다는 질문도 많았던 것 같은데 웹팩 5버전을 사용하고 있다면 당연히 안되는거다. file-loader로 이미지 빌드가 안될때는 내가 어떤 버전을 쓰고 있는지부터 확인하자!

 

한가지 더 추가하자면 type: "asset/resource", type: "asset", 두가지를 사용해서 빌드할 수 있는데 리소스가 있냐 없냐에 따라 차이가 존재한다. type: 'asset'과 type: 'asset/resource'의 차이점은 파일 크기라고 하는데, 아래 내용을 참고해보면 좋을 것 같다. 결론적으로 asset은 작은 크기의 이미지 파일을 많이 사용하는 경우에 유리하고, asset/resource는 번들 파일 크기를 작게 유지하고, 파일 로딩이 많이 발생하지 않는 경우에 유용하다고 한다.

type: 'asset'은 파일 크기가 maxSize (기본값 8KB) 이하인 경우 Data URL로 인라인화하고, 이보다 큰 파일은 파일로 복사한다. 따라서 파일 크기가 작은 이미지 파일 등은 Data URL로 인라인화되어 번들 파일의 크기가 커지고, 파일 크기가 큰 이미지 파일 등은 파일로 복사되어 서버에서 따로 로딩되는 경우가 있다.

type: 'asset/resource'은 파일을 항상 파일로 복사한다. 따라서 번들 파일의 크기는 줄어들지만, 이미지 파일 등이 여러 번 사용되는 경우에는 서버에서 여러 번 로딩되는 문제가 있을 수 있다.

따라서 type: 'asset'은 작은 파일 크기의 이미지 파일을 많이 사용하거나, 번들 파일의 크기가 크게 상승하지 않는 경우에 유용하며, type: 'asset/resource'은 번들 파일의 크기를 작게 유지하고, 파일 로딩이 많이 발생하지 않는 경우에 유용하다.

 

반응형