Webpack Cung cấpPlugin so với bên ngoài?


84

Tôi đang khám phá ý tưởng sử dụng Webpack với Backbone.js .

Tôi đã làm theo hướng dẫn bắt đầu nhanh và có ý tưởng chung về cách hoạt động của Webpack, nhưng tôi không rõ về cách tải thư viện phụ thuộc như jquery / backbone / underscore.

Chúng có nên được tải ra bên ngoài <script>hay đây là thứ mà Webpack có thể xử lý giống như miếng đệm của RequiJS?

Theo tài liệu webpack doc: shimming module , ProvidePluginexternalsdường như có liên quan đến điều này ( bundle!bộ tải ở đâu đó cũng vậy) nhưng tôi không thể tìm ra khi nào nên sử dụng.

Cảm ơn

Câu trả lời:


153

Cả hai đều có thể: Bạn có thể bao gồm các thư viện với <script>(nghĩa là sử dụng thư viện từ CDN) hoặc bao gồm chúng vào gói đã tạo.

Nếu bạn tải nó qua <script>thẻ, bạn có thể sử dụng externalstùy chọn để cho phép viết require(...)trong các mô-đun của mình.

Ví dụ với thư viện từ 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");

Ví dụ với thư viện được bao gồm trong gói:

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

ProvidePluginthể ánh xạ các mô-đun thành các biến (miễn phí). Vì vậy, bạn có thể xác định: "Mỗi khi tôi sử dụng biến (miễn phí) xyzbên trong một mô-đun, bạn (webpack) nên đặt xyzthành require("abc")."

Ví dụ không có ProvidePlugin:

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

Ví dụ với ProvidePlugin:

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

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

Tóm lược:

  • Thư viện từ CDN: Sử dụng <script>thẻ và externalstùy chọn
  • Thư viện từ hệ thống tệp: Bao gồm thư viện trong gói. (Có thể sửa đổi resolvecác tùy chọn để tìm thư viện)
  • externals: Cung cấp các vars toàn cầu dưới dạng mô-đun
  • ProvidePlugin: Làm cho các mô-đun có sẵn dưới dạng các biến miễn phí bên trong các mô-đun

Nên thêm newtrước webpack.ProvidePlugin webpack.github.io/docs/list-of-plugins.html
MK Yung

Tại sao không chỉ sử dụng trình tải tập lệnh? Điều này dễ dàng hơn nhiều, như @dtothefp đã giải thích
timaschew

Nếu tệp webpack.config của tôi nằm trong một thư mục có tên javascript và bên trong đó tôi có một thư mục được gọi là nhà cung cấp với tệp jquery của mình. con đường không nên. giải quyết: {alias: {jquery: "provider / jquery-1.10.2.js"}}. Vẫn không làm việc cho tôi sử dụng bí danh
tôi-me

3
Chỉ cần chuyển một đường dẫn tuyệt đối đến tùy chọn bí danh. Nếu bạn chuyển một đường dẫn tương đối, nó liên quan đến vị trí của request / import trong webpack 1. Trong webpack 2, nó liên quan đến tệp webpack.config.js. tùy chọn ngữ cảnh.
Tobias K.

@TobiasK. Một đường dẫn tuyệt đối không hợp tác với các bản xuất mặc định. Tôi đang nhận một đối tượng {__esModule: true, default: MY_DEFAULT_EXPORT}thay vì MY_DEFAULT_EXPORTtrong các tệp.
mgol

25

Một điều thú vị cần lưu ý là nếu bạn sử dụng ProvidePluginkết hợp với thuộc externalstính, nó sẽ cho phép bạn jQuerychuyển vào phần đóng mô-đun webpack của mình mà không cần phải đóng requirenó một cách rõ ràng . Điều này có thể hữu ích cho việc cấu trúc lại mã kế thừa với nhiều tệp tham chiếu khác nhau $.

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

bây giờ trong index.js

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

sẽ có một đầu ra được biên dịch với một cái gì đó như dưới đây được chuyển vào phần webpackBootstrapđóng:

/******/ ([
/* 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;

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

Do đó, bạn có thể thấy điều đó $đang tham chiếu đến toàn cầu / cửa sổ jQuerytừ CDN, nhưng đang được chuyển vào phần đóng. Tôi không chắc đây là chức năng dự định hay là một vụ hack may mắn nhưng nó có vẻ hoạt động tốt cho trường hợp sử dụng của tôi.


bạn không cần một trong hai plugin nếu bạn không sử dụng require/importnó. $sẽ chỉ hoạt động vì nó sẽ vươn tới phạm vi toàn cầu bất kể thế nào. Yêu ProviderPlugincầu phân tích cú pháp AST nên đây là một plugin đắt tiền và sẽ làm tăng đáng kể thời gian xây dựng của bạn. Vì vậy, về cơ bản nó là một sự lãng phí.
faceyspacey.com

@dtohefp câu trả lời này là một ơn trời. Bạn có thể giải thích tại sao ProvidePlugintrả về một đối tượng như thế nào, myModule.defaulttrừ khi tôi thêm mô-đun vào bên ngoài? Tôi không bao giờ biết sẽ có bất kỳ mối quan hệ trực tiếp nào.
Slbox

11

Tôi biết đây là một bài đăng cũ nhưng tôi nghĩ rằng sẽ hữu ích khi đề cập rằng trình tải tập lệnh webpack cũng có thể hữu ích trong trường hợp này. Từ tài liệu webpack:

"script: Thực thi một tệp JavaScript một lần trong ngữ cảnh chung (như trong thẻ script), các yêu cầu không được phân tích cú pháp."

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

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

Tôi nhận thấy điều này đặc biệt hữu ích khi di chuyển các quy trình xây dựng cũ hơn kết hợp các tệp của nhà cung cấp JS và tệp ứng dụng với nhau. Một lời cảnh báo là trình tải tập lệnh dường như chỉ hoạt động thông qua quá tải require()và không hoạt động xa như tôi có thể nói bằng cách được chỉ định trong tệp webpack.config. Mặc dù, nhiều người cho rằng quá tải requirelà một phương pháp không tốt, nhưng nó có thể khá hữu ích để kết hợp nhà cung cấp và tập lệnh ứng dụng trong một gói, đồng thời để lộ JS Globals mà không cần phải ghép vào các gói webpack bổ sung. Ví dụ:

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

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

Điều này sẽ làm cho $ .cookie, History và moment có sẵn trên toàn cầu bên trong và bên ngoài gói này, đồng thời gói các lib của nhà cung cấp này bằng tập lệnh main.js và tất cả requirecác tệp d.

Ngoài ra, hữu ích với kỹ thuật này là:

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

đang sử dụng Bower, sẽ xem xét maintệp trong mỗi requirethư viện d package.json. Trong ví dụ trên, History.js không có maintệp được chỉ định, vì vậy đường dẫn đến tệp là cần thiết.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.