什麼是 ProvidePlugin

ProvidePlugin 是基於 webpack 裡的一個設定方法,可以用來指定變數讓 JS 套件模組運作於 webpack 下使用,但無法在全域下使用。


ProvidePlugin 在 webpack 內以模組方式使用與全域執行的情形

jQuery 與 axios 的 JS 套件,在全域下的使用情形

將 jQuery 直接在 index.html 的 HTML 頁面將 jQuery 透過 <script src="jquery.js"></script> 方置到注入點 index.js 的方上,這樣的方式會讓 jQuery 變成一個全域物件,也就會在瀏覽器下直接輸入 $ 下方取到 jQuery 的物件。

在這裡要了解沒經模組化,將 JS 套件直接於全域下以 src 的方式引入情形,先進到 webpack 中把所有透過 import <自定模組變數名> from '<模組名>' 加入模組的套件先註解起來不使用。
直接在 index.html</body> 結尾標籤處,在 <script src="./js/index.js"></script> 的 webpack 注入點前方加上下面 CDN,來執行看看二個掛載於全域下的情形。

接著在 index.js 中的最後方,加入下面的程式碼,查看 JS 套件引入的情形。

$jQuerywindow.jQuery 這三個物件,也都是表示 jQuery 物件本身,直接掛於 window 的 $ 物件之下來使用,在成功引入 jQuery 時可以透過下面三個 console.log() 取得 jQuery 物件。
另外 axios 也是一樣的概念,使用 axios 會直接回應是一個函式。


以上就是二個套件在引入 JS 套件後,全域下透過 console.log() 取用情形,另外在瀏覽器開發工具上直接輸入 $jQuerywindow.jQuery 或是 axios 也會一樣直接對應上的結果。

使用 webpack 的 ProvidePlugin 設定,在模組裡與全域下的使用情形

webpack 在注入點多或元件多的情形下使用與設定的麻煩

在使用 webpack 進行開發使用模組,像是使用到 jQuery 來說,就需要在注入點 index.js 檔中輸入 import $ from 'jquery' 將模組引入使用。
以模組化的使用優點來說,就是在要使用時才透過 import <自定模組變數名> from '<模組名>' 的方式將模組引入使用。

這裡不使用前面直接在 index.html 檔直接把 jQuery 與 axios 透過 CDN 引入為全域物件的方式,先把 CDN 註解起來接著下面的操作。

再以使用 axios 的方式來說在多加上 import axios from 'axios' 引入使用,另外若要在加上 swiper 的概念也是一樣。

這樣的引用模組方式,在注入點多或是元件多的情形下使用上也會變的很麻煩,每個部份都要引入相關的模組進來使用。

透過 ProvidePlugin 指定 JS 套件於變數名稱,讓所有的 .js 與元件一次設定下共用

接下來要進行以 jQuery 的模組設定,先將 npm 中加入 jQuery 與 axios,這裡要使用會是上線後的生產模組還要用到 jQuery 與 axios 所以要使用 --save 而不是使用開發模組,不用在後方加上 -dev

透過 webpack 的功能 ProvidePlugin 來設定,就可以讓每支 js 檔,以不用 import 引入第三方套件的方式。

設定內容如下。

以下說明在 ProvidePlugin 的設定方式,是直接在 plugins: [] 裡以 new webpack.ProvidePlugin() 中帶入一個物件 {} 來說定,物件中的屬性名稱都可用來在 webpack 中使用所表示的引用的套件名,以上面的設定來說就分別是 $ jQuery window.jQuery 設定三組,當然也可以自已另外命一個名稱自定義,以 axios: 'axios' 就是將 axios 模組指定變數為 axios

接著在 index.js 的注入點透過 console.log($(‘#box1’)) 查看 jQuery 取 DOM 元素的結果。

使用指令 npm run dev 啟用 webpack-dev-server 查看執行結果。
瀏覽器往啟後查看後會取得訊息如下,這樣就表非 jQuery 是在全域的設定下取得 #box1 的位置。

$ jQuery window.jQuery 設定三組和 jQuery 本身在全域的使用名稱一樣,但透過 webpack 包進模組後,無法直接在 window 下直接取得,所以需要在 webpack 裡設定變數名稱,指定在模組內以變數名取用引入的 JS 套件的模組。

如何証明 axiosjQuery 不是全域物件呢。
在瀏覽器直接輸入 axiosjQuerywindow.jQuery,在 global (全域) 上無法取得 jQuery 的物件,這樣就是透過 webpack 把 JS 套件透過模組直接包進來,外層的 window 呼叫不到。


前面是在 index.js 注入點執行 console.log() 的 jQuery 與 axios 呼叫與執行 AJAX 正常,而後方是直接在瀏覽器的全域下的呼叫, window 下找不到對應的套件出來。


ProvidePlugin 的設定,在 webpack 裡失去了透過模組化 js 的好處了,會有不好除錯的情形產生

1. 你會無法得知哪個 js 組件引入了那些 lib
2. 當組件出現bug時我們無法得知是第三方套件問題還是自己問題

很重要說所以說三次
非必要盡量不要使用 ProvidePlugin 這個做法!!!
非必要盡量不要使用 ProvidePlugin 這個做法!!!
非必要盡量不要使用 ProvidePlugin 這個做法!!!