Webpack GivePlugin กับ externals?


84

ฉันสำรวจความคิดของการใช้WebpackกับBackbone.js

ฉันได้ทำตามคู่มือเริ่มใช้งานฉบับย่อและมีแนวคิดทั่วไปเกี่ยวกับการทำงานของ Webpack แต่ฉันไม่ชัดเจนเกี่ยวกับวิธีโหลดไลบรารีการพึ่งพาเช่น jquery / backbone / ขีดล่าง

ควรโหลดจากภายนอกด้วย<script>หรือนี่คือสิ่งที่ Webpack สามารถจัดการได้เหมือน shim ของ RequireJS?

ตามที่doc webpack: shimming โมดูล , ProvidePluginและexternalsดูเหมือนจะเกี่ยวข้องกับเรื่องนี้ (เพื่อให้เป็นbundle!ที่ใดที่หนึ่งรถตักดิน) แต่ฉันไม่สามารถคิดออกเมื่อมีการใช้งานที่

ขอบคุณ

คำตอบ:


153

เป็นไปได้ทั้งสองอย่าง: คุณสามารถรวมไลบรารีด้วย<script>(เช่นใช้ไลบรารีจาก CDN) หรือรวมไว้ในบันเดิลที่สร้าง

หากคุณโหลดผ่าน<script>แท็กคุณสามารถใช้externalsตัวเลือกเพื่ออนุญาตให้เขียนrequire(...)ในโมดูลของคุณ

ตัวอย่างด้วยไลบรารีจาก CDN:

<script src="https://code.jquery.com/jquery-git2.min.js"></script>

// the artifial module "jquery" exports the global var "jQuery"
externals: { jquery: "jQuery" }

// inside any module
var $ = require("jquery");

ตัวอย่างกับไลบรารีที่รวมอยู่ในบันเดิล:

copy `jquery-git2.min.js` to your local filesystem

// make "jquery" resolve to your local copy of the library
// i. e. through the resolve.alias option
resolve: { alias: { jquery: "/path/to/jquery-git2.min.js" } }

// inside any module
var $ = require("jquery");

ProvidePluginสามารถแมโมดูลกับตัวแปร (ฟรี) ดังนั้นคุณสามารถกำหนด: "ทุกครั้งที่ฉันใช้ตัวแปร (ฟรี) xyzภายในโมดูลที่คุณ (webpack) ควรตั้งค่าxyzเป็นrequire("abc")"

ตัวอย่างที่ไม่มีProvidePlugin:

// You need to require underscore before you can use it
var _ = require("underscore");
_.size(...);

ตัวอย่างด้วยProvidePlugin:

plugins: [
  new webpack.ProvidePlugin({
    "_": "underscore"
  }) 
]

// If you use "_", underscore is automatically required
_.size(...)

สรุป:

  • ไลบรารีจาก CDN: ใช้<script>แท็กและexternalsตัวเลือก
  • ไลบรารีจากระบบไฟล์: รวมไลบรารีไว้ในบันเดิล (อาจปรับเปลี่ยนตัวresolveเลือกเพื่อค้นหาไลบรารี)
  • externals: ทำให้ global vars พร้อมใช้งานเป็นโมดูล
  • ProvidePlugin: ทำให้โมดูลพร้อมใช้งานเป็นตัวแปรอิสระภายในโมดูล

ควรเพิ่มnewก่อนwebpack.ProvidePlugin webpack.github.io/docs/list-of-plugins.html
MK Yung

ทำไมไม่ใช้แค่ตัวโหลดสคริปต์? มันง่ายกว่ามากเหมือนที่ @dtothefp อธิบายไว้
timaschew

หากไฟล์ webpack.config ของฉันอยู่ในโฟลเดอร์ชื่อ javascript และภายในนั้นฉันมีโฟลเดอร์ชื่อ vendor พร้อมไฟล์ jquery ของฉัน เส้นทางไม่ควรเป็น แก้ไข: {alias: {jquery: "vendor / jquery-1.10.2.js"}} ยังใช้ไม่ได้กับฉันโดยใช้นามแฝง
me-me

3
เพียงแค่ส่งเส้นทางสัมบูรณ์ไปยังตัวเลือกนามแฝง หากคุณส่งเส้นทางสัมพัทธ์มันจะสัมพันธ์กับตำแหน่งของ Require / import ใน webpack 1 ใน webpack 2 จะสัมพันธ์กับการตอบสนองของไฟล์ webpack.config.js ตัวเลือกบริบท
Tobias K.

@TobiasK. เส้นทางสัมบูรณ์ไม่ร่วมมือกับการส่งออกเริ่มต้น ฉันได้รับวัตถุ{__esModule: true, default: MY_DEFAULT_EXPORT}แทนที่จะMY_DEFAULT_EXPORTอยู่ในไฟล์
mgol

26

