দীর্ঘমেয়াদী ক্যাশে ব্যবহার করুন

কিভাবে ওয়েবপ্যাক সম্পদ ক্যাশে সাহায্য করে

পরবর্তী জিনিস ( অ্যাপ সাইজ অপ্টিমাইজ করার পর যা অ্যাপ লোডিং টাইম উন্নত করে তা হল ক্যাশিং। অ্যাপের কিছু অংশ ক্লায়েন্টে রাখতে এটি ব্যবহার করুন এবং প্রতিবার সেগুলি পুনরায় ডাউনলোড করা এড়ান।

বান্ডিল সংস্করণ এবং ক্যাশে হেডার ব্যবহার করুন

ক্যাশে করার সাধারণ পদ্ধতি হল:

  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>
    

এই পদ্ধতিটি ব্রাউজারকে জেএস ফাইল ডাউনলোড করতে, এটি ক্যাশে করতে এবং ক্যাশড কপি ব্যবহার করতে বলে। ব্রাউজারটি শুধুমাত্র তখনই নেটওয়ার্কে আঘাত করবে যদি ফাইলের নাম পরিবর্তন হয় (অথবা যদি একটি বছর চলে যায়)।

ওয়েবপ্যাকের সাথে, আপনি একই কাজ করেন, তবে সংস্করণ নম্বরের পরিবর্তে, আপনি ফাইল হ্যাশ উল্লেখ করেন। ফাইলের নামের মধ্যে হ্যাশ অন্তর্ভুক্ত করতে, [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'
      }
    };
    

    এই স্নিপেটে, "প্রধান" একটি খণ্ডের নাম। এই নামটি ধাপ 1 থেকে [name] এর জায়গায় প্রতিস্থাপিত হবে।

    এখন পর্যন্ত, আপনি যদি অ্যাপটি তৈরি করেন, তাহলে এই অংশে পুরো অ্যাপ কোড অন্তর্ভুক্ত থাকবে – ঠিক যেমন আমরা এই পদক্ষেপগুলি করিনি। কিন্তু এটি এক সেকেন্ডে বদলে যাবে।

  3. ওয়েবপ্যাক 4 এ , আপনার ওয়েবপ্যাক কনফিগারেশনে optimization.splitChunks.chunks: 'all' বিকল্প যোগ করুন:

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

    এই বিকল্পটি স্মার্ট কোড বিভাজন সক্ষম করে। এটির সাহায্যে, ওয়েবপ্যাক 30 kB (মিনিফিকেশন এবং gzip-এর আগে) থেকে বড় হলে ভেন্ডর কোড বের করবে। এটি সাধারণ কোডটিও বের করবে – যদি আপনার বিল্ড বেশ কয়েকটি বান্ডিল তৈরি করে (যেমন যদি আপনি আপনার অ্যাপকে রুটে বিভক্ত করেন ) তাহলে এটি কার্যকর।

    ওয়েবপ্যাক 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

এই পরিবর্তনের পরে, প্রতিটি বিল্ড vendors~main.[chunkhash].js পরিবর্তে দুটি ফাইল তৈরি করবে: main.[chunkhash].js এবং vendor.[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

ব্রাউজার এই ফাইলগুলিকে আলাদাভাবে ক্যাশে করবে - এবং শুধুমাত্র পরিবর্তন হওয়া কোডটি পুনরায় ডাউনলোড করবে।

ওয়েবপ্যাক রানটাইম কোড

দুর্ভাগ্যবশত, শুধুমাত্র বিক্রেতা কোড নিষ্কাশন যথেষ্ট নয়। আপনি যদি অ্যাপ কোডে কিছু পরিবর্তন করার চেষ্টা করেন:

// 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";

ওয়েবপ্যাক এই রানটাইমকে শেষ জেনারেট করা অংশে অন্তর্ভুক্ত করে, যা আমাদের ক্ষেত্রে 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>

আরও পড়া

একটি অতিরিক্ত HTTP অনুরোধ সংরক্ষণ করতে ইনলাইন ওয়েবপ্যাক রানটাইম

জিনিসগুলিকে আরও ভাল করতে, HTML প্রতিক্রিয়াতে ওয়েবপ্যাক রানটাইম ইনলাইন করার চেষ্টা করুন৷ অর্থাৎ, এর পরিবর্তে:

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

এটি করুন:

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

রানটাইম ছোট, এবং এটি ইনলাইন করা আপনাকে একটি HTTP অনুরোধ সংরক্ষণ করতে সাহায্য করবে (HTTP/1 এর সাথে বেশ গুরুত্বপূর্ণ; HTTP/2 এর সাথে কম গুরুত্বপূর্ণ কিন্তু এখনও একটি প্রভাব ফেলতে পারে)।

এখানে এটা কিভাবে করতে হয়.

আপনি যদি HtmlWebpackPlugin দিয়ে HTML তৈরি করেন

আপনি যদি একটি HTML ফাইল তৈরি করতে 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()
  ]
};

