लंबे समय तक कैश मेमोरी में सेव करने की सुविधा का इस्तेमाल करना

वेबपैक, एसेट को कैश मेमोरी में सेव करने में कैसे मदद करता है

अगली चीज़ (ऐप्लिकेशन के साइज़ को ऑप्टिमाइज़ करने के बाद, जो ऐप्लिकेशन लोड होने के समय को बेहतर बनाती है, उसे कैश मेमोरी में सेव करना होता है. इसका इस्तेमाल ऐप्लिकेशन के कुछ हिस्सों को क्लाइंट पर बनाए रखने के लिए करें और उन्हें हर बार दोबारा डाउनलोड करने से बचें.

बंडल वर्शन और कैश मेमोरी हेडर का इस्तेमाल करना

कैश मेमोरी में सेव करने का सामान्य तरीका यह है:

  1. ब्राउज़र को किसी फ़ाइल को लंबे समय के लिए कैश मेमोरी में सेव रखने के लिए कहें (जैसे, एक साल):

    # Server header
    Cache-Control: max-age=31536000
    

    अगर आपको Cache-Control के काम की जानकारी नहीं है, तो जेक आर्चिबाल्ड की कैश मेमोरी में डेटा सेव करने के सबसे सही तरीकों के बारे में पोस्ट देखें.

  2. और फ़ाइल बदल जाने पर उसका नाम बदलकर फिर से डाउनलोड करें:

    <!-- Before the change -->
    <script src="./index-v15.js"></script>
    
    <!-- After the change -->
    <script src="./index-v16.js"></script>
    

यह तरीका, ब्राउज़र को JS फ़ाइल डाउनलोड करने, उसे कैश मेमोरी में सेव करने, और कैश मेमोरी में सेव की गई कॉपी का इस्तेमाल करने के लिए कहता है. ब्राउज़र, नेटवर्क को सिर्फ़ तब ऐक्सेस करेगा, जब फ़ाइल का नाम बदल जाएगा या एक साल बीत जाने पर.

वेबपैक में, यही काम किया जाता है, लेकिन वर्शन नंबर के बजाय, फ़ाइल हैश तय किया जाता है. फ़ाइल के नाम में हैश शामिल करने के लिए, [chunkhash] का इस्तेमाल करें:

// webpack.config.js
module.exports = {
  entry: './index.js',
  output: {
    filename: 'bundle.[chunkhash].js' // → bundle.8e0d62a03.js
  }
};

अगर क्लाइंट को फ़ाइल भेजने के लिए आपको फ़ाइल का नाम चाहिए, तो HtmlWebpackPlugin या WebpackManifestPlugin का इस्तेमाल करें.

HtmlWebpackPlugin एक आसान है लेकिन यह कम सुविधाजनक तरीका है. कंपाइलेशन के दौरान, यह प्लग इन एक एचटीएमएल फ़ाइल जनरेट करता है. इसमें, कंपाइल किए गए सभी संसाधन शामिल होते हैं. अगर आपका सर्वर लॉजिक मुश्किल नहीं है, तो आपके लिए यह काफ़ी होना चाहिए:

<!-- index.html -->
<!DOCTYPE html>
<!-- ... -->
<script src="bundle.8e0d62a03.js"></script>

WebpackManifestPlugin ज़्यादा सुविधाजनक तरीका है. यह तरीका तब काम आता है, जब आपके सर्वर का हिस्सा जटिल हो. बिल्ड के दौरान, यह एक JSON फ़ाइल जनरेट करता है. इसमें हैश और फ़ाइल के नामों को हैश किए बिना, फ़ाइलों के नामों के बीच मैपिंग की जाती है. किस फ़ाइल के साथ काम करना है, यह जानने के लिए सर्वर पर इस JSON का इस्तेमाल करें:

// manifest.json
{
  "bundle.js": "bundle.8e0d62a03.js"
}

इसके बारे में और पढ़ें

डिपेंडेंसी और रनटाइम को एक अलग फ़ाइल में एक्सट्रैक्ट करें

डिपेंडेंसी

ऐप्लिकेशन की डिपेंडेंसी, असल ऐप्लिकेशन कोड की तुलना में कम बार बदलती हैं. अगर उन्हें किसी अलग फ़ाइल में ले जाया जाता है, तो ब्राउज़र उन्हें अलग-अलग कैश मेमोरी में सेव कर पाएगा. साथ ही, ऐप्लिकेशन कोड बदलने पर उन्हें दोबारा डाउनलोड नहीं करेगा.

डिपेंडेंसी को एक अलग ग्रुप में एक्सट्रैक्ट करने के लिए, तीन चरण पूरे करें:

  1. आउटपुट फ़ाइल के नाम को [name].[chunkname].js से बदलें:

    // webpack.config.js
    module.exports = {
      output: {
        // Before
        filename: 'bundle.[chunkhash].js',
        // After
        filename: '[name].[chunkhash].js'
      }
    };
    

    जब वेबपैक ऐप्लिकेशन को बनाता है, तो वह [name] को हिस्से के नाम से बदल देता है. अगर हम [name] वाला हिस्सा नहीं जोड़ते हैं, तो हमें हैश के हिसाब से हिस्सों के बीच अंतर करना होगा – जो कि काफ़ी मुश्किल है!

  2. entry फ़ील्ड को किसी ऑब्जेक्ट में बदलें:

    // webpack.config.js
    module.exports = {
      // Before
      entry: './index.js',
      // After
      entry: {
        main: './index.js'
      }
    };
    

    इस स्निपेट में, "मुख्य", किसी हिस्से का नाम है. इस नाम को पहले चरण से, [name] की जगह पर बदला जाएगा.

    अब तक, अगर ऐप्लिकेशन बनाया जाता है, तो इस हिस्से में पूरा ऐप्लिकेशन कोड शामिल होगा – ठीक वैसे ही, जैसे कि हमने ये चरण पूरे नहीं किए हों. हालांकि, यह एक सेकंड में बदल जाएगा.

  3. वेबपैक 4 में, अपने वेबपैक कॉन्फ़िगरेशन में optimization.splitChunks.chunks: 'all' विकल्प जोड़ें:

    // webpack.config.js (for webpack 4)
    module.exports = {
      optimization: {
        splitChunks: {
          chunks: 'all'
        }
      }
    };
    

    इस विकल्प की मदद से, कोड को स्मार्ट तरीके से बांटा जा सकता है. इसके साथ, अगर यह 30 केबी (छोटा करने और gzip से पहले) से बड़ा हो जाता है, तो webpack वेंडर कोड को एक्सट्रैक्ट करेगा. यह सामान्य कोड भी निकालेगा – यह तब काम आता है, जब आपका बिल्ड कई बंडल बनाता है (उदाहरण के लिए, अगर आप अपने ऐप्लिकेशन को रूट में बांटते हैं).

    वेबपैक 3 में, CommonsChunkPlugin को जोड़ें:

    // webpack.config.js (for webpack 3)
    module.exports = {
      plugins: [
        new webpack.optimize.CommonsChunkPlugin({
        // A name of the chunk that will include the dependencies.
        // This name is substituted in place of [name] from step 1
        name: 'vendor',
    
        // A function that determines which modules to include into this chunk
        minChunks: module => module.context && module.context.includes('node_modules'),
        })
      ]
    };
    

    यह प्लगिन उन सभी मॉड्यूल को लेता है जिनमें node_modules शामिल है. साथ ही, यह प्लगिन उन्हें vendor.[chunkhash].js नाम की अलग फ़ाइल में ले जाता है.

इन बदलावों के बाद, हर बिल्ड एक के बजाय दो फ़ाइलें जनरेट करेगा: main.[chunkhash].js और vendor.[chunkhash].js (वेबपैक 4 के लिए vendors~main.[chunkhash].js). वेबपैक 4 के मामले में, अगर डिपेंडेंसी कम है, तो हो सकता है कि वेंडर बंडल जनरेट न हो – और यह अच्छी बात है:

$ webpack
Hash: ac01483e8fec1fa70676
Version: webpack 3.8.1
Time: 3816ms
                        Asset      Size  Chunks             Chunk Names
 ./main.00bab6fd3100008a42b0.js   82 kB       0  [emitted]  main
./vendor.d9e134771799ecdf9483.js  47 kB       1  [emitted]  vendor

ब्राउज़र इन फ़ाइलों को अलग-अलग कैश मेमोरी में सेव करेगा. साथ ही, सिर्फ़ बदलने वाले कोड को फिर से डाउनलोड करेगा.

Webpack रनटाइम कोड

माफ़ करें, सिर्फ़ वेंडर कोड निकालना ही काफ़ी नहीं है. अगर ऐप्लिकेशन कोड में कुछ बदलाव करने की कोशिश की जाती है, तो:

// index.js
…
…

// E.g. add this:
console.log('Wat');

आपको दिखेगा कि vendor हैश भी बदल जाएगा:

                           Asset   Size  Chunks             Chunk Names
./vendor.d9e134771799ecdf9483.js  47 kB       1  [emitted]  vendor

                            Asset   Size  Chunks             Chunk Names
./vendor.e6ea4504d61a1cc1c60b.js  47 kB       1  [emitted]  vendor

ऐसा इसलिए होता है, क्योंकि मॉड्यूल कोड के अलावा वेबपैक बंडल में रनटाइम होता है. यह कोड का एक छोटा हिस्सा होता है, जो मॉड्यूल का एक्ज़ीक्यूशन मैनेज करता है. कोड को कई फ़ाइलों में बांटने पर, कोड के इस हिस्से में चंक आईडी और उससे जुड़ी फ़ाइलों के बीच मैपिंग शामिल होती है:

// vendor.e6ea4504d61a1cc1c60b.js
script.src = __webpack_require__.p + chunkId + "." + {
    "0": "2f2269c7f0a55a5c1871"
}[chunkId] + ".js";

Webpack इस रनटाइम को पिछली बार जनरेट किए गए हिस्से में शामिल करता है, जो कि हमारे मामले में vendor है. साथ ही, जब भी कोई सेगमेंट बदलता है, तो कोड का यह हिस्सा भी बदल जाता है. इससे पूरा vendor सेगमेंट बदल जाता है.

इसे हल करने के लिए, रनटाइम को किसी अलग फ़ाइल में ले जाएं. वेबपैक 4 में, ऐसा करने के लिए optimization.runtimeChunk विकल्प चालू किया जाता है:

// webpack.config.js (for webpack 4)
module.exports = {
  optimization: {
    runtimeChunk: true
  }
};

वेबपैक 3 में, CommonsChunkPlugin के साथ एक अतिरिक्त खाली हिस्सा बनाकर ऐसा करें:

// webpack.config.js (for webpack 3)
module.exports = {
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: module => module.context && module.context.includes('node_modules')
    }),
    // This plugin must come after the vendor one (because webpack
    // includes runtime into the last chunk)
    new webpack.optimize.CommonsChunkPlugin({
      name: 'runtime',
      // minChunks: Infinity means that no app modules
      // will be included into this chunk
      minChunks: Infinity
    })
  ]
};

