webpack多頁(yè)應(yīng)用架構(gòu)系列(四):老式j(luò)Query插件還不能丟,怎么兼容氧吐?

本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意末盔,請(qǐng)勿轉(zhuǎn)載筑舅。
原文地址:https://segmentfault.com/a/1190000006887523
如果您對(duì)本系列文章感興趣,歡迎關(guān)注訂閱這里:https://segmentfault.com/blog/array_huang

前言

目前前端雖處于百花齊放階段陨舱,angular/react/vue競(jìng)相角逐翠拣,但畢竟尚未完全成熟,有些需求還是得依靠我們的老大哥jQuery的游盲。

我個(gè)人對(duì)jQuery并不反感误墓,但我對(duì)jQuery生態(tài)的停滯不前相當(dāng)無(wú)奈,比如說(shuō)赫赫有名的bootstrap(特指3代)益缎,在webpack上打包還得靠個(gè)loader的谜慌,太跟不上時(shí)勢(shì)了。況且莺奔,bootstrap還算好的欣范,有些jquery插件都有一兩年沒(méi)更新了,連NPM都沒(méi)上架呢令哟,可偏偏就是找不到它們的替代品恼琼,項(xiàng)目又急著要上,這可咋辦吶屏富?

別急晴竞,今天就教你適配兼容老式j(luò)Query插件。

老式j(luò)Query插件為和不能直接用webpack打包狠半?

如果你把jQuery看做是一個(gè)普通的js模塊來(lái)加載(要用到j(luò)Query的模塊統(tǒng)統(tǒng)先require后再使用)噩死,那么,當(dāng)你加載老式j(luò)Query插件時(shí)神年,往往會(huì)提示找不到j(luò)Query實(shí)例(有時(shí)候是提示找不到$)甜滨,這是為啥呢?

要解釋這個(gè)問(wèn)題瘤袖,就必須先稍微解釋一下jQuery插件的機(jī)制:jQuery插件是通過(guò)jQuery提供的jQuery.fn.extend(object)jQuery.extend(object)這倆方法衣摩,來(lái)把插件本身實(shí)現(xiàn)的方法掛載到jQuery(也即$)這個(gè)對(duì)象上的。傳統(tǒng)引用jQuery及其插件的方式是先用<script>加載jQuery本身,然后再用同樣的方法來(lái)加載其插件艾扮;jQuery會(huì)把jQuery對(duì)象設(shè)置為全局變量(當(dāng)然也包括了$)既琴,既然是全局變量,那么插件們很容易就能找到jQuery對(duì)象并掛載自身的方法了泡嘴。

而webpack作為一個(gè)遵從模塊化原則的構(gòu)建工具甫恩,自然是要把各模塊的上下文環(huán)境給分隔開(kāi)以減少相互間的影響;而jQuery也早已適配了AMD/CMD等加載方式酌予,換句話說(shuō)磺箕,我們?cè)趓equire jQuery的時(shí)候,實(shí)際上并不會(huì)把jQuery對(duì)象設(shè)置為全局變量抛虫。說(shuō)到這里松靡,問(wèn)題也很明顯了,jQuery插件們找不到jQuery對(duì)象了建椰,因?yàn)樵谒鼈兏髯缘纳舷挛沫h(huán)境里雕欺,既沒(méi)有局部變量jQuery(因?yàn)闆](méi)有適配AMD/CMD,所以就沒(méi)有相應(yīng)的require語(yǔ)句了)棉姐,也沒(méi)有全局變量jQuery屠列。

怎么來(lái)兼容老式j(luò)Query插件呢?

方法有不少伞矩,下面一個(gè)一個(gè)來(lái)看笛洛。

ProvidePlugin + expose-loader

首先來(lái)介紹我最為推薦的方法:ProvidePlugin + expose-loader,在我公司的項(xiàng)目乃坤,以及我個(gè)人的腳手架開(kāi)源項(xiàng)目webpack-seed里使用的都是這一種方法撞蜂。

ProvidePlugin的配置是這樣的:

  var providePlugin = new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    'window.jQuery': 'jquery',
    'window.$': 'jquery',
  });

ProvidePlugin的機(jī)制是:當(dāng)webpack加載到某個(gè)js模塊里,出現(xiàn)了未定義且名稱符合(字符串完全匹配)配置中key的變量時(shí)侥袜,會(huì)自動(dòng)require配置中value所指定的js模塊蝌诡。

如上述例子,當(dāng)某個(gè)老式插件使用了jQuery.fn.extend(object)枫吧,那么webpack就會(huì)自動(dòng)引入jquery(此處我是用NPM的版本浦旱,我也推薦使用NPM的版本)。

另外九杂,使用ProvidePlugin還有個(gè)好處颁湖,就是,你自己寫(xiě)的代碼里例隆,再甥捺!也!不镀层!用镰禾!require!jQuery!啦吴侦!畢竟少寫(xiě)一句是一句嘛哈哈哈屋休。

接下來(lái)介紹expose-loader,這個(gè)loader的作用是备韧,將指定js模塊export的變量聲明為全局變量劫樟。下面來(lái)看下expose-loader的配置:

