विक्रेता स्क्रिप्ट को अलग से कैसे बंडल करें और उन्हें वेबपैक के साथ आवश्यकतानुसार उपयोग करें?


173

मैं कुछ ऐसा करने की कोशिश कर रहा हूं जो मुझे विश्वास है कि संभव होना चाहिए, लेकिन मैं वास्तव में समझ नहीं पा रहा हूं कि इसे वेबपैक प्रलेखन से कैसे किया जाए।

मैं कई मॉड्यूल के साथ एक जावास्क्रिप्ट पुस्तकालय लिख रहा हूं जो एक दूसरे पर निर्भर हो सकते हैं या नहीं। उसके शीर्ष पर, jQuery का उपयोग सभी मॉड्यूल द्वारा किया जाता है और उनमें से कुछ को jQuery प्लगइन्स की आवश्यकता हो सकती है। इस लाइब्रेरी का उपयोग कई अलग-अलग वेबसाइटों पर किया जाएगा जिन्हें कुछ या सभी मॉड्यूल की आवश्यकता हो सकती है।

मेरे मॉड्यूल के बीच निर्भरता को परिभाषित करना बहुत आसान था, लेकिन उनकी तृतीय-पक्ष निर्भरता को परिभाषित करना कठिन प्रतीत होता है तब मुझे उम्मीद थी।

मैं क्या हासिल करना चाहूंगा : प्रत्येक ऐप के लिए मुझे दो बंडल फाइलें मिलनी चाहिए, जिसमें आवश्यक तृतीय-पक्ष निर्भरताएं और अन्य मेरे पुस्तकालय से आवश्यक मॉड्यूल के साथ हों।

उदाहरण : आइए कल्पना करें कि मेरे पुस्तकालय में निम्नलिखित मॉड्यूल हैं:

  • a (आवश्यकता है: jquery, jquery.plugin1)
  • b (आवश्यकता: jquery, a)
  • सी (की आवश्यकता है: jquery, jquery.ui, ए, बी)
  • d (आवश्यकता: jquery, jquery.plugin2, a)

और मेरे पास एक ऐप है (इसे एक अनूठी प्रविष्टि फ़ाइल के रूप में देखें) को मॉड्यूल ए, बी और सी की आवश्यकता होती है। इस मामले के लिए वेबपैक को निम्नलिखित फाइलें उत्पन्न करनी चाहिए:

  • विक्रेता बंडल : jquery, jquery.plugin1 और jquery.ui के साथ;
  • वेबसाइट बंडल : मॉड्यूल ए, बी और सी के साथ;

अंत में, मैं एक वैश्विक के रूप में jQuery को पसंद करूंगा, इसलिए मुझे हर एक फ़ाइल पर इसकी आवश्यकता नहीं है (मुझे केवल मुख्य फ़ाइल पर इसकी आवश्यकता हो सकती है, उदाहरण के लिए)। और jQuery प्लगइन्स केवल आवश्यक होने पर $ ग्लोबल का विस्तार करेंगे (यह एक समस्या नहीं है यदि वे अन्य मॉड्यूल के लिए उपलब्ध हैं जिनकी आवश्यकता नहीं है)।

यह संभव है, इस मामले के लिए एक वेबपैक कॉन्फ़िगरेशन फ़ाइल का एक उदाहरण क्या होगा? मैंने अपनी कॉन्फ़िगरेशन फ़ाइल पर लोडर, एक्सटर्नल और प्लगइन्स के कई संयोजनों की कोशिश की, लेकिन मुझे वास्तव में नहीं मिला कि वे क्या कर रहे हैं और मुझे किनका उपयोग करना चाहिए। धन्यवाद!


2
आपका समाधान क्या है? क्या आपने एक सभ्य दृष्टिकोण खोजने का प्रबंधन किया। यदि ऐसा है तो कृपया इसे पोस्ट करें! धन्यवाद
GeekOnGadgets

जवाबों:


140

मेरे webpack.config.js (संस्करण 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
]