আপনি যদি একটি কাস্টম সার্ভার লজিক ব্যবহার করে HTML তৈরি করেন

ওয়েবপ্যাক 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>
        …
      `);
    });
    

অথবা ওয়েবপ্যাক 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 এ রাখেন তবে অনেকগুলি মডিউল সাধারণ ফাইলে প্রবেশ করবে, এটিকে খুব বেশি স্ফীত করবে।

আরও পড়া

মডিউল আইডি আরও স্থিতিশীল করুন

কোড তৈরি করার সময়, ওয়েবপ্যাক প্রতিটি মডিউলকে একটি আইডি বরাদ্দ করে। পরবর্তীতে, এই আইডিগুলি বান্ডেলের ভিতরে 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-এর পরিবর্তে ID 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

এই পদ্ধতির সাথে, একটি মডিউলের ID শুধুমাত্র পরিবর্তন হয় যদি আপনি সেই মডিউলটির নাম পরিবর্তন করেন বা সরান। নতুন মডিউলগুলি অন্যান্য মডিউলের আইডিগুলিকে প্রভাবিত করবে না।

প্লাগইন সক্ষম করতে, এটি কনফিগারেশনের plugins বিভাগে যোগ করুন:

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

আরও পড়া

সারসংক্ষেপ

  • বান্ডিলটি ক্যাশে করুন এবং বান্ডিলের নাম পরিবর্তন করে সংস্করণগুলির মধ্যে পার্থক্য করুন
  • বান্ডেলটিকে অ্যাপ কোড, ভেন্ডর কোড এবং রানটাইমে বিভক্ত করুন
  • একটি HTTP অনুরোধ সংরক্ষণ করতে রানটাইম ইনলাইন করুন
  • অলস-লোড import সহ অ-গুরুত্বপূর্ণ কোড
  • অপ্রয়োজনীয় জিনিস লোড করা এড়াতে রুট/পৃষ্ঠা দ্বারা কোড বিভক্ত করুন
,

কিভাবে ওয়েবপ্যাক সম্পদ ক্যাশে সাহায্য করে

পরবর্তী জিনিস ( অ্যাপ সাইজ অপ্টিমাইজ করার পর যা অ্যাপ লোডিং টাইম উন্নত করে তা হল ক্যাশিং। অ্যাপের কিছু অংশ ক্লায়েন্টে রাখতে এটি ব্যবহার করুন এবং প্রতিবার সেগুলি পুনরায় ডাউনলোড করা এড়ান।

বান্ডিল সংস্করণ এবং ক্যাশে হেডার ব্যবহার করুন

ক্যাশে করার সাধারণ পদ্ধতি হল:

  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>
    

এই পদ্ধতিটি ব্রাউজারকে জেএস ফাইল ডাউনলোড করতে, এটি ক্যাশে করতে এবং ক্যাশড কপি ব্যবহার করতে বলে। ব্রাউজারটি শুধুমাত্র তখনই নেটওয়ার্কে আঘাত করবে যদি ফাইলের নাম পরিবর্তন হয় (অথবা যদি একটি বছর চলে যায়)।

ওয়েবপ্যাকের সাথে, আপনি একই কাজ করেন, তবে সংস্করণ নম্বরের পরিবর্তে, আপনি ফাইল হ্যাশ উল্লেখ করেন। ফাইলের নামের মধ্যে হ্যাশ অন্তর্ভুক্ত করতে, [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'
      }
    };
    

    এই স্নিপেটে, "প্রধান" একটি খণ্ডের নাম। এই নামটি ধাপ 1 থেকে [name] এর জায়গায় প্রতিস্থাপিত হবে।

    এখন পর্যন্ত, আপনি যদি অ্যাপটি তৈরি করেন, তাহলে এই অংশে পুরো অ্যাপ কোড অন্তর্ভুক্ত থাকবে – ঠিক যেমন আমরা এই পদক্ষেপগুলি করিনি। কিন্তু এটি এক সেকেন্ডে বদলে যাবে।

  3. ওয়েবপ্যাক 4 এ , আপনার ওয়েবপ্যাক কনফিগারেশনে optimization.splitChunks.chunks: 'all' বিকল্প যোগ করুন:

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

    এই বিকল্পটি স্মার্ট কোড বিভাজন সক্ষম করে। এটির সাহায্যে, ওয়েবপ্যাক 30 kB (মিনিফিকেশন এবং gzip-এর আগে) থেকে বড় হলে ভেন্ডর কোড বের করবে। এটি সাধারণ কোডটিও বের করবে – যদি আপনার বিল্ড বেশ কয়েকটি বান্ডিল তৈরি করে (যেমন যদি আপনি আপনার অ্যাপকে রুটে বিভক্ত করেন ) তাহলে এটি কার্যকর।

    ওয়েবপ্যাক 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

এই পরিবর্তনের পরে, প্রতিটি বিল্ড vendors~main.[chunkhash].js পরিবর্তে দুটি ফাইল তৈরি করবে: main.[chunkhash].js এবং vendor.[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

ব্রাউজার এই ফাইলগুলিকে আলাদাভাবে ক্যাশে করবে - এবং শুধুমাত্র পরিবর্তন হওয়া কোডটি পুনরায় ডাউনলোড করবে।

ওয়েবপ্যাক রানটাইম কোড

দুর্ভাগ্যবশত, শুধুমাত্র বিক্রেতা কোড নিষ্কাশন যথেষ্ট নয়। আপনি যদি অ্যাপ কোডে কিছু পরিবর্তন করার চেষ্টা করেন:

// 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";

ওয়েবপ্যাক এই রানটাইমকে শেষ জেনারেট করা অংশে অন্তর্ভুক্ত করে, যা আমাদের ক্ষেত্রে 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>

আরও পড়া

একটি অতিরিক্ত HTTP অনুরোধ সংরক্ষণ করতে ইনলাইন ওয়েবপ্যাক রানটাইম

জিনিসগুলিকে আরও ভাল করতে, HTML প্রতিক্রিয়াতে ওয়েবপ্যাক রানটাইম ইনলাইন করার চেষ্টা করুন৷ অর্থাৎ, এর পরিবর্তে:

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

এটি করুন:

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

রানটাইম ছোট, এবং এটি ইনলাইন করা আপনাকে একটি HTTP অনুরোধ সংরক্ষণ করতে সাহায্য করবে (HTTP/1 এর সাথে বেশ গুরুত্বপূর্ণ; HTTP/2 এর সাথে কম গুরুত্বপূর্ণ কিন্তু এখনও একটি প্রভাব ফেলতে পারে)।

এখানে এটা কিভাবে করতে হয়.

আপনি যদি HtmlWebpackPlugin দিয়ে HTML তৈরি করেন

আপনি যদি একটি HTML ফাইল তৈরি করতে 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()
  ]
};

আপনি যদি একটি কাস্টম সার্ভার লজিক ব্যবহার করে HTML তৈরি করেন

ওয়েবপ্যাক 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>
        …
      `);
    });
    

