작성자 : Jennifer Bland
원문 : https://medium.com/js-dojo/how-to-reduce-your-vue-js-bundle-size-with-webpack-3145bf5019b7
필자는 Stanley Black & Decker의 Industry 4.0 팀에서 일하고 있다. 최근 우리 팀은 세계적인 Stanley의 제조 공장을 위해 앱 스토어와 같은 것을 만들었다. 공장들은 온라인 시장에 방문하여 해당 지역에서 생산하는 제품을 기반으로 필요한 애플리케이션을 선택할 수 있다. 이렇게 하면 공장을 돌리기 위해 모든 애플리케이션을 함께 번들로 묶은 커스텀 빌드가 만들어진다. 그러나 이렇게 많은 양의 애플리케이션을 번들로 묶어 Vue를 프로덕션 빌드하면 크기가 초과되었다는 경고가 여러 번 나타난다.
빌드를 하면 다음 두 가지 에러 메시지가 발생한다.

Vue는 번들 된 각 에셋의 크기가 244 KiB를 초과하지 않을 것을 권장한다. 우리는 이 크기를 초과한 14개의 에셋을 가지고 있었다. 추가로 위에서 권장한 크기를 초과한 네 개의 엔트리 포인트 파일도 있었다. 지금부터 빌드 파일 크기를 반으로 줄이는 방법을 소개한다.
먼저 크기가 큰 번들 파일의 원인을 알아야 했다. 원인을 찾기 위해 webpack-bundle-analyzer를 설치했다. 이 플러그인은 각 번들 아이템의 크기를 시각적인 가이드로 제공해준다.
npm install --save-dev webpack-bundle-analyzer그 다음 vue.config.js 파일에서 이것을 사용하기 위해 webpack 설정을 했다. 필자가 vue.config.js 파일에 설정한 내용은 다음과 같다.
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
.BundleAnalyzerPlugin;
module.exports = {
configureWebpack: {
plugins: [new BundleAnalyzerPlugin()]
}
};플러그인을 설치하고 프로덕션 빌드를 다시 실행하면 번들 파일 크기가 2.48MB로 나온다. 이미지를 보면 큰 용량의 범인을 명확히 알 수 있다.

Lodash는 번들 파일의 70.74kb를 차지하고 있었다. Lodash는 프레임워크의 모든 애플리케이션에서 두 곳에서만 사용된다. 단지 2개 메서드 때문에 번들 크기의 많은 양이 차지되고 있다.

lodash뿐만 아니라 vue-lodash도 가져오고 있었다. 문제를 해결하는 첫 번째 단계는 필요하지 않은 vue-lodash를 package.json에서 제거하는 것이다.
다음 단계는 lodash 전체 라이브러리를 가져오는 대신 필요한 2개 메서드만 가져오도록 하는 것이다. 우리는 cloneDeep과 sortBy를 사용하고 있었다. lodash 전체 라이브러리를 가져오던 초기 호출 방식을 변경했다.
import _ from 'lodash';lodash에서 lodash/core로 import 구문을 변경해 필요한 2개 메서드만 가져오도록 변경했다.
import { cloneDeep, sortBy } from 'lodash/core';이러한 변경으로 번들 파일 크기가 2.48MB에서 2.42MB로 줄어들었다. 다음 이미지는 현재 줄어든 번들 크기를 보여준다.

그리고 여기서 번들 파일의 부분으로 lodash 자체 크기를 볼 수 있다.

Moment.js는 번들 파일에서 234.36KB를 차지하고 있었다. 이전 이미지를 보면 지원하는 모든 언어에 대한 국제화 로케일이 압도적으로 큰 용량을 차지한 것을 볼 수 있다. 번들 파일에서는 moment.js 전체를 사용하지 않으므로 불필요한 용량을 차지할 뿐이다.
다행히도 이를 제거할 수 있다. 다음 호출로 moment.js 전체를 가져오는 대신,
import moment form 'moment';이 호출을 통해서 날짜 조작 코드만 가져올 수 있다.
import moment from 'moment/src/moment'하지만 우리의 코드베이스에서 적어도 이 대체 코드를 만드는 것만으로는 어려움이 있다. 코드의 18곳에서 moment.js를 가져오고 있었다. 전체 검색을 해서 코드를 변경할 수 있었다. 그러나 프레임워크에 새 애플리케이션을 추가할 경우, 개발자가 기본 호출을 사용하여 moment.js를 가져올 수 있다. 그렇게 하면 우리는 또 다시 모든 국제화 로케일을 가져오게 된다.
그래서 트레이드오프로 웹팩에서 숏컷 별칭을 만들었다. 숏컷은 'moment'를 'moment/src/moment'로 가져오는 모든 호출을 대체한다. resolve 옵션을 사용하고 별칭을 설정하여 vue.config.js 파일에 별칭을 추가할 수 있다. 다음은 필자가 설정한 vue.config.js 파일이다.

현재 프로덕션 빌드를 실행하면 번들 파일 크기가 2.22MB로 줄어들었다.