इन बदलावों के बाद, हर बिल्ड तीन फ़ाइलें जनरेट करेगा:

$ webpack
Hash: ac01483e8fec1fa70676
Version: webpack 3.8.1
Time: 3816ms
                            Asset     Size  Chunks             Chunk Names
   ./main.00bab6fd3100008a42b0.js    82 kB       0  [emitted]  main
 ./vendor.26886caf15818fa82dfa.js    46 kB       1  [emitted]  vendor
./runtime.79f17c27b335abc7aaf4.js  1.45 kB       3  [emitted]  runtime

उन्हें index.html में उलटे क्रम में शामिल करें – और आपका काम हो गया:

<!-- index.html -->
<script src="./runtime.79f17c27b335abc7aaf4.js"></script>
<script src="./vendor.26886caf15818fa82dfa.js"></script>
<script src="./main.00bab6fd3100008a42b0.js"></script>

इसके बारे में और पढ़ें

अतिरिक्त एचटीटीपी अनुरोध को सेव करने के लिए, webpack रनटाइम को इनलाइन करें

चीज़ों को और बेहतर बनाने के लिए, वेबपैक रनटाइम को एचटीएमएल रिस्पॉन्स में इनलाइन करने की कोशिश करें. यानी, इसके बजाय:

<!-- index.html -->
<script src="./runtime.79f17c27b335abc7aaf4.js"></script>