अब मेरे पास एक फाइल है जो केवल आवश्यकतानुसार 3 पार्टी के कामों को एक फ़ाइल में जोड़ती है।

यदि आप अधिक दानेदार चाहते हैं, जहां आप अपने विक्रेताओं और प्रवेश बिंदु फ़ाइलों को अलग करते हैं:

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);
    }
  })
]

ध्यान दें कि प्लगइन्स का क्रम बहुत मायने रखता है।

इसके अलावा, यह संस्करण 4 में बदलने जा रहा है। जब यह आधिकारिक है, तो मैं इस उत्तर को अपडेट करता हूं।

अपडेट: विंडोज़ उपयोगकर्ताओं के लिए इंडेक्सऑफ़ खोज परिवर्तन


1
मुझे नहीं पता कि यह पहले से ही संभव था जब मैंने अपना प्रश्न पोस्ट किया था, लेकिन यह वास्तव में वही है जो मैं देख रहा था। इस समाधान के साथ मुझे अब अपने विक्रेता प्रविष्टि चंक को निर्दिष्ट करने की आवश्यकता नहीं है। आपका बहुत बहुत धन्यवाद!
बेंसम्पायो

1
isExternalमें minChunksमेरा दिन बना दिया। यह कैसे प्रलेखित नहीं है? डाउनसाइड्स है?
वेस्ले स्कोलर डी डेस

Thx, लेकिन windowsRes के लिए userRequest.indexOf ('/ node_modules /') को बदलकर windows पथों के लिए userRequest.indexOf ('node_modules')
Kinjeiro

@ WesleySchleumerdeGóes यह प्रलेखित है, लेकिन उदाहरण के बिना 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)/);
cdauth

54

मुझे यकीन नहीं है कि अगर मैं आपकी समस्या को पूरी तरह से समझ पाऊंगा, लेकिन चूंकि मेरा हाल ही में ऐसा ही मुद्दा था, तो मैं आपकी मदद करने की कोशिश करूंगा।

वेंडर बंडल।

उसके लिए आपको CommonsChunkPlugin का उपयोग करना चाहिए । कॉन्फ़िगरेशन में आप चंक का नाम निर्दिष्ट करते हैं (उदा vendor), और फ़ाइल नाम जो उत्पन्न होगा ( vendor.js)।

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

अब महत्वपूर्ण हिस्सा, आपको अब यह निर्दिष्ट करना होगा कि इसका क्या मतलब है vendorपुस्तकालय और आप एक प्रविष्टि अनुभाग में ऐसा करते हैं। प्रवेश सूची में एक और आइटम उसी नाम के साथ है, जो इस मामले में नए घोषित चंक का नाम है (यानी 'विक्रेता')। उस प्रविष्टि का मूल्य उन सभी मॉड्यूलों की सूची होना चाहिए जिन्हें आप vendorबंडल में स्थानांतरित करना चाहते हैं । आपके मामले में यह कुछ इस तरह दिखना चाहिए:

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

JQuery के रूप में वैश्विक

एक ही समस्या थी और इसे ProvPlugin के साथ हल किया । यहाँ आप वैश्विक वस्तु को परिभाषित नहीं कर रहे हैं लेकिन मॉड्यूल को तरह तरह के शार्टकट्स दे रहे हैं। यानी आप इसे इस तरह कॉन्फ़िगर कर सकते हैं:

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'
    ]
},

यदि कुछ पुस्तकालय प्रवेश बिंदुओं के बीच (और उनमें से अधिकांश के लिए) ओवरलैप कर रहे हैं, तो आप उन्हें अलग-अलग कॉन्फ़िगरेशन के साथ एक ही प्लगइन का उपयोग करके सामान्य फ़ाइल में निकाल सकते हैं। इस उदाहरण को देखें ।