สิ่งที่เย็นที่จะต้องทราบก็คือว่าถ้าคุณใช้ProvidePluginร่วมกับexternalsคุณสมบัติมันจะช่วยให้คุณได้jQueryผ่านเข้าสู่การปิดโมดูล webpack คุณโดยไม่ต้องชัดเจนrequireมัน ซึ่งจะเป็นประโยชน์สำหรับ refactoring $รหัสเดิมที่มีจำนวนมากของไฟล์ที่แตกต่างอ้างอิง

//webpack.config.js
module.exports = {
  entry: './index.js',
  output: { 
    filename: '[name].js' 
  },
  externals: {
    jquery: 'jQuery'
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
    })
  ]
};

ตอนนี้อยู่ใน index.js

console.log(typeof $ === 'function');

จะมีผลลัพธ์ที่คอมไพล์พร้อมสิ่งที่ต้องการด้านล่างผ่านไปยังการwebpackBootstrapปิด

/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    /* WEBPACK VAR INJECTION */(function($) {
        console.log(typeof $ === 'function');

    /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))

/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

    module.exports = jQuery;

/***/ }
/******/ ])

ดังนั้นคุณจะเห็นว่า$กำลังอ้างอิง global / window jQueryจาก CDN แต่กำลังถูกส่งต่อไปยังการปิด ฉันไม่แน่ใจว่านี่เป็นฟังก์ชั่นการใช้งานหรือโชคดีแฮ็ค แต่ดูเหมือนว่าจะใช้ได้ดีกับกรณีการใช้งานของฉัน


คุณไม่จำเป็นต้องปลั๊กอินอย่างใดอย่างหนึ่งถ้าคุณไม่ได้ไปrequire/importมัน $จะใช้งานได้เพราะมันจะไปถึงขอบเขตทั่วโลกไม่ว่าจะเกิดอะไรขึ้น ProviderPluginต้องแยก AST จึงเป็นปลั๊กอินราคาแพงและจะเพิ่มเวลาในการสร้างของคุณอย่างเห็นได้ชัด ดังนั้นมันจึงเป็นการสูญเปล่า
faceyspacey.com

@dtohefp คำตอบนี้คือขั้นเทพ คุณสามารถอธิบายได้หรือไม่ว่าเหตุใดจึงProvidePluginส่งคืนวัตถุเช่นmyModule.defaultเว้นแต่ฉันจะเพิ่มโมดูลไปยังภายนอก ฉันไม่เคยรู้เลยว่าจะมีความสัมพันธ์โดยตรง
Slbox

11

ฉันรู้ว่านี่เป็นโพสต์เก่า แต่คิดว่ามันจะมีประโยชน์หากพูดถึงว่าตัวโหลดสคริปต์ของ webpack อาจมีประโยชน์ในกรณีนี้เช่นกัน จากเอกสาร webpack:

"script: เรียกใช้ไฟล์ JavaScript หนึ่งครั้งในบริบทส่วนกลาง (เช่นในแท็กสคริปต์) ความต้องการจะไม่ถูกแยกวิเคราะห์"

http://webpack.github.io/docs/list-of-loaders.html

https://github.com/webpack/script-loader

ฉันพบว่าสิ่งนี้มีประโยชน์อย่างยิ่งเมื่อย้ายกระบวนการสร้างรุ่นเก่าที่เชื่อมไฟล์ผู้ขาย JS และไฟล์แอปเข้าด้วยกัน คำเตือนคือดูเหมือนว่าตัวโหลดสคริปต์จะทำงานผ่านการโอเวอร์โหลดเท่านั้นrequire()และไม่ทำงานเท่าที่ฉันสามารถบอกได้โดยระบุไว้ในไฟล์ webpack.config แม้ว่าหลายคนโต้แย้งว่าการใช้งานมากเกินไปrequireเป็นแนวทางปฏิบัติที่ไม่ดี แต่ก็มีประโยชน์มากสำหรับการรวมผู้ขายและสคริปต์แอปไว้ในชุดเดียวและในขณะเดียวกันก็เปิดเผย JS Globals ที่ไม่จำเป็นต้องแยกเป็นชุด webpack เพิ่มเติม ตัวอย่างเช่น:

require('script!jquery-cookie/jquery.cookie');
require('script!history.js/scripts/bundled-uncompressed/html4+html5/jquery.history');
require('script!momentjs');

require('./scripts/main.js');

สิ่งนี้จะทำให้ $ .cookie, ประวัติและช่วงเวลาพร้อมใช้งานทั่วโลกทั้งภายในและภายนอกของบันเดิลนี้และรวม libs ของผู้ให้บริการเหล่านี้ด้วยสคริปต์ main.js และทั้งหมดเป็นrequireไฟล์ d

นอกจากนี้เทคนิคนี้ยังมีประโยชน์คือ:

resolve: {
  extensions: ["", ".js"],
  modulesDirectories: ['node_modules', 'bower_components']
},
plugins: [
  new webpack.ResolverPlugin(
    new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
   )
]

ซึ่งใช้ Bower จะดูmainไฟล์ในแต่ละrequired libraries package.json ในตัวอย่างข้างต้น History.js ไม่มีmainไฟล์ที่ระบุดังนั้นจึงจำเป็นต้องใช้พา ธ ไปยังไฟล์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.