Webpack 3 에서 Webpack 5 으로 바꾸기 위해 해야 할 일들
포트폴리오

Webpack 3 에서 Webpack 5 으로 바꾸기 위해 해야 할 일들

현재 티도리 프레임워크Webpack 3 를 기반으로 동작하고 있다. 최근 Webpack 5 로 업그레이드하는 작업을 진행하고 있는데, 그 와중에 당연히 시행착오도 여럿 발생하고 있어 내가 했던 삽질을 바탕으로 웹팩을 업그레이드하기 위해 겪어야 할 과정을 공유하고자 한다. 본론으로 가기 전에 먼저 이야기 하자면, 꼭 필요한게 아니라면 웹팩 업그레이드는 권장하지 않는다. 번거로운 일이 한 두개가 아니다. 게다가 둘은 Webpack 4 보다도 큰 차이를 보이고 있어 주의가 필요하다.

 

글을 쓰기전에 먼저 결론부터 말하자면 Webpack 3 을 Webpack 5 로 업그레이드할 때 중요한 것은 다음과 같다.

  • Webpack, Webpack Dev Server 의 변경된 CLI 사용법 숙지
  • 설정 파일의 새로 추가되거나 삭제된 옵션 점검
  • 설치되었거나 작성한 플러그인, 로더를 웹팩의 버전에 맞추기

무작정 웹팩을 최신버전으로

Webpack 3

 

먼저 Webpack 3 버전의 package.json 의 상태는 다음과 같다. webpack3.x 버전이고 webpack-dev-server2.x 버전을 사용중이었다. 개발서버에 대해 Webpack Dev Server 를 사용했으니 둘 다 필요하다.

{
    "webpack": "^3.11.0",
    "webpack-dev-server": "^2.11.1"
}

이를 실행할 때는 다음과 같이 처리되었었다.

const webpackDevServer = require.resolve('webpack-dev-server/bin/webpack-dev-server')
const webpackDevConfig = path.join(__dirname, '../config/webpack.dev.conf')

/**
 * -> tidory start
 */
tidory
  .command('start')
  .description('Start development server')
  .action(() => {
    shelljs.exec(`node ${webpackDevServer} --config ${webpackDevConfig} --env.development`)
  })

Webpack 5

 

그 다음 Webpack 의 버전을 다음과 같이 무작정 갱신하였다.

{
    "webpack": "^5.37.1",
    "webpack-dev-server": "^3.11.2"
}

이렇게 바꾸고 실행하고 나면 당연히 에러가 난다. Webpack 5 에서는 웹팩 바이너리를 실행할 때 바로 실행할 수 없다는 문구가 나올 것인데, 새로설치한 Webpack 5 의 바이너리를 CLI 에서 실행하려 들면 webpack-cli 의 설치가 필요하다는 사실을 알려줄 것이다.

{
    "webpack-cli": "^4.7.0",
}

또한 Webpack Dev Server 가 이전에는 webpack-dev-server 의 바이너리를 직접 실행하여 할 수 있었지만 Webpack 5 에서는 Webpack 바이너리에 serve 커맨드를 사용하여 처리할 수 있다.

const webpack = require.resolve('webpack/bin/webpack')
const webpackDevConfig = path.join(__dirname, '../config/webpack.dev.conf')

/**
 * -> tidory start
 */
tidory
  .command('start')
  .description('Start development server')
  .action(() => {
    shelljs.exec(`node ${webpack} serve --config ${webpackDevConfig} --env development`)
  })

웹팩 설정 파일 속성 점검

Webpack 3 와 Webpack 5 의 설정에는 일부 차이가 있다. mode, optimization 등의 속성이 이전에는 없었지만 Webpack 5 에는 존재한다. 여타 프레임워크에는 빌드와 개발모드가 별도로 파일로 존재하기 때문에 mode 를 추가해주기로 하자.

module.exports = async env => {
  return merge(await webpackBaseConfig(env), {
    mode: 'development' // 'mode' 는 Wepbpack 3 에는 없는 옵션이다.
  })
}

여기서 중요한 것은 Webpack 5 에서 설정 파일의 옵션이 새로 추가되었거나 삭제된 속성이 있다면 그에 맞춰 설정파일 변경을 적용시켜주어야 한다는 점이다.

로더, 플러그인의 웹팩 지원 버전 맞추기