অথবা ওয়েবপ্যাক 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 এ রাখেন তবে অনেকগুলি মডিউল সাধারণ ফাইলে প্রবেশ করবে, এটিকে খুব বেশি স্ফীত করবে।

আরও পড়া

মডিউল আইডি আরও স্থিতিশীল করুন

কোড তৈরি করার সময়, ওয়েবপ্যাক প্রতিটি মডিউলকে একটি আইডি বরাদ্দ করে। পরবর্তীতে, এই আইডিগুলি বান্ডেলের ভিতরে 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-এর পরিবর্তে ID 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

এই পদ্ধতির সাথে, একটি মডিউলের ID শুধুমাত্র পরিবর্তন হয় যদি আপনি সেই মডিউলটির নাম পরিবর্তন করেন বা সরান। নতুন মডিউলগুলি অন্যান্য মডিউলের আইডিগুলিকে প্রভাবিত করবে না।

প্লাগইন সক্ষম করতে, এটি কনফিগারেশনের plugins বিভাগে যোগ করুন:

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

আরও পড়া

সারসংক্ষেপ

  • বান্ডিলটি ক্যাশে করুন এবং বান্ডিলের নাম পরিবর্তন করে সংস্করণগুলির মধ্যে পার্থক্য করুন
  • বান্ডেলটিকে অ্যাপ কোড, ভেন্ডর কোড এবং রানটাইমে বিভক্ত করুন
  • একটি HTTP অনুরোধ সংরক্ষণ করতে রানটাইম ইনলাইন করুন
  • অলস-লোড import সহ অ-গুরুত্বপূর্ণ কোড
  • অপ্রয়োজনীয় জিনিস লোড করা এড়াতে রুট/পৃষ্ঠা দ্বারা কোড বিভক্ত করুন
