深藏若虛

讓 jQuery 在 webpack 中成為全域變數

Expose jQuery to global variable with Webpack

前言

這兩三年,可謂前端技術更迭不斷、框架不斷推陳出新的尖峰時期,本來就比較沒有再碰前端技術、以及專注在碩士求學生涯的我也算是落後許多。在拿到碩士學位後,又重新開始投入 Web 開發,不斷學習新知,尤其是在前端技術方面。最近開始使用 webpack 做為 module bundler,這篇主要就是紀錄初期使用 webpack 時遇到的一個撞牆點。

儘管前端框架越來越多,angular.js、react.js 以及最近竄起的 vue.js 開始主導整個網頁前段的流程控制以及事件觸發,但是許多 CSS 框架仍是相依在 jQuery 上,且可能沒有對其他 JavaScript 框架有著完整的支援,所以在使用 JavaScript 框架之餘,仍需要使用 jQuery 作為驅動 CSS 框架的手段。最近開始嘗試使用 vue.js 與 webpack 的組合去做網站開發,在套用 semantic-ui 和 materialize 這兩門前端設計框架時,就遇到了找不到 jQuery 套件庫的錯誤,導致網站的 JavaScrit 程序被中斷,無法繼續執行下去。

誤區

依照 webpack 去引入 JavaScript 的套件,以為只要在 js 檔案中加入下面兩行程式碼即可。但首先遇到的就是 JSLint 發出重複 import 的錯誤,直接否決掉這個做法。

// Error: no-duplicate-imports  'jquery' import is duplicated
import $ from 'jquery'
import jQuery from 'query'

為了避開這個錯誤,改只有 import 一次,用變數賦值去改善這個問題。在引入 semantic-ui 或 materialize 時,仍然出現了 ReferenceError: Can't find variable: jQuery 的錯誤。

// Error: ReferenceError: Can't find variable: jQuery
import $ from 'jquery'
var jQuery = $

接著稍微 Google,有人提到要讓 jQuery 掛載 window 物件下成為全域變數,就可以解決問題了。所以嘗試以下面程式碼解決問題,但仍然得到 ReferenceError: Can't find variable: jQuery 的錯誤。

// Error: ReferenceError: Can't find variable: jQuery
import jquery from 'jquery'

window.$ = jquery
window.jQuery = jquery

以上解法都失敗。目前對於 webpack 還不甚熟悉,只有在同一個檔案內的程式碼可以使用 $jQuery 呼叫 jQuery,但若是 import 的 JavaScript 套件需要 jQuery 時就會找不到,在網頁開啟開發者工具區呼叫這兩個變數時也會找不到。推估是因為 webpack 對於每個檔案的變數宣告的作用範圍 (scope) 都侷限在檔案裡,不會真的成為全域變數,所以就算把 jQuery 掛在 window 物件內,仍無法解決問題。這個假設等未來對前端更熟悉後,再來嘗試驗證。

解法

既然無法從單個檔案解決問題,就只好換個方向,嘗試使用設定檔解決問題。繼續嘗試 Google 尋找資料,得到大致有兩種解法,且都是可以運作的。

不管是何種解法,首先就是要透過 npm 安裝 jQuery:

npm install --save jquery

第一種是使用 webpack plugin 的方式,透過 Provide Plugin 1 讓 jQuery 成為全域變數。編輯 webpack 的設定檔,在 module.exports.plugins 中加入 Webpack ProvidePlugins,並把 $jQuery 這兩個全域變數指向 jquery 套件庫。

plugins: [
  // other plugins
  // ...
  new webpack.ProvidePlugin({
     $: "jquery",
     jQuery: "jquery"
  })
]

第二種解法則是使用 expose-loader。首先先透過 npm 安裝 expose-loader:

npm install expose-loader --save

然後編輯 webpack 的設定檔,在 module.exports.loaders 中加入下面的程式碼,把 jquery 套件庫揭露 (expose) 成 $jQuery 這兩個全域變數。

loaders: [
  // other loaders
  // ...
  {
    test: require.resolve('jquery'),
    loader: 'expose?jQuery!expose?$'
  }
]

設定檔完成後,重新啟動伺服器。此時網頁仍會顯示 ReferenceError: Can't find variable: jQuery 的錯誤。這時打開網頁的腳本,加入下面的程式碼即可解決這個問題。

import 'jquery`

補充:後來在參考資料第二項的文章裡,發現還有許多其他解法,有興趣的可以前往該頁面閱讀。

參考資料

  1. Expose jQuery to real Window object with Webpack
  2. Managing Jquery plugin dependency in webpack
  3. React China – 求大牛帮忙,用webpack 打包jquery、bootstrap时出错。
  4. Rhadow’s Tech Note – 深入了解 Webpack Plugins

  1. 「Provide Plugin 的主要功能是當在程式中遇到特定字元且沒被定義時會自動載入特定模組。」via Ref-4 

Information Technology , , ,