이 과정이 가장 오래걸린다. 웹팩의 업그레이드가 어려운 이유는 로더, 플러그인의 웹팩 버전에 대한 의존도가 높기 때문이다. Webpack 3 와 Webpack 5 는 플러그인 작성법이 다르다. 따라서 사용하고 있는 플러그인의 웹팩 지원버전 체크가 필요하다. 예를 들어 https://github.com/jantimon/html-webpack-plugin 을 사용한다면 버전에 따라 웹팩 지원이 다르다. Webpack 3 를 사용할 때는 ^3.2.0 버전을 사용했지만 Webpack 5 로 왔을 때는 그에 맞춰 상승한 버전인 ^5.3.1 버전을 사용한다.

플러그인 문서에 들어가 버전에 따라 사용방법이나 옵션에 변화가 있는 것도 적용시켜주어야 한다.

별도로 작성된 플러그인을 사용하고 있을 때도 작성방법을 달리해주어야 한다. 그 외에 로더나 훅 등의 변경사항이 있을 경우 갱신이 필요하다. 예를 들어 임의로 작성한 TidoryWebpackPlugin 의 작성방법은 다음과 같이 차이가 난다.

 

Webpack 3

module.exports = class {
  /**
   * Apply plugin
   *
   * @param {object} compiler
   */
  apply (compiler) {
    compiler.plugin('compilation', compilation => {
      compilation.plugin('html-webpack-plugin-after-html-processing', async (htmlPluginData, callback) => {
        callback(null, htmlPluginData)
      })
    })
    compiler.plugin('done', () => {})
  }
}

Webpack 5

module.exports = class {
  /**
   * Apply plugin
   *
   * @param {object} compiler
   */
  apply (compiler) {
    compiler.hooks.compilation.tap('TidoryWebpackPlugin', compilation => {
      HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync('TidoryWebpackPlugin', async (data, callback) => {
        callback(null, data)
      })
    })
    compiler.hooks.done.tap('TidoryWebpackPlugin', stats => {})
  }
}

간단하게는 로더와 플러그인에 대해 몽땅 최신버전을 다운받아 버리면 그만이긴 한데, 달라진 옵션과 사용법을 파악하고 기존과 동일하게, 혹은 더 나아진 방법으로 실행되게 하려면 이 또한 많은 시행착오가 필요하다.

babel-core, @babel/core

둘은 무슨 차이일까? 스택오버플로우에 따르면 Babel 7 부터는 @babel/core 를 사용하라고 한다. 하지만 나는 기존에 babel-core 를 사용했는데, 만약 위와 같은 사실을 인지하지 못하면 단순히 버전만 갱신한다고 해서 처리되지 않는다. babel-core, @babel/core 는 적용가능한 웹팩의 버전이 다르다. 이렇게 플러그인 및 로더의 체계가 달라지는 경우에는 새로 찾아야 하는 번거로움이 발생한다.

Since Babel 7 the Babel team switched to scoped packages, so you now have to use @babel/core instead of babel-core.

각종 @bebel/preset-* 들도 웹팩에 따라 적용가능한 프리셋이 다르다. 수 년전에 작성된 써드파티의 프리셋을 사용했다면 최신버전의 바벨에는 사용할 수 없다. 따라서 웹팩을 갱신할 때 같이 해주어야 한다.

마무리

생각보다 내용이 별로 없어보이지만 핵심만 요약을 해서 그렇지 설정 파일과 바벨을 비롯한 모든 플러그인과 로더를 웹팩 버전에 맞추고 변경된 사용 방법을 적용시켜야 하며 이러한 변경점이 올바르게 동작하는지 테스팅을 해볼 필요도 있어 시간 소모가 제법 많이된다. 특히나 과거의 플러그인이 개발이 중단되었거나 대체되어 더이상 최신의 웹팩에서 제공하지 않는 경우에는 이를 찾아야 하는 수고로움도 존재한다.

더 읽을거리

암호화폐 트레이딩 봇을 만들었다 (feat. 업비트)

나만 알고 있기에는 너무 아깝잖아? 그래서 강의를 만들어봤어.

내가 개발한 티스토리 프로젝트 정리!

티스토리 구독 서비스 이전에 존재했던, 티스토리 이웃서비스 티네스(Tines) 개발 돌아보기