webpack을 사용하여 앱을 최대한 작게 만드는 방법
애플리케이션을 최적화할 때 가장 먼저 해야 할 일은 애플리케이션을 있습니다. webpack으로 이를 수행하는 방법은 다음과 같습니다.
프로덕션 모드 사용 (webpack 4만 해당)
Webpack 4는 새로운 mode
플래그를 도입했습니다. 다음과 같이 설정할 수 있습니다.
이 플래그를 'development'
또는 'production'
로 지정하여 빌드 중인 webpack에 대한 힌트를 얻을 수 있습니다.
애플리케이션을 배포합니다.
// webpack.config.js
module.exports = {
mode: 'production',
};
프로덕션용 앱을 빌드할 때는 production
모드를 사용 설정해야 합니다.
이렇게 하면 Webpack이 압축, 개발 전용 코드 삭제와 같은 최적화를 적용합니다.
라이브러리 등
추가 자료
압축 사용 설정
축소는 여분의 공백을 제거하고 변수 이름을 단축하고 등등. 다음 행을 추가하면 됩니다.
// Original code
function map(array, iteratee) {
let index = -1;
const length = array == null ? 0 : array.length;
const result = new Array(length);
while (++index < length) {
result[index] = iteratee(array[index], index, array);
}
return result;
}
↓
// Minified code
function map(n,r){let t=-1;for(const a=null==n?0:n.length,l=Array(a);++t<a;)l[t]=r(n[t],t,n);return l}
Webpack은 코드를 축소하는 두 가지 방법인 번들 수준 축소와 로더별 옵션을 제공합니다. 동시에 사용해야 합니다.
번들 수준 축소
번들 수준 축소는 컴파일 후 전체 번들을 압축합니다. 이용 방법은 다음과 같습니다.
다음과 같은 코드를 작성합니다.
// comments.js import './comments.css'; export function render(data, target) { console.log('Rendered!'); }
Webpack은 이를 대략 다음과 같이 컴파일합니다.
// bundle.js (part of) "use strict"; Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); /* harmony export (immutable) */ __webpack_exports__["render"] = render; /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__comments_css__ = __webpack_require__(1); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__comments_css_js___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__comments_css__); function render(data, target) { console.log('Rendered!'); }
축소기는 파일을 대략 다음과 같이 압축합니다.
// minified bundle.js (part of) "use strict";function t(e,n){console.log("Rendered!")} Object.defineProperty(n,"__esModule",{value:!0}),n.render=t;var o=r(1);r.n(o)
Webpack 4에서는 번들 수준 축소가 자동으로 사용 설정됩니다. 둘 다 프로덕션 환경에서
있습니다. UglifyJS 축소기를 사용합니다.
살펴보겠습니다 축소를 사용 중지해야 하는 경우 개발 모드만 사용하여
또는 false
를 optimization.minimize
옵션에 전달합니다.)
Webpack 3에서는 UglifyJS 플러그인을 사용해야 합니다.
바로 그것입니다. 플러그인은 webpack과 함께 번들로 제공됩니다. 사용 설정하려면 plugins
에 추가하세요.
섹션에서 다음을 실행합니다.
// webpack.config.js
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.optimize.UglifyJsPlugin(),
],
};
로더별 옵션
코드를 축소하는 두 번째 방법은 로더별 옵션 (로더는
is) 로더 옵션을 사용하면
축소할 수 없습니다. 예를 들어
css-loader
: 파일이 문자열로 컴파일됩니다.
/* comments.css */
.comment {
color: black;
}
// minified bundle.js (part of)
exports=module.exports=__webpack_require__(1)(),
exports.push([module.i,".comment {\r\n color: black;\r\n}",""]);
이 코드는 문자열이므로 축소기가 압축할 수 없습니다. 파일 콘텐츠를 축소하려면 이렇게 하도록 로더를 구성합니다.
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { minimize: true } },
],
},
],
},
};
추가 자료
- UglifyJsPlugin 문서
- 인기 있는 기타 축소기는 다음과 같습니다. Babel 축소, Google 클로저 컴파일러
NODE_ENV=production
지정
프런트엔드 크기를 줄이는 또 다른 방법은 NODE_ENV
환경 변수
값을 production
로 변경합니다.
라이브러리는 NODE_ENV
변수를 읽고 작동해야 하는 모드를 감지합니다.
프로덕션에 배포할 수 있습니다. 일부 라이브러리는 이 변수에 따라 다르게 동작합니다. 대상
예를 들어 NODE_ENV
가 production
로 설정되지 않은 경우 Vue.js가 추가 검사를 실행하고 인쇄합니다.
경고:
// vue/dist/vue.runtime.esm.js
// …
if (process.env.NODE_ENV !== 'production') {
warn('props must be strings when using array syntax.');
}
// …
React도 비슷하게 작동합니다. 즉, 경고가 포함된 개발 빌드를 로드합니다.
// react/index.js
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react.production.min.js');
} else {
module.exports = require('./cjs/react.development.js');
}
// react/cjs/react.development.js
// …
warning$3(
componentClass.getDefaultProps.isReactClassApproved,
'getDefaultProps is only used on classic React.createClass ' +
'definitions. Use a static property named `defaultProps` instead.'
);
// …
이러한 검사와 경고는 일반적으로 프로덕션에서 불필요하지만 코드에 남아 있고
라이브러리 크기를 늘릴 수 있습니다. Webpack 4에서는
optimization.nodeEnv: 'production'
옵션:
// webpack.config.js (for webpack 4)
module.exports = {
optimization: {
nodeEnv: 'production',
minimize: true,
},
};
Webpack 3에서는 대신 DefinePlugin
를 사용합니다.
// webpack.config.js (for webpack 3)
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"'
}),
new webpack.optimize.UglifyJsPlugin()
]
};
optimization.nodeEnv
옵션과 DefinePlugin
는 모두 동일한 방식으로 작동합니다.
모든 process.env.NODE_ENV
항목을 지정된 값으로 바꿉니다.
구성:
Webpack이
process.env.NODE_ENV
과(와) 일치하는 항목을 모두 다음으로 바꿉니다."production"
:// vue/dist/vue.runtime.esm.js if (typeof val === 'string') { name = camelize(val); res[name] = { type: null }; } else if (process.env.NODE_ENV !== 'production') { warn('props must be strings when using array syntax.'); }
↓
// vue/dist/vue.runtime.esm.js if (typeof val === 'string') { name = camelize(val); res[name] = { type: null }; } else if ("production" !== 'production') { warn('props must be strings when using array syntax.'); }
그런 다음 최소기가 이러한 모든
if
브랜치:"production" !== 'production'
가 항상 false이기 때문에 그리고 플러그인은 이러한 브랜치 내의 코드가 실행되지 않는다는 것을 이해합니다.// vue/dist/vue.runtime.esm.js if (typeof val === 'string') { name = camelize(val); res[name] = { type: null }; } else if ("production" !== 'production') { warn('props must be strings when using array syntax.'); }
↓
// vue/dist/vue.runtime.esm.js (without minification) if (typeof val === 'string') { name = camelize(val); res[name] = { type: null }; }
추가 자료
- '환경 변수'란 무엇인가요?
DefinePlugin
에 관한 Webpack 문서EnvironmentPlugin
ES 모듈 사용
프런트엔드 크기를 줄이는 다음 방법은 ES를 사용하는 것입니다. 모듈을 참조하세요.
ES 모듈을 사용하면 webpack이 트리 쉐이킹을 할 수 있게 됩니다. 나무 흔들림은 번들러가 전체 종속 항목 트리를 순회하고 사용된 종속 항목을 확인하고 사용되지 않는 종속 항목을 삭제합니다. 따라서 ES 모듈 구문을 사용하는 경우 webpack으로 사용되지 않는 코드를 제거할 수 있습니다.
내보내기가 여러 개 포함된 파일을 작성하지만 앱에서 그중 하나만 사용합니다.
// comments.js export const render = () => { return 'Rendered!'; }; export const commentRestEndpoint = '/rest/comments'; // index.js import { render } from './comments.js'; render();
Webpack은
commentRestEndpoint
이 사용되지 않으며 번들에 있는 별도의 내보내기 지점을 지정합니다.// bundle.js (part that corresponds to comments.js) (function(module, __webpack_exports__, __webpack_require__) { "use strict"; const render = () => { return 'Rendered!'; }; /* harmony export (immutable) */ __webpack_exports__["a"] = render; const commentRestEndpoint = '/rest/comments'; /* unused harmony export commentRestEndpoint */ })
최소기는 사용되지 않는 변수를 삭제합니다.
// bundle.js (part that corresponds to comments.js) (function(n,e){"use strict";var r=function(){return"Rendered!"};e.b=r})
라이브러리가 ES 모듈로 작성된 경우에도 작동합니다.
하지만 Webpack에 내장된 축소기 (UglifyJsPlugin
)를 정확하게 사용할 필요는 없습니다.
데드 코드 삭제를 지원하는 축소기
(예: Babel Minify 플러그인)
또는 Google 클로저 컴파일러 플러그인)
할 수 있습니다.
추가 자료
트리 쉐이킹 관련 Webpack 문서
이미지 최적화
Google에서 제공하는 이미지는
절반으로 줄일 수 있습니다. 다른
자바스크립트만큼 중요하지 않지만 (예: 렌더링을 차단하지 않음)
지정할 수도 있습니다 url-loader
, svg-url-loader
, image-webpack-loader
를 사용하여
webpack이 포함되어 있습니다
url-loader
는 작은 정적 파일을
있습니다. 구성이 없으면 전달된 파일을 가져와서 컴파일된 번들 옆에 배치하고 다음을 반환합니다.
해당 파일의 URL입니다. 그러나 limit
옵션을 지정하면
이 한도를 Base64 데이터 URL로 저장하고 이 URL을 반환합니다. 이
이미지를 자바스크립트 코드에 삽입하고 HTTP 요청을 저장합니다.
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif)$/,
loader: 'url-loader',
options: {
// Inline files smaller than 10 kB (10240 bytes)
limit: 10 * 1024,
},
},
],
}
};
// index.js
import imageUrl from './image.png';
// → If image.png is smaller than 10 kB, `imageUrl` will include
// the encoded image: 'data:image/png;base64,iVBORw0KGg…'
// → If image.png is larger than 10 kB, the loader will create a new file,
// and `imageUrl` will include its url: `/2fcd56a1920be.png`
svg-url-loader
는 url-loader
처럼 작동합니다.
URL
인코딩을 사용하여
있습니다 이는 SVG 이미지에 유용합니다. SVG 파일은 일반 텍스트이기 때문에
더 효율적으로 사용할 수 있습니다.
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
loader: "svg-url-loader",
options: {
limit: 10 * 1024,
noquotes: true
}
}
]
}
};
image-webpack-loader
는 이동 중인 이미지를 압축합니다
그것을 통해. JPG, PNG, GIF, SVG 이미지를 지원하므로 이 모든 유형에 사용합니다.
이 로더는 앱에 이미지를 삽입하지 않으므로 url-loader
및
svg-url-loader
두 규칙 모두에 복사해서 붙여넣지 않으려면 (JPG/PNG/GIF 이미지에 대해 하나씩, 다른 규칙은
SVG용 하나) enforce: 'pre'
를 사용하여 별도의 규칙으로 이 로더를 포함합니다.
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif|svg)$/,
loader: 'image-webpack-loader',
// This will apply the loader before the other ones
enforce: 'pre'
}
]
}
};
로더의 기본 설정은 이미 준비가 되어 있지만, 기본 설정을 구성하기를 원하는 경우 플러그인 옵션을 참고하세요. 받는사람 추가할 옵션을 선택하려면 Addy Osmani의 이미지 관련 유용한 가이드를 읽어보세요 최적화를 참조하세요.
추가 자료
- "base64 인코딩은 궁금하실 수 있습니다
- Addy Osmani의 이미지 최적화 가이드
종속 항목 최적화
평균 JavaScript 크기의 절반 이상이 종속 항목에서 비롯되며, 그 중 일부는 불필요할 수도 있습니다
예를 들어 Lodash (v4.17.4부터)는 번들에 72KB의 축소된 코드를 추가합니다. 그러나 만일 약 65KB의 축소된 코드는 아무 작업도 하지 않습니다.
또 다른 예는 Moment.js입니다. 최신 버전의 2.19.1 버전은 223KB의 축소된 코드를 사용합니다. 10월에 페이지의 JavaScript 평균 크기는 452KB였습니다. 2017 하지만 이 크기의 170KB는 현지화는 파일을 참고하세요. 만약 Moment.js를 여러 언어로 사용하지 않는 경우 이 파일은 있습니다.
이러한 모든 종속 항목을 쉽게 최적화할 수 있습니다. Google은 여러 연구에서 GitHub 저장소 – 확인
ES 모듈에 모듈 연결 사용 설정 (범위 호이스팅이라고도 함)
번들을 빌드할 때 webpack은 각 모듈을 함수로 래핑합니다.
// index.js
import {render} from './comments.js';
render();
// comments.js
export function render(data, target) {
console.log('Rendered!');
}
↓
// bundle.js (part of)
/* 0 */
(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
var __WEBPACK_IMPORTED_MODULE_0__comments_js__ = __webpack_require__(1);
Object(__WEBPACK_IMPORTED_MODULE_0__comments_js__["a" /* render */])();
}),
/* 1 */
(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_exports__["a"] = render;
function render(data, target) {
console.log('Rendered!');
}
})
이전에는 CommonJS/AMD 모듈을 서로 격리하기 위해 이렇게 해야 했습니다. 그러나 크기 및 성능 오버헤드가 존재합니다
Webpack 2는 CommonJS 및 AMD 모듈과 달리 번들로 묶을 수 있는 ES 모듈 지원을 도입했습니다. 각 함수를 함수로 래핑하지 않고 함수를 만들 수 있습니다 그리고 Webpack 3는 이러한 번들을 가능하게 했습니다. 모듈 연결. 방법은 다음과 같습니다. 모듈 연결은 어떤 역할을 하나요?
// index.js
import {render} from './comments.js';
render();
// comments.js
export function render(data, target) {
console.log('Rendered!');
}
↓
// Unlike the previous snippet, this bundle has only one module
// which includes the code from both files
// bundle.js (part of; compiled with ModuleConcatenationPlugin)
/* 0 */
(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
// CONCATENATED MODULE: ./comments.js
function render(data, target) {
console.log('Rendered!');
}
// CONCATENATED MODULE: ./index.js
render();
})
차이점을 아시겠죠? 일반 번들에서 모듈 0은 모듈 1의 render
를 요구했습니다. 다음으로 바꿉니다.
require
는 단순히 필수 함수로 대체되고 모듈 1은
삭제되었습니다. 번들은 모듈이 더 적고 모듈 오버헤드도 적습니다.
이 동작을 사용 설정하려면 Webpack 4에서 optimization.concatenateModules
옵션을 사용 설정하세요.
// webpack.config.js (for webpack 4)
module.exports = {
optimization: {
concatenateModules: true
}
};
Webpack 3에서 ModuleConcatenationPlugin
를 사용합니다.
// webpack.config.js (for webpack 3)
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.optimize.ModuleConcatenationPlugin()
]
};
추가 자료
Webpack 및 Webpack 외의 코드가 모두 있는 경우 externals
사용
일부 코드는 webpack으로 컴파일되는 대규모 프로젝트의 경우, 어떤 코드는 컴파일되지 않을 수 있습니다. 좋아요 웹팩으로 플레이어 위젯을 구축할 수 있는 동영상 호스팅 사이트와 주변 페이지 다음과 같지 않을 수 있습니다.
<ph type="x-smartling-placeholder">두 코드 모두에 공통 종속 항목이 있는 경우 이를 공유하여 코드 다운로드를 방지할 수 있습니다.
여러 번 반복해야 할 수도 있습니다. 이 작업은 Webpack의 externals
옵션을 사용하여 모듈을 변수로 대체하거나
기타 외부 가져오기를 실행할 수 있습니다
window
에서 종속 항목을 사용할 수 있는 경우
webpack 외의 코드가 window
에서 변수로 사용할 수 있는 종속 항목을 사용하는 경우 별칭
종속 항목 이름을 변수 이름으로 바꿉니다.
// webpack.config.js
module.exports = {
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
}
};
이 구성을 사용하면 webpack이 react
및 react-dom
패키지를 번들로 묶지 않습니다. 대신
다음과 같이 바꿉니다.
// bundle.js (part of)
(function(module, exports) {
// A module that exports `window.React`. Without `externals`,
// this module would include the whole React bundle
module.exports = React;
}),
(function(module, exports) {
// A module that exports `window.ReactDOM`. Without `externals`,
// this module would include the whole ReactDOM bundle
module.exports = ReactDOM;
})
종속 항목이 AMD 패키지로 로드되는 경우
webpack 이외의 코드가 window
에 종속 항목을 노출하지 않으면 상황이 더 복잡해집니다.
하지만 webpack 이외 코드에서
AMD 패키지로 종속 항목을 설치합니다.
이렇게 하려면 다음과 같이 webpack 코드를 AMD 번들로 컴파일하고 별칭 모듈을 라이브러리 URL로 컴파일합니다.
// webpack.config.js
module.exports = {
output: {
libraryTarget: 'amd'
},
externals: {
'react': {
amd: '/libraries/react.min.js'
},
'react-dom': {
amd: '/libraries/react-dom.min.js'
}
}
};
Webpack은 번들을 define()
로 래핑하고 다음 URL에 종속되도록 합니다.
// bundle.js (beginning)
define(["/libraries/react.min.js", "/libraries/react-dom.min.js"], function () { … });
webpack 이외의 코드에서 동일한 URL을 사용하여 종속 항목을 로드하는 경우 이러한 파일이 로드됩니다. 한 번만 – 추가 요청에서 로더 캐시를 사용합니다.
추가 자료
externals
의 Webpack 문서
요약
- webpack 4를 사용하는 경우 프로덕션 모드 사용 설정
- 번들 수준의 최소화기 및 로더 옵션으로 코드 최소화
NODE_ENV
를production
로 바꿔 개발 전용 코드를 삭제합니다.- ES 모듈을 사용하여 트리 쉐이킹 사용 설정
- 이미지 압축
- 종속 항목별 최적화 적용
- 모듈 연결 사용 설정
- 이 옵션이 적절하다면
externals
을(를) 사용하세요.