आपके उत्तर के लिए बहुत बहुत धन्यवाद। यह अब तक मैंने देखा सबसे अच्छा तरीका था, लेकिन दुर्भाग्य से यह अभी भी मेरी समस्या का समाधान नहीं करता है ... मैंने आपके उदाहरण और विक्रेता का परीक्षण किया। जेएस फाइल में अभी भी 'jquery' और 'jquery.plugin1' से सभी कोड होंगे, भले ही उन्हें मेरे किसी भी मॉड्यूल की आवश्यकता नहीं है। इसका मतलब है कि अंत में वे हमेशा ब्राउज़र पर लोड रहेंगे। अगर मेरे पास बहुत सारे jquery प्लगइन्स हैं, तो यह एक बहुत बड़ी फ़ाइल का परिणाम देगा, भले ही उनमें से केवल आधे का उपयोग किया जाए। क्या आवश्यकता होने पर ही वेंडर बंडल में 'jquery.plugin1' को शामिल करने का कोई तरीका नहीं है?
bensampaio

धन्यवाद, इसलिए मैंने भी कुछ सीखा है :) मैंने कई वेंडर-चंक्स के निर्माण के साथ अपना जवाब अपडेट किया है। हो सकता है कि अब यह आपको बेहतर लगे।
मिशैल मार्गील

4
इस समाधान के साथ समस्या यह है कि यह मानता है कि मुझे पता है कि प्रत्येक पृष्ठ के लिए निर्भरताएं क्या हैं। लेकिन मैं यह अनुमान नहीं लगा सकता कि ... jQuery को केवल एक विक्रेता बंडल में शामिल किया जाना चाहिए, यदि यह पृष्ठ में उपयोग किए गए किसी एक मॉड्यूल द्वारा आवश्यक हो। यह निर्दिष्ट करके कि विन्यास फाइल पर यह हमेशा विक्रेता बंडल में होगा, भले ही पृष्ठ में उपयोग किए गए किसी भी मॉड्यूल की आवश्यकता न हो, सही? असल में, मैं वेंडर बंडलों की सामग्री का अनुमान नहीं लगा सकता, अन्यथा मेरे पास एक काम का नर्क होगा क्योंकि मेरे पास सिर्फ 2 पृष्ठ नहीं हैं जिनमें मेरे सैकड़ों हैं ... क्या आपको समस्या है? कोई विचार? :)
बेंसम्पायो

मैं समझता हूं कि आप क्या कह रहे हैं, लेकिन मैं इसे एक समस्या के रूप में नहीं देखता। यदि आप किसी पृष्ठ में नए पुस्तकालय का उपयोग करते हैं, तो बस उस पृष्ठ के लिए एक विक्रेता पुस्तकालय सूची में जोड़ें। यह सिर्फ कुछ किरदार हैं। वैसे भी आपके समाधान में आपको इसे लोडर निर्दिष्ट करके करना होगा। यदि आप नहीं जानते हैं कि कौन से पृष्ठ आपके नए बनाए गए मॉड्यूल का उपयोग करेंगे - तो अपने मॉड्यूल से कॉमन लाइब्रेरीज़ को स्वचालित रूप से निकालने के लिए कॉमनच्यून्क्स प्लग इन करें।
मिशैल मार्गील

मैं विक्रेता फ़ाइलों के लिए अलग से संदर्भ कैसे सेट कर सकता हूं?
harshes53

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 द्वारा स्पष्ट रूप से आवश्यक है। मुझे यह निर्दिष्ट नहीं करना चाहिए कि विन्यास फाइल पर ... क्या इसका कोई मतलब है? कोई विचार?
बेनसम्पैयो

@Anakin सवाल यह है कि आप 200 विक्रेताओं के टूल को एक अलग फ़ाइल में क्यों बांधना चाहते हैं। मैं केवल सामान्य टूल को एक अलग फ़ाइल में बंडल करता हूं, और बाकी को प्रोजेक्ट बंडल के साथ रखता हूं।
मैक्सिसम

@Anakin मुझे लगता है कि मैं एक ही मुद्दे से निपट रहा हूं, अगर मैं गलत हूं तो मुझे सुधारें? stackoverflow.com/questions/35944067/…
pjdicke
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.