यह करें:

<!-- index.html -->
<script>
!function(e){function n(r){if(t[r])return t[r].exports;…}} ([]);
</script>

रनटाइम छोटा होता है और इसे इनलाइन करने से आपको एचटीटीपी अनुरोध सेव करने में मदद मिलेगी (एचटीटीपी/1 के साथ बहुत ज़रूरी; एचटीटीपी/2 के साथ कम ज़रूरी है, लेकिन इसका असर हो सकता है).

आइए जानते हैं कि इसे कैसे किया जाए.

अगर आपने HtmlWebpackPlugin के साथ एचटीएमएल जनरेट किया है

अगर आपने एचटीएमएल फ़ाइल जनरेट करने के लिए HtmlWebpackPlugin का इस्तेमाल किया है, तो आपको InlineSourcePlugin की ज़रूरत होगी:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const InlineSourcePlugin = require('html-webpack-inline-source-plugin');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      inlineSource: 'runtime~.+\\.js',
    }),
    new InlineSourcePlugin()
  ]
};

अगर कस्टम सर्वर लॉजिक का इस्तेमाल करके एचटीएमएल जनरेट किया जाता है, तो

वेबपैक 4 के साथ:

  1. रनटाइम समूह का जनरेट किया गया नाम जानने के लिए, WebpackManifestPlugin जोड़ें:

    // webpack.config.js (for webpack 4)
    const ManifestPlugin = require('webpack-manifest-plugin');
    
    module.exports = {
      plugins: [
        new ManifestPlugin()
      ]
    };
    

    इस प्लग इन के साथ बिल्ड करने से एक फ़ाइल बन जाएगी जो इस तरह दिखेगी:

    // manifest.json
    {
      "runtime~main.js": "runtime~main.8e0d62a03.js"
    }
    
  2. रनटाइम समूह के कॉन्टेंट को आसान तरीके से इनलाइन करें. उदाहरण के लिए, Node.js और Express की मदद से:

    // server.js
    const fs = require('fs');
    const manifest = require('./manifest.json');
    const runtimeContent = fs.readFileSync(manifest['runtime~main.js'], 'utf-8');
    
    app.get('/', (req, res) => {
      res.send(`
        …
        <script>${runtimeContent}</script>
        …
      `);
    });
    

