Kullanıcı arabirimi boyutunu küçült

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:

  1. Şöyle bir kod yazıyorsunuz:

    // comments.js
    import './comments.css';
    export function render(data, target) {
      console.log('Rendered!');
    }
    
  2. 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!');
    }
    
  3. 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

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:

  1. 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.');
    }
    
  2. 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

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:

  1. 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();
    
  2. 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 */
    })
    
  3. 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

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

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

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:

Bir video barındırma sitesinin ekran görüntüsü
(Tamamen rastgele bir video barındırma sitesi)

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ğerini production 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.