কীভাবে বিক্রেতাদের স্ক্রিপ্টগুলি আলাদাভাবে বান্ডেল করবেন এবং ওয়েবপ্যাকের সাথে প্রয়োজনীয়ভাবে সেগুলি কীভাবে প্রয়োজন?


173

আমি এমন কিছু করার চেষ্টা করছি যা আমি বিশ্বাস করি যে এটি সম্ভব হওয়া উচিত, তবে কেবল ওয়েবপ্যাক ডকুমেন্টেশন থেকে এটি কীভাবে করা যায় তা আমি সত্যিই বুঝতে পারি না।

আমি একটি জাভাস্ক্রিপ্ট লাইব্রেরি লিখছি বেশ কয়েকটি মডিউল যা একে অপরের উপর নির্ভর করতে পারে। তার উপরে, jQuery সমস্ত মডিউল দ্বারা ব্যবহৃত হয় এবং তাদের কিছুতে jQuery প্লাগইন প্রয়োজন হতে পারে। এই লাইব্রেরিটি বেশ কয়েকটি বিভিন্ন ওয়েবসাইটে ব্যবহৃত হবে যার জন্য কিছু বা সমস্ত মডিউলের প্রয়োজন হতে পারে।

আমার মডিউলগুলির মধ্যে নির্ভরতা নির্ধারণ করা খুব সহজ ছিল, তবে তাদের তৃতীয় পক্ষের নির্ভরতা নির্ধারণ করা আমার প্রত্যাশার পরে আরও শক্ত বলে মনে হচ্ছে।

আমি কী অর্জন করতে চাই : প্রতিটি অ্যাপ্লিকেশনের জন্য আমি দুটি বান্ডিল ফাইল রাখতে চাই একটি তৃতীয় পক্ষের নির্ভরতা এবং অন্যটি আমার লাইব্রেরি থেকে প্রয়োজনীয় মডিউল সহ।

উদাহরণ : আসুন কল্পনা করুন যে আমার লাইব্রেরিতে নিম্নলিখিত মডিউল রয়েছে:

  • একটি (প্রয়োজনীয়: jquery, jquery.plugin1)
  • খ (প্রয়োজনীয়: jquery, ক)
  • সি (প্রয়োজনীয়: জ্যাকুয়ারি, জ্যাকুয়ারি.উই, এ, বি)
  • d (প্রয়োজনীয়: jquery, jquery.plugin2, a)

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

  • বিক্রেতার বান্ডেল : jquery, jquery.plugin1 এবং jquery.ui সহ;
  • ওয়েবসাইট বান্ডেল : মডিউল ক, খ এবং সি সহ;

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

এটি সম্ভব বলে ধরে নেওয়া, এই ক্ষেত্রে ওয়েবপ্যাক কনফিগারেশন ফাইলের উদাহরণ কী হবে? আমি আমার কনফিগারেশন ফাইলে লোডার, এক্সটার্নাল এবং প্লাগইনগুলির বেশ কয়েকটি সংমিশ্রণ চেষ্টা করেছি, তবে তারা আসলে কী করছে এবং কোনটি আমার ব্যবহার করা উচিত তা সত্যিই পাই না। ধন্যবাদ!


2
আপনার সমাধান কি? আপনি একটি শালীন পদ্ধতির সন্ধান করতে পরিচালিত? তা হলে পোস্ট করুন! ধন্যবাদ
গীকনগ্যাজেটগুলি

উত্তর:


140

আমার ওয়েবপ্যাক.কনফিগ.জে (সংস্করণ 1,2,3) ফাইলে আছে

function isExternal(module) {
  var context = module.context;

  if (typeof context !== 'string') {
    return false;
  }

  return context.indexOf('node_modules') !== -1;
}

আমার প্লাগিন অ্যারে

plugins: [
  new CommonsChunkPlugin({
    name: 'vendors',
    minChunks: function(module) {
      return isExternal(module);
    }
  }),
  // Other plugins
]

এখন আমার কাছে একটি ফাইল রয়েছে যা কেবলমাত্র একটি ফাইল হিসাবে তৃতীয় পক্ষের libs যুক্ত করে।

আপনি যদি আরও বিক্রেতাদের পেতে চান তবে যেখানে আপনি আপনার বিক্রেতাদের এবং এন্ট্রি পয়েন্ট ফাইলগুলি পৃথক করুন:

plugins: [
  new CommonsChunkPlugin({
    name: 'common',
    minChunks: function(module, count) {
      return !isExternal(module) && count >= 2; // adjustable
    }
  }),
  new CommonsChunkPlugin({
    name: 'vendors',
    chunks: ['common'],
    // or if you have an key value object for your entries
    // chunks: Object.keys(entry).concat('common')
    minChunks: function(module) {
      return isExternal(module);
    }
  })
]

নোট করুন যে প্লাগইনগুলির ক্রমটি অনেক গুরুত্বপূর্ণ।

এছাড়াও, এটি সংস্করণ ৪-এ পরিবর্তিত হতে চলেছে যখন এটি সরকারী হয়, আমি এই উত্তরটি আপডেট করি।

আপডেট: উইন্ডোজ ব্যবহারকারীদের জন্য অনুসন্ধানের তালিকা পরিবর্তন করুন


1
আমি আমার প্রশ্ন পোস্ট করার সময় এটি ইতিমধ্যে সম্ভব ছিল কিনা তা জানি না, তবে আমি যা খুঁজছিলাম তা এটিই ছিল। এই সমাধানের সাথে আমার আর আমার বিক্রেতা প্রবেশের অংশটি নির্দিষ্ট করার দরকার নেই। অনেক ধন্যবাদ!
বেনসাম্পাইও

1
isExternalমধ্যে minChunksআমার দিন। এটি কীভাবে নথিভুক্ত হয় না? ডাউনসাইডস আছে?
ওয়েসলি শ্লিউমার ডি গেইস

থেক্স, তবে উইন্ডোজ প্যাথগুলির জন্য ব্যবহারকারীরউকেস্ট.ইন্ডেক্সঅফ ('/ নোড_মডিউলস /') ব্যবহারকারীর রিকোয়েস্ট.ইন্ডেক্সঅফ ('নোড_মডিউলস') এ পরিবর্তন করুন
কিনজিরো

@ ওয়েসলি স্ক্লিউমারডেজিও এটি নথিভুক্ত হয়েছে তবে উদাহরণ ছাড়াই options.minChunks (number|Infinity|function(module, count) -> boolean):আমি এখনও কোনও খারাপ দিক দেখছি না।
রাফায়েল ডি লিওন

2
লোডারগুলি ব্যবহার করার সময় এটি কাজ করবে না, কারণ লোডারটির পথটিও হবে module.userRequest(এবং সম্ভবত লোডারটি এতে রয়েছে node_modules)। আমার কোড isExternal():return typeof module.userRequest === 'string' && !!module.userRequest.split('!').pop().match(/(node_modules|bower_components|libraries)/);
সিডিউথ

54

আমি নিশ্চিত যে আমি আপনার সমস্যাটি পুরোপুরি বুঝতে পেরেছি কিনা তবে আমি সম্প্রতি একইরকম সমস্যা হওয়ায় আমি আপনাকে সাহায্য করার চেষ্টা করব।

বিক্রেতার বান্ডিল

এর জন্য আপনার CommonsChunkPlugin ব্যবহার করা উচিত । কনফিগারেশনে আপনি খণ্ডের নাম (উদাহরণস্বরূপ vendor), এবং ফাইলের নাম উল্লেখ করবেন যা উত্পন্ন হবে ( vendor.js)।

new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.js", Infinity),

এখন গুরুত্বপূর্ণ অংশ, আপনাকে এখন উল্লেখ করতে হবে এর vendorলাইব্রেরিটি কী বোঝায় এবং আপনি এন্ট্রি বিভাগে এটি করেন। সদ্য ঘোষিত খণ্ডের নাম হিসাবে একই নামের সাথে প্রবেশের তালিকায় আরও একটি আইটেম (এই ক্ষেত্রে 'বিক্রেতা')। সেই প্রবেশের মানটি সেই সমস্ত মডিউলগুলির তালিকা হওয়া উচিত যা আপনি vendorবান্ডলে যেতে চান । আপনার ক্ষেত্রে এটির মতো দেখতে হবে:

entry: {
    app: 'entry.js',
    vendor: ['jquery', 'jquery.plugin1']
}

গ্লোবাল হিসাবে JQuery

একই সমস্যা ছিল এবং এটি ProvidePlugin দিয়ে সমাধান করেছে । এখানে আপনি গ্লোবাল অবজেক্টের সংজ্ঞা দিচ্ছেন না তবে মডিউলগুলিতে এক ধরণের শর্টকাট করছেন। যেমন আপনি এটির মতো কনফিগার করতে পারেন:

new webpack.ProvidePlugin({
    $: "jquery"
})

এবং এখন আপনি কেবল $আপনার কোডের যে কোনও জায়গায় ব্যবহার করতে পারেন - ওয়েবপ্যাক স্বয়ংক্রিয়ভাবে এটিকে রূপান্তর করবে

