Uygulamanızı mümkün olduğunca küçük hale getirmek için webpack'i kullanma
Bir uygulamayı optimize ederken yapılacak ilk şeylerden biri, uygulamayı mümkün olduğunca küçük yapmasını sağlar. Bunu webpack ile nasıl yapacağınız aşağıda açıklanmıştır.
Üretim modunu kullanma (yalnızca webpack 4)
Webpack 4, yeni mode
işaretini kullanıma sundu. Örneğin,
oluşturmakta olduğunuz web paketine işaret etmek için bu işareti 'development'
veya 'production'
olarak ayarlayın
ortama yönelik olarak
değiştirilmesini gerektiriyor:
// webpack.config.js
module.exports = {
mode: 'production',
};
Uygulamanızı üretim için oluştururken production
modunu etkinleştirdiğinizden emin olun.
Bu seçenek, web paketinin sadeleştirme, yalnızca geliştirme amaçlı kodun kaldırılması gibi optimizasyonlar uygulamasını sağlar
kitaplıklarda ve daha fazlasında bulun.
Daha fazla bilgi
Küçültmeyi etkinleştir
Küçültme, kodun fazladan boşlukları kaldırarak, değişken adlarını ve değişken adlarını ve bu şekilde devam eder. Aşağıdaki 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);++t<a;)l[t]=r(n[t],t,n);return l}
Webpack, kodu küçültmek için iki yöntemi destekler: paket düzeyinde küçültme ve yükleyiciye özel seçenekler. Aynı anda kullanılmalıdırlar.
Paket düzeyinde küçültme
Paket düzeyinde küçültme, derlemeden sonra tüm paketi sıkıştırır. İşleyiş şekli:
Şöyle bir kod yazıyorsunuz:
// comments.js import './comments.css'; export function render(data, target) { console.log('Rendered!'); }
Webpack, dosyayı 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!'); }
Küçültücü, şablonu yaklaşık olarak aşağıdaki bölümlere 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 düzeyinde küçültme,her ikisi de üretimde otomatik olarak etkinleştirilir
ve bunlar olmadan kullanabilirsiniz. UglifyJS küçültücüsünü kullanır.
daha yakından inceleyeceğiz. (Küçültmeyi devre dışı bırakmanız gerekirse geliştirme modunu kullanın)
veya false
öğesini optimization.minimize
seçeneğine iletin.)
Web paketi 3'te,UglifyJS eklentisini kullanmanız gerekir.
doğrudan ekleyebilirsiniz. Eklenti webpack ile birlikte gelir; Bunu etkinleştirmek için plugins
bölümüne ekleyin
bölümüne ekleyin:
// webpack.config.js
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.optimize.UglifyJsPlugin(),
],
};
Yükleyiciye özel seçenekler
Kodu küçültmenin ikinci yolu, yükleyiciye özel seçeneklerdir (yükleyici
'dir) tıklayın. Yükleyici seçenekleriyle, sıkıştırılan öğeleri
küçültemez. Örneğin,
css-loader
ise dosya bir dize olarak 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}",""]);
Bu bir dize olduğundan, küçültücü kodu sıkıştıramaz. Dosya içeriğini küçültmek için yükleyiciyi bunu yapacak şekilde yapılandırın:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { minimize: true } },
],
},
],
},
};
Daha fazla bilgi
- UglifyJsplugin belgeleri
- Diğer popüler küçültücüler: Babel Küçült, Google Closure Derleyici
NODE_ENV=production
değerini belirtin
Kullanıcı arabirimi boyutunu küçültmenin bir başka yolu da NODE_ENV
çevresel değişken
kodunuzda production
değerine ekleyin.
Kitaplıklar, hangi modda çalışmaları gerektiğini algılamak için NODE_ENV
değişkenini okur.
mi yoksa üretime mi ihtiyacınız var? Bazı kitaplıklar bu değişkene bağlı olarak farklı davranır. Örneğin,
örnek, NODE_ENV
production
olarak ayarlanmadığında Vue.js ek kontroller ve baskılar yapar
uyarılar:
// vue/dist/vue.runtime.esm.js
// …
if (process.env.NODE_ENV !== 'production') {
warn('props must be strings when using array syntax.');
}
// …
React de 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 denetimler ve uyarılar üretimde genellikle gerekli değildir, ancak bunlar kodda kalır ve
büyütür. Webpack 4'te,
optimization.nodeEnv: 'production'
seçeneği:
// webpack.config.js (for webpack 4)
module.exports = {
optimization: {
nodeEnv: 'production',
minimize: true,
},
};
Web paketi 3'te bunun yerine DefinePlugin
kullanın:
// 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
seçeneği ve DefinePlugin
aynı şekilde çalışır:
tüm process.env.NODE_ENV
oluşumlarını belirtilen değerle değiştirir. Şununla
yapılandıralım:
Web paketi, tüm
process.env.NODE_ENV
oluşumlarını şununla değiştirecek:"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.'); }
Daha sonra, küçültücü bu tür tüm
if
dal –"production" !== 'production'
her zaman yanlış olduğundan ve eklenti şu dalların içindeki kodun hiçbir zaman 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 bilgi
- "Ortam değişkenleri" nedir?
- Şu konudaki web paketi dokümanları:
DefinePlugin
,EnvironmentPlugin
ES modüllerini kullanma
Kullanıcı arabirimi boyutunu küçültmenin bir sonraki yolu ES modüllerini inceleyin.
ES modüllerini kullandığınızda webpack, ağaç sallama özelliğini kullanabilir. Ağaç sallama, bir bitki örtüsü bağımlılık ağacının tamamını gezinir, hangi bağımlılıkların kullanıldığını kontrol eder ve kullanılmayanları kaldırır. Dolayısıyla, ES modülü söz dizimini kullanıyorsanız webpack, kullanılmayan kodu ortadan kaldırabilir:
Birden fazla dışa aktarma işlemi olan bir dosya yazıyorsunuz, ancak uygulama bunlardan yalnızca birini kullanıyor:
// comments.js export const render = () => { return 'Rendered!'; }; export const commentRestEndpoint = '/rest/comments'; // index.js import { render } from './comments.js'; render();
Webpack,
commentRestEndpoint
öğesinin kullanılmadığını ve bir ayrı dışa aktarma noktası ekleyin:// 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 işlem, ES modülleriyle yazılan kitaplıklarda bile çalışır.
Bununla birlikte, tam olarak webpack'in yerleşik küçültücüsünü (UglifyJsPlugin
) kullanmanız gerekmez.
Geçersiz kodların kaldırılmasını destekleyen tüm küçültücüler
(ör. Babel Minify eklentisi
veya Google Closure Compiler eklentisi)
size yardımcı olacaktır.
Daha fazla bilgi
Ağaç sallama hakkında web paketi dokümanları
Resimleri optimize edin
Resimler 1'den daha fazla
yarısına eşittir. Bu süre içinde
bunlar JavaScript kadar kritik öneme sahip değildir (ör. oluşturmayı engellemezler),
bant genişliği. Bu kampanyaları optimize etmek için url-loader
, svg-url-loader
ve image-webpack-loader
kullanın
webpack.
url-loader
küçük statik dosyaları satır içi
uygulamasını indirin. Yapılandırma olmadan, iletilen bir dosyayı alır, derlenen paketin yanına yerleştirir ve sonuçları
dosyanın URL'sini ekleyin. Ancak limit
seçeneğini belirtirseniz
Bu sınırı Base64 veri URL'si olarak ayarlayın ve bu URL'yi döndürün. Bu
resmi JavaScript koduna satır içi yaptırır ve bir HTTP isteği 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
, url-loader
gibi çalışır:
tek fark şudur: URL
kodlamayı kullanın.
bir. Bu, SVG resimler için yararlıdır. SVG dosyaları yalnızca düz bir metin olduğundan, bu kodlama
daha uygun bir boyuta sahip olmanızı sağlar.
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
loader: "svg-url-loader",
options: {
limit: 10 * 1024,
noquotes: true
}
}
]
}
};
image-webpack-loader
, giden resimleri sıkıştırır
adım adım açıklayacağım. JPG, PNG, GIF ve SVG resimleri desteklediğinden tüm bu türler için onu kullanacağız.
Bu yükleyici, uygulamaya resim yerleştirmediğinden url-loader
ve
svg-url-loader
. Kopyayı her iki kurala da (biri JPG/PNG/GIF resimleri, diğeri JPG/PNG/GIF) olarak yapıştırılmasını önlemek için
bir) yükleyiciyi, enforce: 'pre'
ile birlikte ayrı bir kural olarak ekleyeceğiz:
// 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 hazır durumda. Ancak bunu yapılandırmak daha fazla bilgi için eklenti seçeneklerine göz atın. Alıcı: belirtmek için, Addy Osmani’nin harika resim kılavuzuna göz atın. optimizasyon.
Daha fazla bilgi
- "base64 kodlaması nedir? ne için?"
- Addy Osmani'nin resim optimizasyonu rehberi
Bağımlılıkları optimize edin
Ortalama JavaScript boyutunun yarısından fazlası bağımlılıklardan kaynaklanır ve bu boyutun bir kısmı gereksizdir.
Örneğin, Lodash (sürüm 4.17.4'ten itibaren) pakete 72 KB küçültülmüş kod ekler. Ancak yalnızca örneğin, 20 yöntemi varsa, yaklaşık 65 KB küçültülmüş kod herhangi bir işe yaramaz.
Diğer bir örnek de Moment.js'dir. 2.19.1 sürümünde, küçültülmüş 223 KB kod gerekir. Bu da oldukça büyük bir sayıdır. bir sayfadaki JavaScript'in ortalama boyutu Ekim ayında 452 KB'tı 2017. Ancak, bu boyutta 170 KB yerelleştirme dosyaları ile kullanılabilir. Eğer Moment.js'yi birden fazla dilde kullanmıyorsanız bu dosyalar, amaçlanıyor.
Tüm bu bağımlılıklar kolayca optimize edilebilir. Bu kılavuzdaki optimizasyon yaklaşımlarını bir GitHub deposu – göz atın!
ES modülleri için modül birleştirmeyi etkinleştir (kapsam kaldırma olarak da bilinir)
Bir paket oluştururken webpack, her modülü bir işleve sarmalar:
// 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, CommonJS/AMD modüllerini birbirinden ayırmak için bu gerekliydi. Ancak bu ve her modül için genel bir boyut ve performans yükü oluşturur.
Webpack 2, CommonJS ve AMD modüllerinden farklı olarak paket ekleyebileceğiniz ES modülleri için destek sunmaya başladı. her birini bir fonksiyonla sarmalamadan çalışır. Webpack 3 ise bu tür bir paketlemeyi mümkün kılıyordu. modül birleştirme. İşte modül birleştirme ne işe yarar?
// 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üyor musunuz? Düz pakette, modül 0, modül 1'den render
gerektiriyordu. Entegre
require
yerine gerekli fonksiyon, modül 1'in ise
emin olun. Pakette daha az modül bulunur, ayrıca modül ek yükü de azalır.
Bu davranışı etkinleştirmek için web paketi 4'te optimization.concatenateModules
seçeneğini etkinleştirin:
// webpack.config.js (for webpack 4)
module.exports = {
optimization: {
concatenateModules: true
}
};
Web paketi 3'te,ModuleConcatenationPlugin
kullanın:
// webpack.config.js (for webpack 3)
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.optimize.ModuleConcatenationPlugin()
]
};
Daha fazla bilgi
- Chrome Web Mağazası'ndaki ModuleConcatenationPlugin
- “Kapsama kısa bir giriş kaldırma"
- Bu eklentinin ne yaptığına ilişkin ayrıntılı açıklama CANNOT TRANSLATE
Hem webpack hem de webpack olmayan kodunuz varsa externals
öğesini kullanın
Bazı kodların webpack ile derlendiği, bazılarının ise derlendiği büyük bir projeniz olabilir. Beğenme oynatıcı widget'ının webpack ile oluşturulabileceği bir video barındırma sitesi ve çevresindeki sayfa şu olmayabilir:
Her iki kod parçası da ortak bağımlılıklara sahipse kodlarını indirmemek için bunları paylaşabilirsiniz
birden fazla kez. Bu işlem, web paketinin externals
özelliğiyle yapılır.
seçeneği: Modülleri değişkenler veya
içe aktarmanızı sağlar.
window
bölgesinde bağımlılıklar kullanılabiliyorsa
Web paketi olmayan kodunuz window
ürününde değişken olarak bulunan bağımlılıklara dayanıyorsa takma ad,
bağımlılık adlarını değişken adlarına çevir:
// webpack.config.js
module.exports = {
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
}
};
Bu yapılandırmayla web paketi, react
ve react-dom
paketlerini paketlemez. Bunun yerine
şununla değiştirin:
// 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 window
içine bağımlılıkları göstermiyorsa işler daha karmaşıktır.
Bununla birlikte, web paketi olmayan kodlar bu kodları tüketiyorsa aynı kodu iki kez yüklemekten kaçınabilirsiniz
bağımlılıkları AMD paketleri olarak ekleyin.
Bunu yapmak için web paketi kodunu AMD paketi ve takma ad modüllerinden kitaplık URL'lerinde derleyin:
// webpack.config.js
module.exports = {
output: {
libraryTarget: 'amd'
},
externals: {
'react': {
amd: '/libraries/react.min.js'
},
'react-dom': {
amd: '/libraries/react-dom.min.js'
}
}
};
Web paketi, paketi define()
içine sarmalar ve şu URL'lere bağımlı hale getirir:
// 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 yüklenir. Yalnızca bir kez – ek istekler yükleyici önbelleğini kullanır.
Daha fazla bilgi
externals
üzerindeki web paketi dokümanları
Özet
- Web paketi 4 kullanıyorsanız üretim modunu etkinleştirme
- Paket düzeyinde küçültücü ve yükleyici seçenekleriyle kodunuzu en aza indirin
NODE_ENV
değeriniproduction
ile değiştirerek yalnızca geliştirme amaçlı kodu kaldırın- Ağaç sallamayı etkinleştirmek için ES modüllerini kullanın
- Resimleri sıkıştırın
- Bağımlılığa özel optimizasyonlar uygulama
- Modül birleştirmeyi etkinleştir
- Sizin için mantıklıysa
externals
özelliğini kullanın.