,

কিভাবে ওয়েবপ্যাক সম্পদ ক্যাশে সাহায্য করে

পরবর্তী জিনিস ( অ্যাপ সাইজ অপ্টিমাইজ করার পর যা অ্যাপ লোডিং টাইম উন্নত করে তা হল ক্যাশিং। অ্যাপের কিছু অংশ ক্লায়েন্টে রাখতে এটি ব্যবহার করুন এবং প্রতিবার সেগুলি পুনরায় ডাউনলোড করা এড়ান।

বান্ডিল সংস্করণ এবং ক্যাশে হেডার ব্যবহার করুন

ক্যাশে করার সাধারণ পদ্ধতি হল:

  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>
    

এই পদ্ধতিটি ব্রাউজারকে জেএস ফাইল ডাউনলোড করতে, এটি ক্যাশে করতে এবং ক্যাশড কপি ব্যবহার করতে বলে। ব্রাউজারটি শুধুমাত্র তখনই নেটওয়ার্কে আঘাত করবে যদি ফাইলের নাম পরিবর্তন হয় (অথবা যদি একটি বছর চলে যায়)।

ওয়েবপ্যাকের সাথে, আপনি একই কাজ করেন, তবে সংস্করণ নম্বরের পরিবর্তে, আপনি ফাইল হ্যাশ উল্লেখ করেন। ফাইলের নামের মধ্যে হ্যাশ অন্তর্ভুক্ত করতে, [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'
      }
    };
    

    এই স্নিপেটে, "প্রধান" একটি খণ্ডের নাম। এই নামটি ধাপ 1 থেকে [name] এর জায়গায় প্রতিস্থাপিত হবে।

    এখন পর্যন্ত, আপনি যদি অ্যাপটি তৈরি করেন, তাহলে এই অংশে পুরো অ্যাপ কোড অন্তর্ভুক্ত থাকবে – ঠিক যেমন আমরা এই পদক্ষেপগুলি করিনি। কিন্তু এটি এক সেকেন্ডে বদলে যাবে।

  3. ওয়েবপ্যাক 4 এ , আপনার ওয়েবপ্যাক কনফিগারেশনে optimization.splitChunks.chunks: 'all' বিকল্প যোগ করুন:

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

    এই বিকল্পটি স্মার্ট কোড বিভাজন সক্ষম করে। এটির সাহায্যে, ওয়েবপ্যাক 30 kB (মিনিফিকেশন এবং gzip-এর আগে) থেকে বড় হলে ভেন্ডর কোড বের করবে। এটি সাধারণ কোডটিও বের করবে – যদি আপনার বিল্ড বেশ কয়েকটি বান্ডিল তৈরি করে (যেমন যদি আপনি আপনার অ্যাপকে রুটে বিভক্ত করেন ) তাহলে এটি কার্যকর।

    ওয়েবপ্যাক 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