require('jquery')

আমি আশা করি এটি সাহায্য করেছে আপনি এখানে থাকা আমার ওয়েবপ্যাক কনফিগারেশন ফাইলটিও দেখতে পারেন

আমি ওয়েবপ্যাকটি পছন্দ করি, তবে আমি একমত যে ডকুমেন্টেশনটি বিশ্বের সেরাতমটি নয় ... তবে আরে .. মানুষ শুরুতে কৌণিক ডকুমেন্টেশন সম্পর্কে একই কথা বলেছিল :)


সম্পাদনা:

এন্ট্রিপয়েন্ট-নির্দিষ্ট বিক্রেতার অংশগুলি পেতে কেবল একাধিকবার CommonsChunkPlugins ব্যবহার করুন:

new webpack.optimize.CommonsChunkPlugin("vendor-page1", "vendor-page1.js", Infinity),
new webpack.optimize.CommonsChunkPlugin("vendor-page2", "vendor-page2.js", Infinity),

এবং তারপরে বিভিন্ন ফাইলের জন্য বিভিন্ন বহিরাগত গ্রন্থাগার ঘোষণা করুন:

entry: {
    page1: ['entry.js'],
    page2: ['entry2.js'],
    "vendor-page1": [
        'lodash'
    ],
    "vendor-page2": [
        'jquery'
    ]
},

যদি কিছু লাইব্রেরি এন্ট্রি পয়েন্টগুলির মধ্যে (এবং তাদের বেশিরভাগের জন্য) ওভারল্যাপ করে থাকে তবে আপনি এগুলি একই প্লাগইন ব্যবহার করে বিভিন্ন কনফিগারেশনের সাহায্যে সাধারণ ফাইলে বের করতে পারবেন। এই উদাহরণটি দেখুন ।


আপনার উত্তরের জন্য আপনাকে অনেক ধন্যবাদ। এটি আমি এখনও অবধি দেখেছি সেরা পন্থা কিন্তু দুর্ভাগ্যক্রমে এটি এখনও আমার সমস্যার সমাধান করে না ... আমি আপনার উদাহরণটি পরীক্ষা করেছি এবং বিক্রেতার.জেএস ফাইলটিতে এখনও 'জ্যাকুয়ারি' এবং 'জ্যাকুয়ের.প্লাগিন 1' থেকে সমস্ত কোড থাকবে যদিও এগুলি আমার কোনও মডিউল দ্বারা প্রয়োজনীয় নয়। এর অর্থ শেষ পর্যন্ত তারা সর্বদা ব্রাউজারে লোড হবে। যদি আমার কাছে প্রচুর jquery প্লাগইন থাকে তবে এর মধ্যে কেবলমাত্র অর্ধেকটি ব্যবহার করা হলেও এটি একটি খুব বড় ফাইলের ফলাফল করবে। 'Jquery.plugin1' কেবল বিক্রেতার বান্ডেলে অন্তর্ভুক্ত করার কোনও উপায় নেই?
বেনসাম্পাইও

ধন্যবাদ, তাই আমিও কিছু শিখেছি :) আমি একাধিক বিক্রেতা-খণ্ড তৈরির সাথে আমার উত্তরটি আপডেট করেছি। সম্ভবত এখন এটি আপনার পক্ষে আরও ভাল মানাবে।
মিচা মারজিয়েল

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

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

আমি কীভাবে বিক্রেতা ফাইলগুলির জন্য আলাদাভাবে প্রসঙ্গ সেট করতে পারি?
কঠোরতা 53

44

আপনি যদি বিক্রেতাদের থেকে আলাদা হয়ে নিজের স্ক্রিপ্টগুলি স্বয়ংক্রিয়ভাবে বান্ডিল করতে আগ্রহী হন:

var webpack = require('webpack'),
    pkg     = require('./package.json'),  //loads npm config file
    html    = require('html-webpack-plugin');

module.exports = {
  context : __dirname + '/app',
  entry   : {
    app     : __dirname + '/app/index.js',
    vendor  : Object.keys(pkg.dependencies) //get npm vendors deps from config
  },
  output  : {
    path      : __dirname + '/dist',
    filename  : 'app.min-[hash:6].js'
  },
  plugins: [
    //Finally add this line to bundle the vendor code separately
    new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.min-[hash:6].js'),
    new html({template : __dirname + '/app/index.html'})
  ]
};

