요즘 회사 코드에 있는 웹팩 동작 방식이 궁금해 웹팩을 공부하고 있다. 자주 사용하는 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'은 번들 파일의 크기를 작게 유지하고, 파일 로딩이 많이 발생하지 않는 경우에 유용하다.