এই পরিবর্তনের পরে, প্রতিটি বিল্ড vendors~main.[chunkhash].js পরিবর্তে দুটি ফাইল তৈরি করবে: main.[chunkhash].js এবং vendor.[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

ব্রাউজার এই ফাইলগুলিকে আলাদাভাবে ক্যাশে করবে - এবং শুধুমাত্র পরিবর্তন হওয়া কোডটি পুনরায় ডাউনলোড করবে।

ওয়েবপ্যাক রানটাইম কোড

দুর্ভাগ্যবশত, শুধুমাত্র বিক্রেতা কোড নিষ্কাশন যথেষ্ট নয়। আপনি যদি অ্যাপ কোডে কিছু পরিবর্তন করার চেষ্টা করেন:

// 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";

ওয়েবপ্যাক এই রানটাইমকে শেষ জেনারেট করা অংশে অন্তর্ভুক্ত করে, যা আমাদের ক্ষেত্রে 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>

আরও পড়া

একটি অতিরিক্ত HTTP অনুরোধ সংরক্ষণ করতে ইনলাইন ওয়েবপ্যাক রানটাইম

জিনিসগুলিকে আরও ভাল করতে, HTML প্রতিক্রিয়াতে ওয়েবপ্যাক রানটাইম ইনলাইন করার চেষ্টা করুন৷ অর্থাৎ, এর পরিবর্তে:

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

এটি করুন:

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

রানটাইম ছোট, এবং এটি ইনলাইন করা আপনাকে একটি HTTP অনুরোধ সংরক্ষণ করতে সাহায্য করবে (HTTP/1 এর সাথে বেশ গুরুত্বপূর্ণ; HTTP/2 এর সাথে কম গুরুত্বপূর্ণ কিন্তু এখনও একটি প্রভাব ফেলতে পারে)।

এখানে এটা কিভাবে করতে হয়.

আপনি যদি HtmlWebpackPlugin দিয়ে HTML তৈরি করেন

আপনি যদি একটি HTML ফাইল তৈরি করতে 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()
  ]
};

আপনি যদি একটি কাস্টম সার্ভার লজিক ব্যবহার করে HTML তৈরি করেন