আপনি অফিসিয়াল ডকুমেন্টেশনে এই বৈশিষ্ট্যটি সম্পর্কে আরও পড়তে পারেন ।


4
দয়া করে মনে রাখবেন যে vendor : Object.keys(pkg.dependencies) সর্বদা কাজ করে না এবং প্যাকেজটি কীভাবে তৈরি হয় তার উপর নির্ভর করে।
মার্কিফ

1
আপনি কীভাবে package.jsonসেট হন তার উপর আপনি সর্বদা নির্ভরশীল । এই কর্মক্ষেত্রটি বেশিরভাগ ক্ষেত্রে কাজ করে তবে সেখানে ব্যতিক্রম রয়েছে যেখানে আপনাকে আলাদা পথ নিতে হবে। সম্প্রদায়কে সহায়তা করতে আপনার নিজের প্রশ্নের উত্তর পোস্ট করা আকর্ষণীয় হতে পারে।
ফ্রিজিস্টেম

16
আমি এই পছন্দ। এটি আমাকে কিছুটা প্রস্রাব করেছে।
cgatian

3
মনে রাখবেন এটি এমনকি এমন প্যাকেজগুলি অন্তর্ভুক্ত করবে যা আপনি এমনকি আপনার কোডে ব্যবহার করছেন না ... কারণ Object.keys(pkg.dependencies)সমস্ত কিছু বান্ডিল করবে !!!! যাক আপনাকে এখানে একটি গুচ্ছ লোডার তালিকাভুক্ত করা আছে ... হ্যাঁ এটি অন্তর্ভুক্ত করা হবে !!! সুতরাং সাবধানতা অবলম্বন করুন ... আলাদাভাবে যত্ন সহকারে ডিভডিপেন্সিটি কী এবং নির্ভরতা কী
রাফায়েল

1
@ রাফায়েলমিলিউস্কি আপনি কেন লোডার রাখবেন dependencies?
প্যান্ট

13

আমি আপনার কেস পুরোপুরি বুঝতে পেরেছি কিনা তাও নিশ্চিত নন তবে আপনার প্রতিটি বান্ডেলের জন্য পৃথক বিক্রেতার অংশগুলি তৈরি করতে এখানে কনফিগার করা স্নিপেট রয়েছে:

entry: {
  bundle1: './build/bundles/bundle1.js',
  bundle2: './build/bundles/bundle2.js',
  'vendor-bundle1': [
    'react',
    'react-router'
  ],
  'vendor-bundle2': [
    'react',
    'react-router',
    'flummox',
    'immutable'
  ]
},

plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor-bundle1',
    chunks: ['bundle1'],
    filename: 'vendor-bundle1.js',
    minChunks: Infinity
  }),
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor-bundle2',
    chunks: ['bundle2'],
    filename: 'vendor-bundle2-whatever.js',
    minChunks: Infinity
  }),
]

এবং CommonsChunkPluginদস্তাবেজের লিঙ্ক : http://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin


আমি বিশ্বাস করি যে এই সমাধানের সাথে সমস্যাটি মিশালের সরবরাহকারীর মতোই। আপনি ধরে নিচ্ছেন যে আমি বান্ডেল 1 এবং বান্ডেল 2 এর বিক্রেতার নির্ভরতা জানি, তবে আমি তা করি না ... আপনি 200 বান্ডিল পেয়েছেন তা কি কনফিগার ফাইলে নির্দিষ্ট করতে চান? আপনার উদাহরণ ব্যবহার করে, reactকেবলমাত্র বান্ডেল 1 এবং বান্ডেল 2 দ্বারা স্পষ্টভাবে প্রয়োজন হলে কেবল বিক্রেতার বান্ডলে উপস্থিত থাকতে হবে। কনফিগার ফাইলে আমার এটি নির্দিষ্ট করা উচিত নয় ... এটি কি কোনও তাৎপর্যপূর্ণ? কোন ধারনা?
বেনসাম্পাইও

@ আনাকিন প্রশ্ন আপনি 200 ভেন্ডার সরঞ্জামকে আলাদা একটি ফাইলে বান্ডিল করতে চান কেন তা প্রশ্ন। আমি কেবল সাধারণ সরঞ্জামগুলিকে একটি পৃথক ফাইলে বান্ডিল করব এবং বাকী প্রকল্পের বান্ডিলগুলি দিয়ে রাখব।
ম্যাক্সিসাম

@ আনাকিন আমার মনে হয় আমি একই সমস্যা নিয়ে কাজ করছি, আমি ভুল হলে আমাকে সংশোধন করব? stackoverflow.com/questions/35944067/...
pjdicke
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.