या webpack 3 के साथ:

  1. रनटाइम के नाम को स्टैटिक बनाने के लिए, filename तय करें:

    module.exports = {
      plugins: [
        new webpack.optimize.CommonsChunkPlugin({
          name: 'runtime',
          minChunks: Infinity,
          filename: 'runtime.js'
        })
      ]
    };
    
  2. runtime.js कॉन्टेंट को आसान तरीके से इनलाइन करें. उदाहरण के लिए, Node.js और Express की मदद से:

    // server.js
    const fs = require('fs');
    const runtimeContent = fs.readFileSync('./runtime.js', 'utf-8');
    
    app.get('/', (req, res) => {
      res.send(`
        …
        <script>${runtimeContent}</script>
        …
      `);
    });
    

लेज़ी-लोड कोड, जिसकी आपको अभी ज़रूरत नहीं है

कभी-कभी, किसी पेज पर कुछ ज़्यादा अहम हिस्से होते हैं:

  • अगर आपने YouTube पर कोई वीडियो पेज लोड किया है, तो आपके लिए टिप्पणियों से ज़्यादा वीडियो पर कोई ध्यान देना होगा. यहां टिप्पणियों से ज़्यादा अहम वीडियो है.
  • अगर आपने समाचार साइट पर कोई लेख खोला है, तो आपके लिए उस लेख के टेक्स्ट पर विज्ञापनों की तुलना में ज़्यादा ध्यान देने की ज़रूरत है. यहां टेक्स्ट, विज्ञापनों से ज़्यादा अहम है.

ऐसे मामलों में, शुरुआत में लोड होने वाले पेज की परफ़ॉर्मेंस को बेहतर बनाने के लिए, सबसे ज़रूरी कॉन्टेंट को पहले डाउनलोड करें और बाकी हिस्सों को बाद में लेज़ी लोड करें. इसके लिए, import() फ़ंक्शन और कोड-स्प्लिटिंग का इस्तेमाल करें:

// videoPlayer.js
export function renderVideoPlayer() { … }

// comments.js
export function renderComments() { … }

// index.js
import {renderVideoPlayer} from './videoPlayer';
renderVideoPlayer();

// …Custom event listener
onShowCommentsClick(() => {
  import('./comments').then((comments) => {
    comments.renderComments();
  });
});

import() से पता चलता है कि आपको किसी मॉड्यूल को डाइनैमिक तौर पर लोड करना है. जब वेबपैक import('./module.js') देखता है, तो यह इस मॉड्यूल को एक अलग हिस्से में ले जाता है:

$ webpack
Hash: 39b2a53cb4e73f0dc5b2
Version: webpack 3.8.1
Time: 4273ms
                            Asset     Size  Chunks             Chunk Names
      ./0.8ecaf182f5c85b7a8199.js  22.5 kB       0  [emitted]
   ./main.f7e53d8e13e9a2745d6d.js    60 kB       1  [emitted]  main
 ./vendor.4f14b6326a80f4752a98.js    46 kB       2  [emitted]  vendor
./runtime.79f17c27b335abc7aaf4.js  1.45 kB       3  [emitted]  runtime

और इसे सिर्फ़ तब डाउनलोड करता है, जब एक्ज़ीक्यूशन import() फ़ंक्शन तक पहुंच जाता है.

इससे main बंडल छोटा हो जाएगा, जिससे लोड होने में लगने वाला शुरुआती समय बेहतर होगा. इससे भी बेहतर तरीके से कैश मेमोरी में सेव किया जा सकेगा. अगर मुख्य हिस्से में कोड बदला जाता है, तो टिप्पणियों के समूह पर इसका कोई असर नहीं पड़ेगा.

इसके बारे में और पढ़ें

कोड को रास्तों और पेजों में बांटें

अगर आपके ऐप्लिकेशन में कई रूट या पेज हैं, लेकिन कोड वाली सिर्फ़ एक JS फ़ाइल है (एक main डेटा), तो हो सकता है कि हर अनुरोध पर ज़्यादा बाइट डेटा दिखाया जा रहा हो. उदाहरण के लिए, जब कोई उपयोगकर्ता आपकी साइट के किसी होम पेज पर जाता है:

WebFundamentals का होम पेज

उन्हें किसी दूसरे पेज पर मौजूद लेख को रेंडर करने के लिए, कोड को लोड करने की ज़रूरत नहीं होती. हालांकि, वे उस लेख को लोड कर देंगे. इसके अलावा, अगर उपयोगकर्ता हमेशा सिर्फ़ होम पेज पर जाता है और लेख के कोड में बदलाव किया जाता है, तो वेबपैक पूरा बंडल अमान्य कर देगा और उपयोगकर्ता को पूरा ऐप्लिकेशन फिर से डाउनलोड करना होगा.

अगर हम ऐप्लिकेशन को पेजों (या रूट, अगर यह एक पेज वाला ऐप्लिकेशन है) में बांटते हैं, तो उपयोगकर्ता सिर्फ़ काम का कोड डाउनलोड करेगा. साथ ही, ब्राउज़र ऐप्लिकेशन कोड को बेहतर तरीके से कैश मेमोरी में सेव करेगा: अगर होम पेज के कोड को बदला जाता है, तो वेबपैक सिर्फ़ उससे जुड़े डेटा को अमान्य कर देगा.

एक पेज वाले ऐप्लिकेशन के लिए

एक पेज वाले ऐप्लिकेशन को रूट के हिसाब से बांटने के लिए, import() का इस्तेमाल करें (“लेज़ी-लोड कोड जिस की आपको अभी ज़रूरत नहीं है” सेक्शन देखें). अगर किसी फ़्रेमवर्क का इस्तेमाल किया जाता है, तो हो सकता है कि इसके लिए पहले से ही एक समाधान मौजूद हो:

पारंपरिक कई पेज वाले ऐप्लिकेशन के लिए

पारंपरिक ऐप्लिकेशन को पेजों के हिसाब से बांटने के लिए, वेबपैक के एंट्री पॉइंट का इस्तेमाल करें. अगर आपके ऐप्लिकेशन में तीन तरह के पेज हैं: होम पेज, लेख वाला पेज, और उपयोगकर्ता खाता पेज, तो – में तीन तरह के पेज होने चाहिए:

// webpack.config.js
module.exports = {
  entry: {
    home: './src/Home/index.js',
    article: './src/Article/index.js',
    profile: './src/Profile/index.js'
  }
};

हर एंट्री फ़ाइल के लिए, वेबपैक एक अलग डिपेंडेंसी ट्री बनाएगा और एक बंडल जनरेट करेगा. इसमें सिर्फ़ वे मॉड्यूल शामिल होंगे जिनका इस्तेमाल उस एंट्री में किया जाएगा:

$ webpack
Hash: 318d7b8490a7382bf23b
Version: webpack 3.8.1
Time: 4273ms
                            Asset     Size  Chunks             Chunk Names
      ./0.8ecaf182f5c85b7a8199.js  22.5 kB       0  [emitted]
   ./home.91b9ed27366fe7e33d6a.js    18 kB       1  [emitted]  home