ওয়েবপ্যাক 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>
        …
      `);
    });
    

অথবা ওয়েবপ্যাক 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() ব্যবহার করুন ( "অলস-লোড কোড যা আপনার এখনই প্রয়োজন নেই" বিভাগটি দেখুন)। আপনি যদি কোনও কাঠামো ব্যবহার করেন তবে এর জন্য এটির একটি বিদ্যমান সমাধান থাকতে পারে:

Traditional তিহ্যবাহী মাল্টি-পৃষ্ঠা অ্যাপ্লিকেশনগুলির জন্য

পৃষ্ঠাগুলি দ্বারা traditional তিহ্যবাহী অ্যাপ্লিকেশনগুলি বিভক্ত করতে, ওয়েবপ্যাকের প্রবেশের পয়েন্টগুলি ব্যবহার করুন। যদি আপনার অ্যাপ্লিকেশনটিতে তিন ধরণের পৃষ্ঠা থাকে: হোম পৃষ্ঠা, নিবন্ধ পৃষ্ঠা এবং ব্যবহারকারী অ্যাকাউন্ট পৃষ্ঠা - এটির তিনটি এন্ট্রি থাকা উচিত:

// 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

সুতরাং, যদি কেবল নিবন্ধ পৃষ্ঠাটি লোডাস ব্যবহার করে, home এবং profile বান্ডিলগুলি এটি অন্তর্ভুক্ত করে না - এবং হোম পৃষ্ঠাটি দেখার সময় ব্যবহারকারীকে এই গ্রন্থাগারটি ডাউনলোড করতে হবে না।

পৃথক নির্ভরতা গাছের যদিও তাদের ত্রুটি রয়েছে। যদি দুটি এন্ট্রি পয়েন্ট লোডাশ ব্যবহার করে এবং আপনি আপনার নির্ভরতাগুলিকে কোনও বিক্রেতার বান্ডেলে স্থানান্তরিত না করেন তবে উভয় এন্ট্রি পয়েন্টে লোডশের একটি অনুলিপি অন্তর্ভুক্ত থাকবে। এটি সমাধান করার জন্য, ওয়েবপ্যাক 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 এ রাখেন তবে অনেকগুলি মডিউল সাধারণ ফাইলটিতে প্রবেশ করবে, এটি খুব বেশি স্ফীত করে।

আরও পড়া

মডিউল আইডি আরও স্থিতিশীল করুন

কোডটি তৈরি করার সময়, ওয়েবপ্যাক প্রতিটি মডিউলকে একটি আইডি বরাদ্দ করে। পরে, এই আইডিগুলি বান্ডিলের অভ্যন্তরে require() ব্যবহার করা হয়। আপনি সাধারণত মডিউল পাথের ঠিক আগে বিল্ড আউটপুটে আইডি দেখতে পান:

$ 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 সহ অলস-লোড অ-সমালোচনামূলক কোড
  • অপ্রয়োজনীয় স্টাফ লোড এড়াতে রুট/পৃষ্ঠাগুলি দ্বারা কোড বিভক্ত করুন
,

কীভাবে ওয়েবপ্যাক সম্পদ ক্যাশে সহায়তা করে

পরবর্তী জিনিস ( অ্যাপের আকারটি অপ্টিমাইজ করার পরে অ্যাপ্লিকেশন লোডিংয়ের সময়টি উন্নত করে তা হ'ল ক্যাশে।

বান্ডিল সংস্করণ এবং ক্যাশে শিরোনাম ব্যবহার করুন

ক্যাচিং করার সাধারণ পদ্ধতিটি হ'ল:

  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>
    

এই পদ্ধতিটি ব্রাউজারটিকে জেএস ফাইলটি ডাউনলোড করতে, এটি ক্যাশে এবং ক্যাশেড অনুলিপি ব্যবহার করতে বলে। ব্রাউজারটি কেবল তখনই নেটওয়ার্কে আঘাত করবে যদি ফাইলের নাম পরিবর্তন হয় (বা যদি এক বছর কেটে যায়)।

ওয়েবপ্যাকের সাহায্যে আপনিও একই কাজ করেন তবে সংস্করণ নম্বরের পরিবর্তে আপনি ফাইলটি হ্যাশ নির্দিষ্ট করেন। ফাইলের নামটিতে হ্যাশকে অন্তর্ভুক্ত করতে, [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 একটি আরও নমনীয় পদ্ধতির যা আপনার যদি জটিল সার্ভার অংশ থাকে তবে কার্যকর। বিল্ড চলাকালীন, এটি হ্যাশ ছাড়াই ফাইলের নাম এবং হ্যাশ সহ ফাইলের নামগুলির মধ্যে একটি ম্যাপিং সহ একটি জেএসএন ফাইল তৈরি করে। কোন ফাইলটির সাথে কাজ করবেন তা জানতে সার্ভারে এই জসনটি ব্যবহার করুন:

// 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'
      }
    };
    

    এই স্নিপেটে, "মেইন" একটি অংশের নাম। এই নামটি পদক্ষেপ 1 থেকে [name] এর জায়গায় প্রতিস্থাপিত হবে।

    এতক্ষণে, আপনি যদি অ্যাপটি তৈরি করেন তবে এই অংশটি পুরো অ্যাপ্লিকেশন কোডটি অন্তর্ভুক্ত করবে - ঠিক যেমন আমরা এই পদক্ষেপগুলি করিনি। তবে এটি এক সেকেন্ডে পরিবর্তিত হবে।

  3. ওয়েবপ্যাক 4 এ , optimization.splitChunks.chunks: 'all' বিকল্প:

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

    এই বিকল্পটি স্মার্ট কোড বিভাজন সক্ষম করে। এটির সাহায্যে ওয়েবপ্যাকটি 30 কেবি (মিনিফিকেশন এবং জিজেডিপের আগে) এর চেয়ে বড় হলে বিক্রেতার কোডটি বের করে দেবে। এটি সাধারণ কোডটিও বের করে দেবে - যদি আপনার বিল্ডটি বেশ কয়েকটি বান্ডিল উত্পাদন করে (যেমন আপনি যদি আপনার অ্যাপ্লিকেশনটিকে রুটে বিভক্ত করেন ) তবে এটি কার্যকর।

    ওয়েবপ্যাক 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

এই পরিবর্তনের পরে, প্রতিটি বিল্ড vendors~main.[chunkhash].js পরিবর্তে দুটি ফাইল তৈরি করবে: main.[chunkhash].js vendor.[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

ব্রাউজারটি এই ফাইলগুলি আলাদাভাবে ক্যাশে করবে - এবং কেবলমাত্র কোডগুলি পুনরায় করা কোড যা পরিবর্তিত হয়।

ওয়েবপ্যাক রানটাইম কোড

দুর্ভাগ্যক্রমে, কেবল বিক্রেতার কোডটি বের করা যথেষ্ট নয়। আপনি যদি অ্যাপ কোডে কিছু পরিবর্তন করার চেষ্টা করেন:

// 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";

ওয়েবপ্যাকটি এই রানটাইমকে সর্বশেষ উত্পাদিত অংশে অন্তর্ভুক্ত করে, যা আমাদের ক্ষেত্রে vendor । এবং প্রতিবার কোনও অংশ পরিবর্তনের সময়, কোডের এই টুকরোটিও পরিবর্তিত হয়, যার ফলে পুরো vendor অংশটি পরিবর্তন হয়।

এটি সমাধান করার জন্য, আসুন রানটাইমকে একটি পৃথক ফাইলে স্থানান্তরিত করুন। ওয়েবপ্যাক 4 এ, এটি optimization.runtimeChunk সক্ষম করে অর্জন করা হয়েছে 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>

আরও পড়া

অতিরিক্ত এইচটিটিপি অনুরোধ সংরক্ষণ করতে ইনলাইন ওয়েবপ্যাক রানটাইম

বিষয়গুলিকে আরও উন্নত করতে, এইচটিএমএল প্রতিক্রিয়াতে ওয়েবপ্যাক রানটাইম ইনলাইন করার চেষ্টা করুন। অর্থাত্ এর পরিবর্তে:

<!-- 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 ব্যবহার করেন তবে ইনলাইনসোর্সপ্লাগিন আপনার প্রয়োজনীয় সমস্ত কিছু:

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. একটি সুবিধাজনক উপায়ে রানটাইম অংশের সামগ্রীটি ইনলাইন করুন। যেমন নোড.জেএস এবং এক্সপ্রেস সহ:

    // 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>
        …
      `);
    });
    

