Bir uygulamayı optimize ederken yapılacak ilk şeylerden biri, onu olabildiğince küçük yapmaktır. İşte bunu webpack ile nasıl yapacağınız.
Üretim modunu kullanın (yalnızca webpack 4) #
Webpack 4 tanıtıldı yeni mode
bayrak. Bu bayrağı şu şekilde ayarlayabilirsiniz: 'development'
veya 'production'
web paketini, uygulamayı belirli bir ortam için oluşturduğunuza dair ipucu vermek için:
// webpack.config.js
module.exports = {
mode: 'production',
};
etkinleştirdiğinizden emin olun. production
uygulamanızı üretim için oluştururken mod. Bu, webpack’in küçültme, kitaplıklarda yalnızca geliştirmeye yönelik kodun kaldırılması gibi optimizasyonları uygulamasını sağlayacaktır. ve dahası.
daha fazla okuma #
Küçültmeyi etkinleştir #
Küçültme, fazladan boşlukları kaldırarak, değişken adlarını kısaltarak vb. kodu sıkıştırdığınız zamandır. Bunun gibi:
// 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);++ta;)l[t]=r(n[t],t,n);return l}
Webpack, kodu küçültmenin iki yolunu destekler: paket düzeyinde küçültme Ve yükleyiciye özgü seçenekler. Aynı anda kullanılmaları gerekir.
Paket düzeyinde küçültme #
Paket düzeyinde küçültme, derlemeden sonra tüm paketi sıkıştırır. İşte nasıl çalıştığı:
-
Böyle bir kod yazarsınız:
// comments.js
import './comments.css';
export function render(data, target) {
console.log('Rendered!');
} -
Webpack, onu yaklaşık olarak aşağıdaki şekilde derler:
// 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!');
} -
Bir küçültücü, onu yaklaşık olarak şu şekilde sıkıştırır:
// 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)
Web paketi 4’te, paket seviyesinde küçültme, hem üretim modunda hem de mod olmadan otomatik olarak etkinleştirilir. kullanır UglifyJS küçültücü kaputun altında. (Küçültmeyi devre dışı bırakmanız gerekirse, yalnızca geliştirme modunu kullanın veya false
için optimization.minimize
seçenek.)
Web paketi 3’te, kullanman gerek UglifyJS eklentisi direkt olarak. Eklenti, webpack ile birlikte gelir; etkinleştirmek için şuraya ekleyin: plugins
yapılandırma bölümü:
// webpack.config.js
const webpack = require('webpack');module.exports = {
plugins: [
new webpack.optimize.UglifyJsPlugin(),
],
};
Yükleyiciye özgü seçenekler #
Kodu küçültmenin ikinci yolu, yükleyiciye özgü seçeneklerdir (yükleyici nedir). Yükleyici seçenekleriyle, küçültücünün küçültemeyeceği şeyleri sıkıştırabilirsiniz. Örneğin, bir CSS dosyasını içe aktardığınızda css-loader
dosya bir dizgede derlenir:
/* 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}",""]);
Küçültücü, bu kodu bir dize olduğu için sıkıştıramaz. Dosya içeriğini küçültmek için, yükleyiciyi bunu yapacak şekilde yapılandırmamız gerekir:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { minimize: true } },
],
},
],
},
};
daha fazla okuma #
Belirtin NODE_ENV=production
#
Ön uç boyutunu azaltmanın başka bir yolu da NODE_ENV
çevresel değişken kodunuzda değere production
.
kütüphaneler okur NODE_ENV
geliştirme veya üretim modunda hangi modda çalışacaklarını tespit etmek için değişken. Bazı kütüphaneler bu değişkene göre farklı davranır. Örneğin, ne zaman NODE_ENV
ayarlı değil production
Vue.js ek kontroller yapar ve uyarıları yazdırır:
// vue/dist/vue.runtime.esm.js
// …
if (process.env.NODE_ENV !== 'production') {
warn('props must be strings when using array syntax.');
}
// …
React benzer şekilde çalışır – uyarıları içeren bir geliştirme derlemesi yükler:
// 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.'
);
// …
Bu tür kontroller ve uyarılar genellikle üretimde gereksizdir, ancak kodda kalır ve kitaplık boyutunu artırır. Web paketi 4’te, ekleyerek bunları kaldırın optimization.nodeEnv: 'production'
seçenek:
// webpack.config.js (for webpack 4)
module.exports = {
optimization: {
nodeEnv: 'production',
minimize: true,
},
};
Web paketi 3’te, kullan DefinePlugin
yerine:
// 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()
]
};
İkisi de optimization.nodeEnv
seçenek ve DefinePlugin
aynı şekilde çalışır – tüm oluşumlarını değiştirirler process.env.NODE_ENV
belirtilen değer ile. Yukarıdaki yapılandırma ile:
-
Webpack, tüm oluşumlarının yerini alacak
process.env.NODE_ENV
ile"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.');
} -
Ve daha sonra küçültücü tüm bunları kaldıracak
if
dallar – çünkü"production" !== 'production'
her zaman yanlıştır ve eklenti, bu dalların içindeki kodun asla yürütülmeyeceğini anlar:// 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 };
}
daha fazla okuma #
ES modüllerini kullanın #
Ön uç boyutunu azaltmanın bir sonraki yolu kullanmaktır. ES modülleri.
ES modüllerini kullandığınızda, webpack ağaç sallama yapabilir hale gelir. Ağaç sallama, bir paketleyicinin tüm bağımlılık ağacını geçmesi, hangi bağımlılıkların kullanıldığını kontrol etmesi ve kullanılmayanları kaldırmasıdır. Dolayısıyla, ES modülü sözdizimini kullanırsanız, web paketi kullanılmayan kodu ortadan kaldırabilir:
-
Birden çok dışa aktarma içeren bir dosya yazarsınız, ancak uygulama bunlardan yalnızca birini kullanır:
// comments.js
export const render = () => { return 'Rendered!'; };
export const commentRestEndpoint = '/rest/comments';// index.js
import { render } from './comments.js';
render(); -
Webpack bunu anlıyor
commentRestEndpoint
kullanılmaz ve pakette ayrı bir dışa aktarma noktası oluşturmaz:// 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 */
}) -
küçültücü kullanılmayan değişkeni kaldırır:
// bundle.js (part that corresponds to comments.js)
(function(n,e){"use strict";var r=function(){return"Rendered!"};e.b=r})
Bu, ES modülleri ile yazılmışlarsa kitaplıklarda bile çalışır.
Tam olarak web paketinin yerleşik küçültücüsünü kullanmanız gerekmez (UglifyJsPlugin
) Yine de. Ölü kod kaldırmayı destekleyen herhangi bir küçültücü (örn. Babel Minify eklentisi veya Google Kapatma Derleyici eklentisi) hile yapacak.
daha fazla okuma #
Resimleri optimize et #
resim hesabı yarısından fazla sayfa boyutundan. JavaScript kadar kritik olmasalar da (örneğin, işlemeyi engellemezler), yine de bant genişliğinin büyük bir bölümünü tüketirler. Kullanmak url-loader
, svg-url-loader
Ve image-webpack-loader
web paketinde optimize etmek için.
url-loader
küçük statik dosyaları uygulamaya yerleştirir. Konfigürasyon olmadan, iletilen bir dosyayı alır, onu derlenmiş paketin yanına koyar ve o dosyanın bir url’sini döndürür. Ancak belirtirsek, limit
seçeneği, bu sınırdan daha küçük dosyaları şu şekilde kodlar: Base64 veri url’si ve bu url’yi döndür. Bu, görüntüyü JavaScript koduna yerleştirir ve bir HTTP isteğini kaydeder:
// 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
aynen çalışır url-loader
– dosyaları şu şekilde kodlaması dışında: URL kodlaması Base64 yerine. Bu, SVG görüntüleri için kullanışlıdır – SVG dosyaları yalnızca düz bir metin olduğundan, bu kodlama boyut bakımından daha etkilidir.
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
loader: "svg-url-loader",
options: {
limit: 10 * 1024,
noquotes: true
}
}
]
}
};
image-webpack-loader
içinden geçen görüntüleri sıkıştırır. JPG, PNG, GIF ve SVG resimleri destekler, bu yüzden onu tüm bu türler için kullanacağız.
Bu yükleyici, görüntüleri uygulamaya gömmez, bu nedenle şu uygulamayla birlikte çalışması gerekir: url-loader
Ve svg-url-loader
. Her iki kurala da (biri JPG/PNG/GIF resimleri için, diğeri SVG resimleri için) kopyala-yapıştır yapmaktan kaçınmak için, bu yükleyiciyi ayrı bir kural olarak ekleyeceğiz. 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'
}
]
}
};
Yükleyicinin varsayılan ayarları zaten uygundur – ancak daha fazla yapılandırmak istiyorsanız, bkz. eklenti seçenekleri. Hangi seçeneklerin belirtileceğini seçmek için Addy Osmani’nin mükemmeline göz atın görüntü optimizasyonu kılavuzu.
daha fazla okuma #
Bağımlılıkları optimize edin #
Ortalama JavaScript boyutunun yarısından fazlası bağımlılıklardan gelir ve bu boyutun bir kısmı gereksiz olabilir.
Örneğin, Lodash (v4.17.4’ten itibaren) pakete 72 KB küçültülmüş kod ekler. Ancak, yalnızca 20 yöntemini kullanırsanız, yaklaşık 65 KB küçültülmüş kod hiçbir şey yapmaz.
Başka bir örnek Moment.js’dir. 2.19.1 sürümü, 223 KB küçültülmüş kod alır ve bu çok büyüktür – bir sayfadaki JavaScript’in ortalama boyutu Ekim 2017’de 452 KB idi. Ancak, bu boyutun 170 KB’si yerelleştirme dosyaları. Moment.js’yi birden çok dilde kullanmazsanız, bu dosyalar paketi amaçsızca şişirir.
Tüm bu bağımlılıklar kolayca optimize edilebilir. Optimizasyon yaklaşımlarını bir GitHub deposunda topladık – buna bir bak!
ES modülleri için modül birleştirmeyi etkinleştir (diğer adıyla kapsam kaldırma) #
Bir paket oluştururken, web paketi her modülü bir işleve sarar:
// 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!');
}
})
Geçmişte bu, CommonJS/AMD modüllerini birbirinden izole etmek için gerekliydi. Ancak bu, her modül için bir boyut ve performans ek yükü ekledi.
Webpack 2, CommonJS ve AMD modüllerinin aksine, her biri bir işlevle paketlenmeden paketlenebilen ES modülleri için destek sunmuştur. Ve webpack 3 böyle bir paketlemeyi mümkün kıldı – modül birleştirme. İşte modül birleştirmenin yaptığı:
// 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();
})
Farkı gör? Düz pakette, modül 0 gerektiriyordu render
modül 1’den. Modül birleştirme ile, require
basitçe gerekli işlevle değiştirilir ve modül 1 kaldırılır. Pakette daha az modül ve daha az modül yükü vardır!
Bu davranışı açmak için, web paketi 4’teetkinleştir optimization.concatenateModules
seçenek:
// webpack.config.js (for webpack 4)
module.exports = {
optimization: {
concatenateModules: true
}
};
Web paketi 3’te, kullan ModuleConcatenationPlugin
:
// webpack.config.js (for webpack 3)
const webpack = require('webpack');module.exports = {
plugins: [
new webpack.optimize.ModuleConcatenationPlugin()
]
};
daha fazla okuma #
Kullanmak externals
hem web paketi hem de web paketi olmayan kodunuz varsa #
Bazı kodların webpack ile derlendiği ve bazı kodların derlenmediği büyük bir projeniz olabilir. Oynatıcı widget’ının webpack ile oluşturulabileceği ve çevreleyen sayfanın şu şekilde olmayabileceği bir video barındırma sitesi gibi:
Her iki kod parçasının da ortak bağımlılıkları varsa, kodlarının birden çok kez indirilmesini önlemek için bunları paylaşabilirsiniz. Bu ile yapılır web paketi externals
seçenek – modülleri değişkenlerle veya diğer harici ithalatlarla değiştirir.
Bağımlılıklar mevcutsa window
#
Web paketi olmayan kodunuz, içinde değişkenler olarak bulunan bağımlılıklara dayanıyorsa window
takma ad bağımlılık adlarından değişken adlarına:
// webpack.config.js
module.exports = {
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
}
};
Bu yapılandırma ile web paketi paketlenmez react
Ve react-dom
paketler. Bunun yerine, bunun gibi bir şeyle değiştirilecekler:
// 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;
})
Bağımlılıklar AMD paketleri olarak yüklenirse #
Web paketi olmayan kodunuz bağımlılıkları ortaya çıkarmazsa window
, işler daha karmaşıktır. Ancak, web paketi olmayan kod bu bağımlılıkları şu şekilde kullanırsa, aynı kodu iki kez yüklemekten kaçınabilirsiniz: AMD paketleri.
Bunu yapmak için, web paketi kodunu bir AMD paketi olarak ve diğer ad modüllerini kitaplık URL’lerine derleyin:
// webpack.config.js
module.exports = {
output: {
libraryTarget: 'amd'
},
externals: {
'react': {
amd: '/libraries/react.min.js'
},
'react-dom': {
amd: '/libraries/react-dom.min.js'
}
}
};
Webpack, paketi şuraya saracak: define()
ve şu URL’lere bağlı olmasını sağlayın:
// bundle.js (beginning)
define(["/libraries/react.min.js", "/libraries/react-dom.min.js"], function () { … });
Web paketi olmayan kod, bağımlılıklarını yüklemek için aynı URL’leri kullanıyorsa, bu dosyalar yalnızca bir kez yüklenir – ek istekler yükleyici önbelleğini kullanır.
daha fazla okuma #
Özetliyor #
- Webpack 4 kullanıyorsanız üretim modunu etkinleştirin
- Paket düzeyinde küçültücü ve yükleyici seçenekleriyle kodunuzu küçültün
- Yalnızca geliştirme kodunu değiştirerek kaldırın
NODE_ENV
ileproduction
- Ağaç sallamayı etkinleştirmek için ES modüllerini kullanın
- Resimleri sıkıştır
- Bağımlılığa özel optimizasyonlar uygulayın
- Modül birleştirmeyi etkinleştir
- Kullanmak
externals
eğer bu senin için mantıklıysa