./article.87a128755b16ac3294fd.js    32 kB       2  [emitted]  article
./profile.de945dc02685f6166781.js    24 kB       3  [emitted]  profile
 ./vendor.4f14b6326a80f4752a98.js    46 kB       4  [emitted]  vendor
./runtime.318d7b8490a7382bf23b.js  1.45 kB       5  [emitted]  runtime

इसलिए, अगर लेख वाले पेज में सिर्फ़ Lodash का इस्तेमाल किया गया है, तो home और profile बंडल में इसे शामिल नहीं किया जाएगा. साथ ही, उपयोगकर्ता को होम पेज पर जाते समय यह लाइब्रेरी डाउनलोड नहीं करनी होगी.

हालांकि, अलग डिपेंडेंसी ट्री की अपनी कमियां होती हैं. अगर दो एंट्री पॉइंट Lodash का इस्तेमाल किया जाता है और आपने अपनी डिपेंडेंसी को वेंडर बंडल में नहीं भेजा है, तो दोनों एंट्री पॉइंट में Lodash की एक कॉपी होगी. इसे ठीक करने के लिए, वेबपैक 4 में अपने वेबपैक कॉन्फ़िगरेशन में optimization.splitChunks.chunks: 'all' विकल्प जोड़ें:

// webpack.config.js (for webpack 4)
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  }
};

इस विकल्प की मदद से, कोड को स्मार्ट तरीके से बांटा जा सकता है. इस विकल्प से, वेबपैक अपने-आप सामान्य कोड खोजेगा और उसे अलग-अलग फ़ाइलों में एक्सट्रैक्ट कर देगा.

इसके अलावा, वेबपैक 3 में CommonsChunkPlugin का इस्तेमाल करें – यह सामान्य डिपेंडेंसी को तय की गई नई फ़ाइल में ले जाएगा:

module.exports = {
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'common',
      minChunks: 2    // 2 is the default value
    })
  ]
};

सबसे अच्छा विकल्प पाने के लिए, minChunks वैल्यू का इस्तेमाल करें. आम तौर पर, आपको इसे छोटा रखना होता है, लेकिन अगर टुकड़ों की संख्या बढ़ती है, तो आपको इसे बढ़ाना होगा. जैसे, 3 हिस्सों के लिए, minChunks 2 हो सकता है, लेकिन 30 हिस्सों के लिए, यह 8 हो सकता है – अगर इसे 2 पर रखा जाता है, तो बहुत ज़्यादा मॉड्यूल समान फ़ाइल में आ जाएंगे, जिससे यह बहुत ज़्यादा बढ़ जाएगा.

इसके बारे में और पढ़ें

मॉड्यूल आईडी को ज़्यादा स्टेबल बनाएं

कोड बनाते समय, Webpack हर मॉड्यूल को एक आईडी असाइन करता है. बाद में, इन आईडी को बंडल में require()s में इस्तेमाल किया जाता है. आम तौर पर आपको मॉड्यूल पाथ से ठीक पहले बिल्ड आउटपुट में आईडी दिखते हैं:

$ webpack
Hash: df3474e4f76528e3bbc9
Version: webpack 3.8.1
Time: 2150ms
                           Asset      Size  Chunks             Chunk Names
      ./0.8ecaf182f5c85b7a8199.js  22.5 kB       0  [emitted]
   ./main.4e50a16675574df6a9e9.js    60 kB       1  [emitted]  main
 ./vendor.26886caf15818fa82dfa.js    46 kB       2  [emitted]  vendor
./runtime.79f17c27b335abc7aaf4.js  1.45 kB       3  [emitted]  runtime

↓ यहां

[0] ./index.js 29 kB {1} [built]
[2] (webpack)/buildin/global.js 488 bytes {2} [built]
[3] (webpack)/buildin/module.js 495 bytes {2} [built]
[4] ./comments.js 58 kB {0} [built]
[5] ./ads.js 74 kB {1} [built]
+ 1 hidden module

डिफ़ॉल्ट रूप से, आईडी को काउंटर का इस्तेमाल करके कैलकुलेट किया जाता है. उदाहरण के लिए, पहले मॉड्यूल का आईडी 0 है, दूसरे के लिए आईडी 1 है और ऐसे ही दूसरे मॉड्यूल का इस्तेमाल किया जाता है. इसमें समस्या यह है कि जब कोई नया मॉड्यूल जोड़ा जाता है, तो हो सकता है कि वह मॉड्यूल सूची के बीच में दिखे. इससे अगले मॉड्यूल के सभी आईडी बदल जाएंगे:

$ webpack
Hash: df3474e4f76528e3bbc9
Version: webpack 3.8.1
Time: 2150ms
                           Asset      Size  Chunks             Chunk Names
      ./0.5c82c0f337fcb22672b5.js    22 kB       0  [emitted]
   ./main.0c8b617dfc40c2827ae3.js    82 kB       1  [emitted]  main
 ./vendor.26886caf15818fa82dfa.js    46 kB       2  [emitted]  vendor
./runtime.79f17c27b335abc7aaf4.js  1.45 kB       3  [emitted]  runtime
   [0] ./index.js 29 kB {1} [built]
   [2] (webpack)/buildin/global.js 488 bytes {2} [built]
   [3] (webpack)/buildin/module.js 495 bytes {2} [built]

↓ हमने एक नया मॉड्यूल जोड़ा है...

[4] ./webPlayer.js 24 kB {1} [built]

↓ और देखें कि इसने क्या किया! comments.js का अब 4 के बजाय आईडी 5 है

[5] ./comments.js 58 kB {0} [built]

ads.js का अब 5 के बजाय आईडी 6 है

[6] ./ads.js 74 kB {1} [built]
       + 1 hidden module

यह उन सभी हिस्सों को अमान्य कर देता है जिनमें बदलाव किए गए आईडी वाले मॉड्यूल शामिल हैं या उन पर निर्भर करते हैं – भले ही उनका असल कोड न बदला हो. हमारे मामले में, 0 वाला डेटा (comments.js वाला डेटा) और main वाला डेटा अमान्य हो जाएगा. वहीं, main वाला डेटा ही अमान्य हो जाना चाहिए था.

इसे हल करने के लिए, HashedModuleIdsPlugin का इस्तेमाल करके मॉड्यूल आईडी को कैलकुलेट करने का तरीका बदलें. यह काउंटर-आधारित आईडी को मॉड्यूल पाथ के हैश से बदल देता है:

$ webpack
Hash: df3474e4f76528e3bbc9
Version: webpack 3.8.1
Time: 2150ms
                           Asset      Size  Chunks             Chunk Names
      ./0.6168aaac8461862eab7a.js  22.5 kB       0  [emitted]
   ./main.a2e49a279552980e3b91.js    60 kB       1  [emitted]  main
 ./vendor.ff9f7ea865884e6a84c8.js    46 kB       2  [emitted]  vendor
./runtime.25f5d0204e4f77fa57a1.js  1.45 kB       3  [emitted]  runtime

↓ यहां

[3IRH] ./index.js 29 kB {1} [built]
[DuR2] (webpack)/buildin/global.js 488 bytes {2} [built]
[JkW7] (webpack)/buildin/module.js 495 bytes {2} [built]
[LbCc] ./webPlayer.js 24 kB {1} [built]
[lebJ] ./comments.js 58 kB {0} [built]
[02Tr] ./ads.js 74 kB {1} [built]
    + 1 hidden module

इस तरीके से, मॉड्यूल का आईडी सिर्फ़ तब बदलता है, जब उस मॉड्यूल का नाम बदला जाता है या उसे दूसरी जगह ले जाया जाता है. नए मॉड्यूल का असर, दूसरे मॉड्यूल के आईडी पर नहीं पड़ेगा.

प्लग इन को चालू करने के लिए, उसे कॉन्फ़िगरेशन के plugins सेक्शन में जोड़ें:

// webpack.config.js
module.exports = {
  plugins: [
    new webpack.HashedModuleIdsPlugin()
  ]
};

इसके बारे में और पढ़ें

खास जानकारी

  • बंडल को कैश मेमोरी में सेव करें और इसका नाम बदलकर वर्शन के बीच अंतर करें
  • बंडल को ऐप्लिकेशन कोड, वेंडर कोड, और रनटाइम में बांटें
  • एचटीटीपी अनुरोध सेव करने के लिए रनटाइम को इनलाइन करें
  • import के साथ लेज़ी-लोड गैर-ज़रूरी कोड
  • गै़र-ज़रूरी कॉन्टेंट लोड होने से बचने के लिए, कोड को रास्तों/पेजों के हिसाब से बांटें