বা ওয়েবপ্যাক 3 সহ:

  1. filename নির্দিষ্ট করে রানটাইমের নাম স্থির করুন:

    module.exports = {
      plugins: [
        new webpack.optimize.CommonsChunkPlugin({
          name: 'runtime',
          minChunks: Infinity,
          filename: 'runtime.js'
        })
      ]
    };
    
  2. একটি সুবিধাজনক উপায়ে runtime.js সামগ্রী ইনলাইন করুন। যেমন নোড.জেএস এবং এক্সপ্রেস সহ:

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

অলস-লোড কোড যা আপনার এখনই দরকার নেই

কখনও কখনও, একটি পৃষ্ঠায় আরও কম গুরুত্বপূর্ণ অংশ থাকে:

  • আপনি যদি ইউটিউবে কোনও ভিডিও পৃষ্ঠা লোড করেন তবে আপনি মন্তব্যগুলির চেয়ে ভিডিও সম্পর্কে বেশি যত্নশীল। এখানে, ভিডিওটি মন্তব্যের চেয়ে বেশি গুরুত্বপূর্ণ।
  • আপনি যদি কোনও নিউজ সাইটে কোনও নিবন্ধ খোলেন তবে আপনি বিজ্ঞাপনগুলির চেয়ে নিবন্ধের পাঠ্য সম্পর্কে আরও যত্নশীল। এখানে, পাঠ্য বিজ্ঞাপনের চেয়ে গুরুত্বপূর্ণ।

এই জাতীয় ক্ষেত্রে, প্রথমে কেবলমাত্র সবচেয়ে গুরুত্বপূর্ণ স্টাফ ডাউনলোড করে প্রাথমিক লোডিং পারফরম্যান্স উন্নত করুন এবং পরে বাকী অংশগুলি পরে অলস লোড করে। এর জন্য 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 বান্ডিলটিকে আরও ছোট করে তুলবে। আরও বেশি, এটি ক্যাচিংয়ের উন্নতি করবে - আপনি যদি মূল অংশে কোডটি পরিবর্তন করেন তবে মন্তব্যগুলি ক্ষতিগ্রস্থ হবে না।

আরও পড়া

কোডটি রুট এবং পৃষ্ঠাগুলিতে বিভক্ত করুন

যদি আপনার অ্যাপ্লিকেশনটিতে একাধিক রুট বা পৃষ্ঠা থাকে তবে কোড সহ কেবলমাত্র একটি জেএস ফাইল রয়েছে (একটি একক main অংশ), সম্ভবত আপনি প্রতিটি অনুরোধে অতিরিক্ত বাইট পরিবেশন করছেন। উদাহরণস্বরূপ, যখন কোনও ব্যবহারকারী আপনার সাইটের কোনও হোম পৃষ্ঠা পরিদর্শন করেন:

একটি ওয়েব ফান্ডামেন্টাল হোম পৃষ্ঠা