/*
    很明顯這是一個(gè)loader的配置項(xiàng),篇幅有限也只能截取相關(guān)部分了
    看不明白的麻煩去看本系列的另一篇文章《webpack多頁(yè)應(yīng)用架構(gòu)系列(二):webpack配置常用部分有哪些织堂?》:https://segmentfault.com/a/1190000006863968
 */
{
  test: require.resolve('jquery'),  // 此loader配置項(xiàng)的目標(biāo)是NPM中的jquery
  loader: 'expose?$!expose?jQuery', // 先把jQuery對(duì)象聲明成為全局變量`jQuery`叠艳,再通過(guò)管道進(jìn)一步又聲明成為全局變量`$`
},

你或許會(huì)問(wèn),有了ProvidePlugin為嘛還需要expose-loader易阳?問(wèn)得好附较,如果你所有的jQuery插件都是用webpack來(lái)加載的話,的確用ProvidePlugin就足夠了闽烙;但理想是豐滿的,現(xiàn)實(shí)卻是骨感的声搁,總有那么些需求是只能用<script>來(lái)加載的黑竞。

externals

externals是webpack配置中的一項(xiàng),用來(lái)將某個(gè)全局變量“偽裝”成某個(gè)js模塊的exports疏旨,如下面這個(gè)配置:

    externals: {
      'jquery': 'window.jQuery',
    },

那么很魂,當(dāng)某個(gè)js模塊顯式地調(diào)用var $ = require('jquery')的時(shí)候,就會(huì)把window,jQuery返回給它檐涝。

與上述ProvidePlugin + expose-loader的方案相反遏匆,此方案是先用<script>加載的jQuery滿足老式j(luò)Query插件的需要,再通過(guò)externals將其轉(zhuǎn)換成符合模塊化要求的exports谁榜。

我個(gè)人并不太看好這種做法幅聘,畢竟這就意味著jQuery脫離NPM的管理了,不過(guò)某些童鞋有其它的考慮窃植,例如為了加快每次打包的時(shí)間而把jQuery這些比較大的第三方庫(kù)給分離出去(直接調(diào)用公共CDN的第三方庫(kù)帝蒿?),也算是有一定的價(jià)值巷怜。

imports-loader

這個(gè)方案就相當(dāng)于手動(dòng)版的ProvidePlugin葛超,以前我用requireJS的時(shí)候也是用的類似的手段,所以我一開(kāi)始從requireJS遷移到webpack的時(shí)候用的也是這種方法延塑,后來(lái)知道有ProvidePlugin就馬上換了哈绣张。

這里就不詳細(xì)說(shuō)明了,放個(gè)例子大家看看就懂:

// ./webpack.config.js

module.exports = {
    ...
    module: {
        loaders: [
            {
                test: require.resolve("some-module"),
                loader: "imports?$=jquery&jQuery=jquery", // 相當(dāng)于`var $ = require("jquery");var jQuery = require("jquery");`
            }
        ]
    }
};

總結(jié)

以上的方案其實(shí)都屬于shimming关带,并不特別針對(duì)jQuery侥涵,請(qǐng)舉一反三使用。另外,上述方案并不僅用于shimming独令,比如用上ProvidePlugin來(lái)寫(xiě)少幾個(gè)require端朵,自己多多挖掘,很有樂(lè)趣的哈~~

示例代碼

諸位看本系列文章燃箭,搭配我在Github上的腳手架項(xiàng)目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed)冲呢。

附系列文章目錄(同步更新)

本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上猖凛,非經(jīng)作者同意赂蠢,請(qǐng)勿轉(zhuǎn)載。
原文地址:https://segmentfault.com/a/1190000006887523
如果您對(duì)本系列文章感興趣辨泳,歡迎關(guān)注訂閱這里:https://segmentfault.com/blog/array_huang

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末虱岂,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子菠红,更是在濱河造成了極大的恐慌第岖,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件试溯,死亡現(xiàn)場(chǎng)離奇詭異绍傲,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)耍共,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)烫饼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人试读,你說(shuō)我怎么就攤上這事杠纵。” “怎么了钩骇?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵比藻,是天一觀的道長(zhǎng)铝量。 經(jīng)常有香客問(wèn)我,道長(zhǎng)银亲,這世上最難降的妖魔是什么慢叨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮务蝠,結(jié)果婚禮上拍谐,老公的妹妹穿的比我還像新娘。我一直安慰自己馏段,他們只是感情好轩拨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著院喜,像睡著了一般亡蓉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上喷舀,一...
    開(kāi)封第一講書(shū)人閱讀 51,610評(píng)論 1 305
  • 那天砍濒,我揣著相機(jī)與錄音,去河邊找鬼硫麻。 笑死爸邢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的庶香。 我是一名探鬼主播甲棍,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼简识,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼赶掖!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起七扰,我...
    開(kāi)封第一講書(shū)人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤奢赂,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后颈走,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體膳灶,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年立由,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了轧钓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锐膜,死狀恐怖毕箍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情道盏,我是刑警寧澤而柑,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布文捶,位于F島的核電站,受9級(jí)特大地震影響媒咳,放射性物質(zhì)發(fā)生泄漏粹排。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一涩澡、第九天 我趴在偏房一處隱蔽的房頂上張望顽耳。 院中可真熱鬧,春花似錦筏养、人聲如沸斧抱。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)辉浦。三九已至,卻和暖如春茎辐,著一層夾襖步出監(jiān)牢的瞬間宪郊,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工拖陆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弛槐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓依啰,卻偏偏與公主長(zhǎng)得像乎串,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子速警,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容