摘要:本文首發于的技術博客實用至上,非經作者同意,請勿轉載。怎么來兼容老式插件呢方法有不少,下面一個一個來看。與上述的方案相反,此方案是先用加載的滿足老式插件的需要,再通過將其轉換成符合模塊化要求的。
本文首發于Array_Huang的技術博客——實用至上,非經作者同意,請勿轉載。前言
原文地址:https://segmentfault.com/a/1190000006887523
如果您對本系列文章感興趣,歡迎關注訂閱這里:https://segmentfault.com/blog/array_huang
目前前端雖處于百花齊放階段,angular/react/vue競相角逐,但畢竟尚未完全成熟,有些需求還是得依靠我們的老大哥jQuery的。
我個人對jQuery并不反感,但我對jQuery生態的停滯不前相當無奈,比如說赫赫有名的bootstrap(特指3代),在webpack上打包還得靠個loader的,太跟不上時勢了。況且,bootstrap還算好的,有些jquery插件都有一兩年沒更新了,連NPM都沒上架呢,可偏偏就是找不到它們的替代品,項目又急著要上,這可咋辦吶?
別急,今天就教你適配兼容老式jQuery插件。
老式jQuery插件為和不能直接用webpack打包?如果你把jQuery看做是一個普通的js模塊來加載(要用到jQuery的模塊統統先require后再使用),那么,當你加載老式jQuery插件時,往往會提示找不到jQuery實例(有時候是提示找不到$),這是為啥呢?
要解釋這個問題,就必須先稍微解釋一下jQuery插件的機制:jQuery插件是通過jQuery提供的jQuery.fn.extend(object)和jQuery.extend(object)這倆方法,來把插件本身實現的方法掛載到jQuery(也即$)這個對象上的。傳統引用jQuery及其插件的方式是先用加載jQuery本身,然后再用同樣的方法來加載其插件;jQuery會把jQuery對象設置為全局變量(當然也包括了$),既然是全局變量,那么插件們很容易就能找到jQuery對象并掛載自身的方法了。
而webpack作為一個遵從模塊化原則的構建工具,自然是要把各模塊的上下文環境給分隔開以減少相互間的影響;而jQuery也早已適配了AMD/CMD等加載方式,換句話說,我們在require jQuery的時候,實際上并不會把jQuery對象設置為全局變量。說到這里,問題也很明顯了,jQuery插件們找不到jQuery對象了,因為在它們各自的上下文環境里,既沒有局部變量jQuery(因為沒有適配AMD/CMD,所以就沒有相應的require語句了),也沒有全局變量jQuery。
怎么來兼容老式jQuery插件呢?方法有不少,下面一個一個來看。
ProvidePlugin + expose-loader首先來介紹我最為推薦的方法:ProvidePlugin + expose-loader,在我公司的項目,以及我個人的腳手架開源項目webpack-seed里使用的都是這一種方法。
ProvidePlugin的配置是這樣的:
var providePlugin = new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery", "window.jQuery": "jquery", "window.$": "jquery", });
ProvidePlugin的機制是:當webpack加載到某個js模塊里,出現了未定義且名稱符合(字符串完全匹配)配置中key的變量時,會自動require配置中value所指定的js模塊。
如上述例子,當某個老式插件使用了jQuery.fn.extend(object),那么webpack就會自動引入jquery(此處我是用NPM的版本,我也推薦使用NPM的版本)。
另外,使用ProvidePlugin還有個好處,就是,你自己寫的代碼里,再!也!不!用!require!jQuery!啦!畢竟少寫一句是一句嘛哈哈哈。
接下來介紹expose-loader,這個loader的作用是,將指定js模塊export的變量聲明為全局變量。下面來看下expose-loader的配置:
/* 很明顯這是一個loader的配置項,篇幅有限也只能截取相關部分了 看不明白的麻煩去看本系列的另一篇文章《webpack多頁應用架構系列(二):webpack配置常用部分有哪些?》:https://segmentfault.com/a/1190000006863968 */ { test: require.resolve("jquery"), // 此loader配置項的目標是NPM中的jquery loader: "expose?$!expose?jQuery", // 先把jQuery對象聲明成為全局變量`jQuery`,再通過管道進一步又聲明成為全局變量`$` },
你或許會問,有了ProvidePlugin為嘛還需要expose-loader?問得好,如果你所有的jQuery插件都是用webpack來加載的話,的確用ProvidePlugin就足夠了;但理想是豐滿的,現實卻是骨感的,總有那么些需求是只能用來加載的。
externalsexternals是webpack配置中的一項,用來將某個全局變量“偽裝”成某個js模塊的exports,如下面這個配置:
externals: { "jquery": "window.jQuery", },
那么,當某個js模塊顯式地調用var $ = require("jquery")的時候,就會把window,jQuery返回給它。
與上述ProvidePlugin + expose-loader的方案相反,此方案是先用加載的jQuery滿足老式jQuery插件的需要,再通過externals將其轉換成符合模塊化要求的exports。
我個人并不太看好這種做法,畢竟這就意味著jQuery脫離NPM的管理了,不過某些童鞋有其它的考慮,例如為了加快每次打包的時間而把jQuery這些比較大的第三方庫給分離出去(直接調用公共CDN的第三方庫?),也算是有一定的價值。
imports-loader這個方案就相當于手動版的ProvidePlugin,以前我用requireJS的時候也是用的類似的手段,所以我一開始從requireJS遷移到webpack的時候用的也是這種方法,后來知道有ProvidePlugin就馬上換了哈。
這里就不詳細說明了,放個例子大家看看就懂:
// ./webpack.config.js module.exports = { ... module: { loaders: [ { test: require.resolve("some-module"), loader: "imports?$=jquery&jQuery=jquery", // 相當于`var $ = require("jquery");var jQuery = require("jquery");` } ] } };總結
以上的方案其實都屬于shimming,并不特別針對jQuery,請舉一反三使用。另外,上述方案并不僅用于shimming,比如用上ProvidePlugin來寫少幾個require,自己多多挖掘,很有樂趣的哈~~
補充 誤用externals(2016-10-17更新)有童鞋私信我,說用了我文章的方案依然提示$ is not a function,在我仔細分析后,發現:
他用的是我推薦的ProvidePlugin + expose-loader方案,也就是說,他已經把jquery打包進來了。
但是他又不明就里得配了externals:
externals: { jquery: "window.jQuery", },
然而實際上他并沒有直接用來引用jQuery,因此window.jQuery是個null。
結果,他的jquery插件獲得的$就是個null了。
這里面我們可以看出,externals是會覆蓋掉ProvidePlugin的。
但這里有個問題,expose-loader的作用就是設置好window.jQuery和window.$,那window.jQuery怎么會是null呢?我的猜想是:externals在expose-loader設置好window.jQuery前就已經取了window.jQuery的值(null)了。
說了這么多,其實關鍵意思就是,不要手賤不要手賤不要手賤(重要的事情說三遍)!
示例代碼諸位看本系列文章,搭配我在Github上的腳手架項目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed)。
附系列文章目錄(同步更新)webpack多頁應用架構系列(一):一步一步解決架構痛點:https://segmentfault.com/a/1190000006843916
webpack多頁應用架構系列(二):webpack配置常用部分有哪些?:https://segmentfault.com/a/1190000006863968
webpack多頁應用架構系列(三):怎么打包公共代碼才能避免重復?:https://segmentfault.com/a/1190000006871991
webpack多頁應用架構系列(四):老式jQuery插件還不能丟,怎么兼容?:https://segmentfault.com/a/1190000006887523
webpack多頁應用架構系列(五):聽說webpack連less/css也能打包?:https://segmentfault.com/a/1190000006897458
webpack多頁應用架構系列(六):聽說webpack連圖片和字體也能打包?:https://segmentfault.com/a/1190000006907701
webpack多頁應用架構系列(七):開發環境、生產環境傻傻分不清楚?:https://segmentfault.com/a/1190000006952432
webpack多頁應用架構系列(八):教練我要寫ES6!webpack怎么整合Babel?:https://segmentfault.com/a/1190000006992218
webpack多頁應用架構系列(九):總有刁民想害朕!ESLint為你阻擊垃圾代碼:https://segmentfault.com/a/1190000007030775
webpack多頁應用架構系列(十):如何打造一個自定義的bootstrap:https://segmentfault.com/a/1190000007043716
webpack多頁應用架構系列(十一):預打包Dll,實現webpack音速編譯:https://segmentfault.com/a/1190000007104372
webpack多頁應用架構系列(十二):利用webpack生成HTML普通網頁&頁面模板:https://segmentfault.com/a/1190000007126268
webpack多頁應用架構系列(十三):構建一個簡單的模板布局系統:https://segmentfault.com/a/1190000007159115
webpack多頁應用架構系列(十四):No復制粘貼!多項目共用基礎設施
webpack多頁應用架構系列(十五):論前端如何在后端渲染開發模式下夾縫生存
webpack多頁應用架構系列(十六):善用瀏覽器緩存,該去則去,該留則留
本文首發于Array_Huang的技術博客——實用至上,非經作者同意,請勿轉載。
原文地址:https://segmentfault.com/a/1190000006887523
如果您對本系列文章感興趣,歡迎關注訂閱這里:https://segmentfault.com/blog/array_huang
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/90987.html
摘要:我個人慣用的是,因此本文以為例來介紹如何打造一個自定義的。引入全局的方法請看我之前的這篇文章多頁應用架構系列四老式插件還不能丟,怎么兼容,我的腳手架項目也是使用的這套方案。 本文首發于Array_Huang的技術博客——實用至上,非經作者同意,請勿轉載。原文地址:https://segmentfault.com/a/1190000007043716如果您對本系列文章感興趣,歡迎關注訂閱...
摘要:本文首發于的技術博客實用至上,非經作者同意,請勿轉載。原文地址如果您對本系列文章感興趣,歡迎關注訂閱這里這系列文章講什么本系列文章主要介紹如何用這一當前流行的構建工具來設計一個多頁應用的架構。 本文首發于Array_Huang的技術博客——實用至上,非經作者同意,請勿轉載。原文地址:https://segmentfault.com/a/1190000006843916如果您對本系列文章...
摘要:本文首發于的技術博客實用至上,非經作者同意,請勿轉載。原文地址如果您對本系列文章感興趣,歡迎關注訂閱這里前言書承上文多頁應用架構系列十如何打造一個自定義的。終于,發現了這一大殺器,打包時間過長的問題得到完美解決。 本文首發于Array_Huang的技術博客——實用至上,非經作者同意,請勿轉載。原文地址:https://segmentfault.com/a/119000000710437...
摘要:本文首發于的技術博客實用至上,非經作者同意,請勿轉載。如果你使用了,或類似的,那么,通過編譯前后的代碼相差就很大了,這會造成兩個問題以為例把你的代碼轉成什么樣你自己是無法控制的,這往往導致無法通過的審查。 本文首發于Array_Huang的技術博客——實用至上,非經作者同意,請勿轉載。原文地址:https://segmentfault.com/a/1190000007030775如果您...
摘要:在上一篇文章多頁應用架構系列二配置常用部分有哪些中,我介紹了如何配置多頁應用的入口,然而,如果僅僅如此操作,帶來的后果就是,打包生成出來的每一個入口文件都會完整包含所有代碼。的初始化常用參數有哪些,給這個包含公共代碼的命個名唯一標識。 本文首發于Array_Huang的技術博客——實用至上,非經作者同意,請勿轉載。原文地址:https://segmentfault.com/a/1190...
閱讀 1469·2021-11-22 14:44
閱讀 2848·2021-11-16 11:44
閱讀 3214·2021-10-13 09:40
閱讀 1993·2021-10-08 10:04
閱讀 2368·2021-09-24 10:28
閱讀 2916·2021-09-06 15:02
閱讀 2965·2019-08-30 15:52
閱讀 2400·2019-08-30 13:20