অন্য কোনও পৃষ্ঠায় থাকা কোনও নিবন্ধ রেন্ডার করার জন্য তাদের কোডটি লোড করার দরকার নেই - তবে তারা এটি লোড করবে। তদুপরি, যদি ব্যবহারকারী সর্বদা কেবল হোম পৃষ্ঠায় যান এবং আপনি নিবন্ধ কোডটিতে পরিবর্তন করেন তবে ওয়েবপ্যাক পুরো বান্ডিলটি অকার্যকর করবে-এবং ব্যবহারকারীকে পুরো অ্যাপটি পুনরায় ডাউনলোড করতে হবে।

যদি আমরা অ্যাপটিকে পৃষ্ঠাগুলিতে বিভক্ত করি (বা রুটগুলি, যদি এটি একটি একক পৃষ্ঠার অ্যাপ্লিকেশন হয়) তবে ব্যবহারকারী কেবল প্রাসঙ্গিক কোডটি ডাউনলোড করবেন। এছাড়াও, ব্রাউজারটি অ্যাপ্লিকেশন কোডটি আরও ভালভাবে ক্যাশে করবে: আপনি যদি হোম পৃষ্ঠা কোডটি পরিবর্তন করেন তবে ওয়েবপ্যাকটি কেবল সংশ্লিষ্ট অংশকে অকার্যকর করবে।

একক পৃষ্ঠার অ্যাপ্লিকেশনগুলির জন্য

রুটগুলি দ্বারা একক পৃষ্ঠার অ্যাপ্লিকেশনগুলি বিভক্ত করতে, import() ব্যবহার করুন ( "অলস-লোড কোড যা আপনার এখনই প্রয়োজন নেই" বিভাগটি দেখুন)। আপনি যদি কোনও কাঠামো ব্যবহার করেন তবে এর জন্য এটির একটি বিদ্যমান সমাধান থাকতে পারে:

Traditional তিহ্যবাহী মাল্টি-পৃষ্ঠা অ্যাপ্লিকেশনগুলির জন্য

পৃষ্ঠাগুলি দ্বারা traditional তিহ্যবাহী অ্যাপ্লিকেশনগুলি বিভক্ত করতে, ওয়েবপ্যাকের প্রবেশের পয়েন্টগুলি ব্যবহার করুন। যদি আপনার অ্যাপ্লিকেশনটিতে তিন ধরণের পৃষ্ঠা থাকে: হোম পৃষ্ঠা, নিবন্ধ পৃষ্ঠা এবং ব্যবহারকারী অ্যাকাউন্ট পৃষ্ঠা - এটির তিনটি এন্ট্রি থাকা উচিত:

// 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

সুতরাং, যদি কেবল নিবন্ধ পৃষ্ঠাটি লোডাস ব্যবহার করে, home এবং profile বান্ডিলগুলি এটি অন্তর্ভুক্ত করে না - এবং হোম পৃষ্ঠাটি দেখার সময় ব্যবহারকারীকে এই গ্রন্থাগারটি ডাউনলোড করতে হবে না।

পৃথক নির্ভরতা গাছের যদিও তাদের ত্রুটি রয়েছে। যদি দুটি এন্ট্রি পয়েন্ট লোডাশ ব্যবহার করে এবং আপনি আপনার নির্ভরতাগুলিকে কোনও বিক্রেতার বান্ডেলে স্থানান্তরিত না করেন তবে উভয় এন্ট্রি পয়েন্টে লোডশের একটি অনুলিপি অন্তর্ভুক্ত থাকবে। এটি সমাধান করার জন্য, ওয়েবপ্যাক 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 এ রাখেন তবে অনেকগুলি মডিউল সাধারণ ফাইলটিতে প্রবেশ করবে, এটি খুব বেশি স্ফীত করে।

আরও পড়া

মডিউল আইডি আরও স্থিতিশীল করুন

কোডটি তৈরি করার সময়, ওয়েবপ্যাক প্রতিটি মডিউলকে একটি আইডি বরাদ্দ করে। পরে, এই আইডিগুলি বান্ডিলের অভ্যন্তরে require() ব্যবহার করা হয়। আপনি সাধারণত মডিউল পাথের ঠিক আগে বিল্ড আউটপুটে আইডি দেখতে পান:

$ 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 সহ অলস-লোড অ-সমালোচনামূলক কোড
  • অপ্রয়োজনীয় স্টাফ লোড এড়াতে রুট/পৃষ্ঠাগুলি দ্বারা কোড বিভক্ত করুন