[Webpack] Output

함성준·2021년 7월 6일
0
post-thumbnail

Webpack - Output

웹팩 도큐먼트 내용을 요약하기 위한 문서입니다.

Output

웹팩 실행 결과 파일은 다중 엔트리를 설정해도 하나의 객체 옵션만 요구합니다. 그러나 이것은 조금더 생각할 필요가 있습니다. 이전 Entry 내용에서, 다중 엔트리를 통해 독립적인 의존성 그래프를 생성한다고 하였습니다. 같은 이름의 결과파일을 생성하도록 지시하면 하나의 실행결과 후에 나머지 실행결과가 결과 파일을 덮어 씌워버리는 일이 발생하겠죠. 웹팩은 이런 경우를 내부적으로 방지해주고 있습니다.

const path = require('path')
module.exports = {
    mode: 'development',
    entry: {
        depend: {
            import: path.resolve(__dirname, 'src/depend.js')
        },
        entryOne: {
            import: path.resolve(__dirname, 'src/entryOne.js'),
        },
        entryTwo: {
            import: path.resolve(__dirname, 'src/entryTwo.js')
        }   
    },
    output: {
        filename: 'bundle.js'
    }
}
# 같은 결과파일의 이름으로 다중 청크를 생성하고 있습니다.
$ webpack
[webpack-cli] Error: Conflict: Multiple chunks emit assets to the same filename bundle.js (chunks depend and entryOne)
    at /usr/local/lib/node_modules/webpack/lib/Compilation.js:3871:12
    at /usr/local/lib/node_modules/webpack/lib/Cache.js:91:34
    at Array.<anonymous> (/usr/local/lib/node_modules/webpack/lib/cache/MemoryCachePlugin.js:45:13)
    at /usr/local/lib/node_modules/webpack/lib/Cache.js:91:19
    at Hook.eval [as callAsync] (eval at create (/usr/local/lib/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:19:1)
    at Cache.get (/usr/local/lib/node_modules/webpack/lib/Cache.js:75:18)
    at ItemCacheFacade.get (/usr/local/lib/node_modules/webpack/lib/CacheFacade.js:117:15)
    at /usr/local/lib/node_modules/webpack/lib/Compilation.js:3817:22
    at arrayEach (/usr/local/lib/node_modules/webpack/node_modules/neo-async/async.js:2405:9)
    at Object.each (/usr/local/lib/node_modules/webpack/node_modules/neo-async/async.js:2846:9)

이런 이슈는 예약어(substitutions)를 통해 해결이 가능합니다. [name], [contenthash] 등등이 있는데 저는 이 두가지만을 사용해도 실무를 진행하는 상황에서 대응할 수 있다고 봅니다. 우선 [name] 예약어를 사용해보죠.

const path = require('path')
module.exports = {
    mode: 'development',
    entry: {
        depend: {
            import: path.resolve(__dirname, 'src/depend.js')
        },
        entryOne: {
            import: path.resolve(__dirname, 'src/entryOne.js'),
        },
        entryTwo: {
            import: path.resolve(__dirname, 'src/entryTwo.js')
        }   
    },
    output: {
        filename: '[name].bundle.js'
    }
}

결과는 이렇습니다.

$ tree ./dist
./dist
├── depend.bundle.js
├── entryOne.bundle.js
├── entryTwo.bundle.js
└── index.html

entry 필드에 입력한 키값들이 결과 파일 이름의 프리픽스 역할을 해주는군요. [contenthash] 는 무엇일까요? 해쉬의 특성을 이용하기 때문에 소스 내부에 조금만 수정이 발생해도 이 콘텐트 해쉬값은 변경이 일어나게 됩니다. 브라우저의 캐싱 정책으로 인해 업데이트 된 소스가 응답되어야 하는 상황인데 이전 프로덕트가 응답되는 경우를 방지하는데에 아주 유용합니다.

const path = require('path')
module.exports = {
    mode: 'development',
    entry: {
        depend: {
            import: path.resolve(__dirname, 'src/depend.js')
        },
        entryOne: {
            import: path.resolve(__dirname, 'src/entryOne.js'),
        },
        entryTwo: {
            import: path.resolve(__dirname, 'src/entryTwo.js')
        }   
    },
    output: {
        filename: '[name].[contenthash].js'
    }
}
$ tree ./dist
./dist
├── depend.062f106337bb14a35dbb.js
├── entryOne.886f73573e11d4a66472.js
├── entryTwo.67df96878d5620618799.js
└── index.html

좋네요. path 옵션을 통해 결과 파일이 생성될 경로도 자유롭게 지정할 수 있습니다.

    output: {
        filename: '[name].[contenthash].js',
        path: path.resolve(__dirname, 'foo')
    }
$ tree ./foo
./foo
├── depend.062f106337bb14a35dbb.js
├── entryOne.886f73573e11d4a66472.js
└── entryTwo.67df96878d5620618799.js
  • publicPath 옵션을 통해 이미지, 폰트와 같은 정적 에셋 파일이 제공될 기본 경로를 지정할 수 있습니다.

  • assetModuleFilename 옵션을 통해 Webpack 5 버전에 도입된 기능인 내부적 file-loader 가 파일을 어느곳에 위치시킬지, 네이밍은 어떻게 설정할지 결정할 수 있습니다.

    output: {
        filename: '[name].[contenthash].js',
        path: path.resolve(__dirname, 'dist'),
        publicPath: '/assets',
        assetModuleFilename: 'assets/[contenthash][ext]'
    },
    module: {
        rules: [
            {
                test: /\.(png|svg|jpg|jpeg|gif)$/i,
                type: 'asset/resource', // file-loader 를 통해 불러온 파일을 결과 디렉토리의 특정경로에 복사하여 생성하도록 지시합니다.
            },
        ]
    }
$ tree ./dist
./dist
├── assets
│   └── 8e36814b7c56efe8b9d3.png
├── depend.062f106337bb14a35dbb.js
├── entryOne.4804818f0e47b1cfff63.js
└── entryTwo.67df96878d5620618799.js

0개의 댓글