웹팩 도큐먼트
여기서 imagemin 만 추가해서 사용할 예정이다.
웹팩이 이미지를 로딩할 수 없기 때문에 webpack asset 을 먼저 작성
{
test: /\.(png|jpg|svg)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 1024,
},
},
generator: {
filename: "images/[name].[contenthash:12][ext]",
},
},
bun run build
를 해 주면, 오류 없이 번들링이 잘 되는 모습을 볼 수 있다.
이제 이미지 사이즈를 줄이기 위헤 관련 패키지 설치 (image-minimizer-webpack-plugin, imagemin)
bun add -D image-minimizer-webpack-plugin imagemin
lossy option 을 사용할 예정이므로
bun add -D imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo
도큐먼트에 작성된 코드를 거의 그대로 배껴서 작성
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
// Lossless optimization with custom option
// Feel free to experiment with options for better result for you
plugins: [
["gifsicle"],
["mozjpeg"],
["pngquant"],
// Svgo configuration here https://github.com/svg/svgo#configuration
[
"svgo",
{
plugins: [
{
name: "preset-default",
params: {
overrides: {
removeViewBox: false,
addAttributesToSVGElement: {
params: {
attributes: [
{ xmlns: "http://www.w3.org/2000/svg" },
],
},
},
},
},
},
],
},
],
],
},
},
}),
bun run build
ERROR in Error with 'images/header-image.5b361a0f2927.jpg': Command failed with ENOENT: node_modules/mozjpeg/vendor/cjpeg
spawn node_modules/mozjpeg/vendor/cjpeg ENOENT
ERROR in Error: Child compilation failed:
Module Error (from ./node_modules/image-minimizer-webpack-plugin/dist/loader.js):
Error with 'images/header-image.jpg': Command failed with ENOENT: node_modules/mozjpeg/vendor/cjpeg
spawn node_modules/mozjpeg/vendor/cjpeg ENOENT
ModuleError: Module Error (from ./node_modules/image-minimizer-webpack-plugin /dist/loader.js):
Error with '/images/header-image.jpg': Command failed with ENOENT: node_modules/mozjpeg/vendor/cjpeg
spawn node_modules/mozjpeg/vendor/cjpeg ENOENT
at Object.emitError (node_modules/webpac k/lib/NormalModule.js:614:6)
at Object.loader (node_modules/image-min imizer-webpack-plugin/dist/loader.js:161:12)
at process.processTicksAndRejections (node:internal/process/task_queues:9 5:5)
Error with 'images/header-image.5b361a0f2927.jpg': Command failed with ENOENT : node_modules/mozjpeg/vendor/cjpeg
spawn node_modules/mozjpeg/vendor/cjpeg ENOE NT
Error: Error with 'images/header-image.5b361a0f2927.jpg': Command failed with ENOENT: node_modules/mozjpeg/vendor/cjpeg
spawn node_modules/mozjpeg/vendor/cjpeg ENOE NT
at Object.imageminMinify [as implementation] (node_modules/image-minimizer-webpack-plugin/dist/utils.js:575:22)
at process.processTicksAndRejections (node:internal/process/task_queues:9 5:5)
at async worker (node_modules/image-minimizer-webpack-plugin/dist/worker.js:77:25)
at async node_modules/image-minimizer-webpack-plugin/dist/index.js:327:18
- NormalModule.js:614 Object.emitError
[webpack]/[webpack]/lib/NormalModule.js:614:6
- loader.js:161 Object.loader
[webpack]/[image-minimizer-webpack-plugin]/dist/loader.js:161:12
- task_queues:95 process.processTicksAndRejections
node:internal/process/task_queues:95:5
- Error with 'images/header-image.5b361a0f2927.jpg': Command failed with ENOE NT: node_modules/mozjpeg/vendor/cjpeg
- spawn node_modules/mozjpeg/vendor/cjpeg ENOENT
- Error: Error with 'images/header-image.5b361a0f2927.jpg': Command failed with ENOENT: /node_modules/mozjpeg/vendor/cjpeg
- spawn node_modules/mozjpeg/vendor/cjpeg ENOENT
- utils.js:575 Object.imageminMinify [as implementation]
[webpack]/[image-minimizer-webpack-plugin]/dist/utils.js:575:22
- task_queues:95 process.processTicksAndRejections
node:internal/process/task_queues:95:5
- worker.js:77 async worker
[webpack]/[image-minimizer-webpack-plugin]/dist/worker.js:77:25
- index.js:327
[webpack]/[image-minimizer-webpack-plugin]/dist/index.js:327:18
- child-compiler.js:169
[webpack]/[html-webpack-plugin]/lib/child-compiler.js:169:18
- Compiler.js:551 finalCallback
[webpack]/[webpack]/lib/Compiler.js:551:5
- Compiler.js:577
[webpack]/[webpack]/lib/Compiler.js:577:11
- Compiler.js:1200
[webpack]/[webpack]/lib/Compiler.js:1200:17
- Hook.js:18 Hook.CALL_ASYNC_DELEGATE [as _callAsync]
[webpack]/[tapable]/lib/Hook.js:18:14
- Compiler.js:1196
[webpack]/[webpack]/lib/Compiler.js:1196:33
- Compilation.js:2795 finalCallback
[webpack]/[webpack]/lib/Compilation.js:2795:11
- Compilation.js:3100
[webpack]/[webpack]/lib/Compilation.js:3100:11
- Hook.js:18 Hook.CALL_ASYNC_DELEGATE [as _callAsync]
[webpack]/[tapable]/lib/Hook.js:18:14
- Compilation.js:3093
[webpack]/[webpack]/lib/Compilation.js:3093:38
- task_queues:95 process.processTicksAndRejections
node:internal/process/task_queues:95:5
2 ERRORS in child compilations (Use 'stats.children: true' resp. '--stats-children' for more details)
webpack 5.88.2 compiled with 4 errors in 1174 ms
error: script "build" exited with code 1 (SIGHUP)
mozjpeg/vender/cjpeg 가 없다는 오류를 낸다 (ENOENT)
지금 상황에서는 ImageMinimizerPlugin이 문제가 되는지, imagemin이 문제가 되는지, mozjpeg가 문제가 되는지 모르기 때문에, root에 imagemin만 실행 가능하게 해서 ImageMinimizerPlugin을 배제 한 뒤에 오류 트래킹을 할 예정이다.
파일 생성
touch imageMinimizer.ts
이번에도 imagemin을 사용할 예정이므로, imagemin readme을 참고한다.
import imagemin from 'imagemin';
import imageminJpegtran from 'imagemin-jpegtran';
import imageminPngquant from 'imagemin-pngquant';
const files = await imagemin(['images/*.{jpg,png}'], {
destination: 'build/images',
plugins: [
imageminJpegtran(),
imageminPngquant({
quality: [0.6, 0.8]
})
]
});
console.log(files);
패키지 설치
bun add -D @types/imagemin imagemin-jpegtran @types/imagemin-jpegtran imagemin-pngquant @types/imagemin-pngquant
현재 images 폴더가 있으므로, 바로 bun imageMinimizer.ts
를 실행 해 주면,
TypeError: Error occurred when handling file: images/*.{jpg,png}
TypeError: Executable not found in $PATH: "node_modules/jpegtran-bin/vendor/jpegtran"
at spawn (native)
at spawn (node:child_process:610:8)
at <anonymous> (node:child_process:2:21)
at <anonymous> (/Users/joepasss/joepasss/webpack/node_modules/exec-buffer/node_modules/execa/index.js:139:3)
at <anonymous> (/Users/joepasss/joepasss/webpack/node_modules/exec-buffer/index.js:37:44)
at processTicksAndRejections (:55:39)
code: "ERR_INVALID_ARG_TYPE"
at node:child_process:611:8
비슷하게 {특정 패키지}/vender/~ 가 뜨는데, 이게 imagemin 문제인지 확인하기 위해 plugins를 비워놓고 실행
import imagemin from "imagemin";
import imageminJpegtran from "imagemin-jpegtran";
import imageminPngquant from "imagemin-pngquant";
const files = await imagemin(["images/*.{jpg,png}"], {
destination: "build/images",
plugins: [],
});
console.log(files);
이후 bun imageMinimizer.ts
를 실행해 보면
[
{
data: Buffer(1341775) [ 255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 1, 0, 72, 0, 72, 0, 0, 255, 226, 12, 88, 73, 67, 67, 95, 80, 82, 79, 70, 73, 76, 69, 0, 1, 1, 0, 0, 12, 72, 76, 105, 110, 111, 2, 16, 0, 0, 109, 110, 116, 114, 82, 71, 66, 32, 88, 89, 90, 32, 7, 206, 0, 2, 0, 9, 0, 6, 0, 49, 0, 0, 97, 99, 115, 112, 77, 83, 70, 84, 0, 0, 0, 0, 73, 69, 67, 32, 115, 82, 71, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 214, 0, 1, 0, 0, 0, 0, 211, 45, 72, 80, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 99, 112, 114, 116, 0, 0, 1, 80, 0, 0, 0, 51, 100, 101, 115, 99, 0, 0, 1, 132, 0, 0, 0, 108, 119, 116, 112, 116, 0, 0, 1, 240, 0, 0, 0, 20, 98, 107, 112, 116, 0, 0, 2, 4, 0, 0, 0, 20, 114, 88, 89, 90, 0, 0, 2, 24, 0, 0, 0, 20, 103, 88, 89, 90, 0, 0, 2, 44, 0, 0, 0, 20, 98, 88, 89, 90, 0, 0, 2, 64, 0, 0, 0, 20, 100, 109, 110, 100, 0, 0, 2, 84, 0, 0, 0, 112, 100, 109, 100, 100, 0, 0, 2, 196, 0, 0, 0, 136, 118, 117, 101, 100, 0, 0, 3, 76, 0, 0, 0, 134, 118, 105, 101, 119, 0, 0, 3, 212, 0, 0, 0, 36, 108, 117, 109, 105, 0, 0, 3, 248, 0, 0, 0, 20, 109, 101, 97, 115, 0, 0, 4, 12, 0, 0, 0, 36, 116, 101, 99, 104, 0, 0, 4, 48, 0, 0, 0, 12, 114, 84, 82, 67, 0, 0, 4, 60, 0, 0, 8, 12, 103, 84, 82, 67, 0, 0, 4, 60, 0, 0, 8, 12, 98, 84, 82, 67, 0, 0, 4, 60, 0, 0, 8, 12, 116, 101, 120, 116, 0, 0, 0, 0, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 40, 99, 41, 32, 49, 57, 57, 56, 32, 72, 101, 119, 108, 101, 116, 116, 45, 80, 97, 99, 107, 97, 114, 100, 32, 67, 111, 109, 112, 97, 110, 121, 0, 0, 100, 101, 115, 99, 0, 0, 0, 0, 0, 0, 0, 18, 115, 82, 71, 66, 32, 73, 69, 67, 54, 49, 57, 54, 54, 45, 50, 46, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 115, 82, 71, 66, 32, 73, 69, 67, 54, 49, 57, 54, 54, 45, 50, 46, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 1341262 more ],
sourcePath: "images/header-image.jpg",
destinationPath: "build/images/header-image.jpg"
}, {
data: Buffer(404) [ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 50, 0, 0, 0, 50, 8, 6, 0, 0, 0, 30, 63, 136, 177, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 14, 195, 0, 0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 1, 41, 73, 68, 65, 84, 104, 67, 237, 217, 61, 10, 194, 64, 16, 134, 225, 120, 0, 91, 237, 245, 36, 30, 66, 143, 99, 105, 43, 158, 201, 51, 216, 122, 11, 59, 65, 103, 212, 15, 150, 16, 66, 118, 179, 59, 63, 50, 47, 124, 168, 169, 124, 208, 77, 147, 46, 138, 162, 232, 111, 90, 208, 142, 180, 245, 231, 147, 110, 123, 218, 238, 251, 54, 63, 70, 188, 104, 55, 154, 38, 230, 64, 123, 210, 30, 180, 45, 95, 200, 141, 191, 60, 35, 52, 49, 64, 240, 119, 56, 241, 133, 210, 52, 49, 213, 16, 72, 3, 83, 29, 129, 36, 49, 205, 16, 72, 2, 211, 28, 129, 90, 98, 196, 16, 168, 5, 70, 28, 129, 106, 98, 212, 16, 168, 6, 70, 29, 129, 230, 96, 204, 32, 80, 9, 198, 28, 2, 229, 96, 204, 34, 208, 20, 140, 121, 4, 26, 195, 184, 65, 160, 33, 140, 59, 4, 74, 49, 119, 154, 75, 4, 98, 12, 35, 24, 192, 187, 208, 92, 150, 254, 157, 120, 253, 51, 227, 162, 20, 113, 166, 245, 207, 140, 139, 134, 14, 118, 122, 102, 92, 96, 198, 238, 78, 110, 48, 83, 110, 177, 230, 49, 83, 16, 200, 44, 38, 7, 129, 204, 97, 74, 16, 200, 12, 102, 14, 2, 169, 99, 106, 32, 144, 26, 166, 38, 2, 137, 99, 90, 32, 144, 24, 166, 37, 2, 53, 199, 72, 32, 80, 51, 140, 36, 2, 85, 199, 104, 32, 80, 53, 140, 38, 2, 245, 49, 43, 90, 118, 252, 204, 142, 31, 119, 105, 33, 16, 48, 87, 218, 146, 47, 148, 180, 249, 189, 106, 199, 191, 68, 49, 34, 138, 162, 200, 90, 93, 247, 6, 139, 252, 198, 202, 131, 239, 188, 39, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 ],
sourcePath: "images/delete.png",
destinationPath: "build/images/delete.png"
}
]
잘 되는 걸 볼 수 있다.
plugin으로 implement 하든, 웹팩 밖에서 implement 하든 imagemin 플러그인이 node_module 상에서 특정 imagemin 플러그인의 vender 폴더가 비어있다고 오류가 나는데, 웹팩이나 imagemin의 오류가 아닌, bun이 패키지를 설치하는 방법이 npm 또는 yarn과 다르기 때문에 특정 파일이 설치되지 않았던 것 같다.
실제로 yarn으로 바꾸고 실행해 보니 잘 되는것을 보아 하니, bun.build를 직접 사용하는 것이 아니라 webpack, imagemin 등의 특정 npm package를 사용해 프로젝트를 빌드하는 것은 노드를 사용하는것에 비해 메리트가 떨어져보인다.
bun이 충분히 성숙하기 전 까지는 node + yarn 조합을 사용해야겠다