이미지에서 moment.js를 보면 국제화 로케일이 더 이상 로드되지 않는 것을 볼 수 있다.
moment.js에서 로케일을 제거하면, 서버를 실행할 때마다 코드에서 ./locale를 찾을 수 없다고 에러가 발생한다. 이 문제에 대해서 찾아보니 이전부터 있었던 moment.js의 노운 이슈인 것을 알게되었다. moment.js는 로케일을 항상 로드한다고 가정한다. 날짜 조작 기능만 로드할 수는 없다.
이를 해결하기 위해 빌트인 웹팩 플러그인 IgnorePlugin을 사용해 이 메시지를 무시했다. 다음은 필자가 vue.config.js 파일에 추가한 플러그인 코드다.
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)다음 목표는 Vuetify.js의 크기다. Vuetify는 500.78KB를 차지하고 있었다. 이것은 하나의 벤더가 차지하기에 많은 양이다.

Vuetify는 마치 원하는 것만 골라 담을 수 있는 식사(a-la-carte) 같은 기능을 제공한다. 이는 사용하는 Vuetify 컴포넌트만 가져올 수 있다는 것을 의미한다. 그리고 이렇게 하면 크기가 줄어든다. 문제는 우리가 사용하고 있는 컴포넌트를 확인하고 처리하려고 하는 애플리케이션이 너무 많다는 것이다.
현재 Vuetify 버전(아티클을 작성할 당시 1.56 버전)에서는 vuetify-loader를 제공하고 있다. vuetify-loader는 코드를 살펴보고 사용중인 모든 컴포넌트를 확인한 다음 번들로 가져올 것이다. 참고: 결국 vuetify v2에 이 기능이 내장되었다. 2 버전을 사용하기 전까지는 사용하는 컴포넌트만 가져오기 위해 vuetify-loader를 사용해야 한다. Vuetify 문서에 따르면 필요한 모든 스타일을 얻으려면 stylus로 가져와야 한다.
필자는 우리가 vuetify.js 구 버전을 실행하고 있었다는 것을 알게 되었다. 그래서 vuetify 버전을 최신으로 업그레이드 하기로 했다. 또한 스타일 관련된 것들과 vuetify-loader를 같이 설치했다. (역자주 : vuetify 외 다른 모듈은 --save-dev 옵션을 사용하여 devDependencies로 설치해야 한다)
npm install vuetify vuetify-loader stylus stylus-loader style-loader css-loader --saveVuetify를 가져오는 플러그인 코드에는 테마가 회사의 색상표를 사용하도록 정의되어 있다. 현재 필자의 Vuetify 플러그인은 다음과 같다.

vuetify/lib으로 가져오기 위해 Vuetify import 방식을 변경해야 한다. 또한 모든 스타일을 얻기 위해 stylus를 import 했다. 현재 필자의 플러그인 코드는 다음과 같다.

마지막 단계는 사용하는 컴포넌트만 가져올 수 있도록 웹팩에서 vuetify-loader 플러그인을 설정하는 것이다. 플러그인을 require로 가져오고 배열로 플러그인을 추가한다. 필자의 vue.config.js는 다음과 같다.

현재 실행된 프로덕션용 번들 파일 크기는 2MB가 되었다.

Vue-echarts는 필자의 번들 파일에서 그다지 크지 않은 요소이다. Vue-echarts는 echarts 위에서 실행된다. Vuetify와 같이 Vue-echarts, echarts도 구 버전을 실행하고 있다. 두 모듈을 최신 버전으로 업그레이드 하기 위해 다음 명령어를 실행한다.
npm install echarts vue-echarts --save필자는 vue-echarts의 깃헙 레포를 조사하다가 클로즈 된 이슈들 중에서 다음 내용을 찾았다. 최신 버전의 vue-echarts를 사용하면 가져오는 코드를 변경해 더 작은 크기의 번들을 로드할 수 있다. 이전에는 이렇게 vue-echarts를 가져오고 있었는데,
import ECharts from 'vue-echarts';이렇게 변경했다.
import ECharts from 'vue-echarts/components/ECharts.vue';프로덕션 빌드를 실행하면 번들 파일 크기는 1.28MB로 줄어든다.

목표는 우리 애플리케이션의 프로덕션용 번들 파일 크기를 줄이는 것이었다. 초기 번들 파일 크기는 2.48MB였다. 몇 가지 변경을 통해서 번들 파일 크기를 1.2MB로 줄일 수 있었다. 크기가 거의 절반으로 줄었다.
만약 프로덕션용 Vue 애플리케이션을 만든다면 당신의 번들 파일 크기를 평가해봐야 한다. webpack-bundle-analyzer를 사용해 많은 공간을 차지하고 있는 항목을 확인한다. 그리고 나서 이 항목들의 크기를 줄이기 위해 필요한 단계들을 시작한다. 이러한 방식으로 필자의 번들 파일에서는 네 가지 가장 큰 항목의 크기를 줄일 수 있었다.
이 글에서 설명한 단계를 따라서 여러분의 프로덕션용 번들 사이즈도 줄일 수 있길 바란다. 질문이 있거나 코멘트가 필요하다면 아래에 남겨달라. 읽어줘서 고맙다.