이전까지 작성했던 코드로 build 를 실행하면, webpack에서 asset 사이즈가 크다는 warning을 띄운다. 이미지 사이즈가 크면, 앱이 느려질 수 있기 때문에 이를 해결해 보자.
앱에 이미지를 임포트하는 방법에는 크게 html 파일에 삽입하거나, css에 삽입하거나 ts 파일에 넣는 방법이 있는데, 이 중 ts 파일에서 임포트를 하게 되면,
ERROR in ./images/check.svg 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
관련 loader가 없다는 에러가 뜨게 된다
webpack 5 에서 기본적으로 제공하는 asset을 이용하여 ts파일에 이미지를 직접 임포트 해 보자
common.config.ts 에서
// webpack.common.config.ts
import path from "path";
import { Configuration } from "webpack";
import HtmlWebpackPlugin from "html-webpack-plugin";
import { CleanWebpackPlugin } from "clean-webpack-plugin";
const commonConfig: Configuration = {
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "../dist"),
filename: "main.js",
},
resolve: {
extensions: [".ts", ".tsx", ".js"],
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: "ts-loader",
},
{
test: /\.html$/,
loader: "html-loader",
},
{
test: /\.(png|jpg|svg)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 10kb 이상일 때만 파일 생성 10kb 이하일 때는 번들링된 자바스크립트 파일에 inline으로 삽입된다
},
},
generator: {
filename: "./images/[name][ext]", // 생성된 파일 이름과 확장자를 그대로 사용하겠다는 뜻, 여기서도 [name].[contenthash:12][ext] 등으로 hash를 사용할 수 있다.
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "src/index.html",
filename: "index.html",
}),
new CleanWebpackPlugin(),
],
};
export default commonConfig;
rules 에서 작성해 주면 된다
image minimizer webpack plugin과 imagemin 을 이용해서 image minify를 해 보자
패키지 설치
yarn add -D image-minimizer-webpack-plugin imagemin
imagemin 플러그인 설치
yarn add -D imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo
lossless 옵션을 사용하려면,
yarn add -D imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo
를 사용해 주면 된다.
여기서는 lossy 옵션을 사용할 예정이므로, 전자의 패키지를 설치한 후 진행할 것이다
prod.config 에서
// webpack.prod.config.ts
import MiniCssExtractPlugin from "mini-css-extract-plugin";
import { Configuration } from "webpack";
import commonConfig from "./webpack.common.config";
import { merge } from "webpack-merge";
import CssMinimizerPlugin from "css-minimizer-webpack-plugin";
import ImageMinimizerPlugin from "image-minimizer-webpack-plugin";
const prodConfig: Configuration = merge(commonConfig, {
mode: "production",
output: {
filename: "js/[name].[contenthash:12].js",
},
optimization: {
minimize: true,
minimizer: [
`...`,
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
"default",
{
discardComments: { removeAll: true },
},
],
},
}),
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
[
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-gifsicle",
"imagemin-svgo",
],
],
},
},
}),
],
},
module: {
rules: [
{
test: /\.(scss|sass)$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash:12].css",
}),
],
});
export default prodConfig;
optimization property에서 작성해 주면 된다.
ls -lah dist/images
// 이전
total 3560
drwxr-xr-x 3 joepasss staff 96B 10 8 15:50 .
drwxr-xr-x 6 joepasss staff 192B 10 8 15:50 ..
-rw-r--r-- 1 joepasss staff 1.7M 10 8 15:50 header-image.jpg
// 이후
total 384
drwxr-xr-x 3 joepasss staff 96B 10 8 15:51 .
drwxr-xr-x 6 joepasss staff 192B 10 8 15:51 ..
-rw-r--r-- 1 joepasss staff 188K 10 8 15:51 header-image.jpg
파일 사이즈가 1.7M에서 188K로 줄어든 모습을 볼 수 있다.