摘要:所以通常情況下當你的庫需要依賴到例如,這樣的通用模塊時,我們可以不將它打包進,而是在的配置中聲明這就是在告訴請不要將這個模塊注入編譯后的文件里,對于我源代碼里出現的任何這個模塊的語句,請將它保留。
這篇文章討論Webpack打包library時經常需要用到的一個選項external,它用于避免將一些很通用的模塊打包進你發(fā)布的library里,而是選擇把它們聲明成external的模塊,在你的library被上層使用后,在最后階段由Webpack統(tǒng)一把這個external的依賴模塊打包進來。
external選項一般都是用在打包library上面,如果不是library而是一個最終的app的發(fā)布JS文件,那external也沒有什么意義。關于Webpack打包library的分析和一些選項的作用,我在前一篇文章做了討論。
external選項我們仍然使用前一篇文章的例子,定義一個庫util.js:
import $ from "jquery" function hideImages() { $("img").hide(); } export default { "hideImages": hideImages }
我們使用Webpack打包發(fā)布這個庫:
// 入口文件 entry: { util: "./util.js", } // 輸出文件 output: { path: "./dist", filename: "[name].dist.js" library: "util", libraryTarget: commonjs2, targetExport: "default" }
這樣打包出來的util.dist.js文件會把jquery的代碼完整地注入進去,因為你的源代碼使用到了它。但是這往往并不是我們希望的,因為jquery是很通用的模塊,在一個app中,很可能其它的庫也會用到它,最頂層的入口文件app也可能用到它,如果每一個庫模塊的發(fā)布版本都將jquery原封不動地打包進了自己的bundle,最后拼到一起,在最終的app發(fā)布代碼里就會有很多份jquery的復制,當然這可能并不會影響它的正常功能,但是會占據很大的代碼體積。
所以通常情況下當你的庫需要依賴到例如jquery,bootstrap這樣的通用JS模塊時,我們可以不將它打包進bundle,而是在Webpack的配置中聲明external:
externals: { jquery: { root: "jquery", commonjs: "jquery", commonjs2: "jquery", amd: "jquery", }, },
這就是在告訴Webpack:請不要將這個模塊注入編譯后的JS文件里,對于我源代碼里出現的任何import/require這個模塊的語句,請將它保留。
我們可以看一下編譯后的bundle文件的結構:
module.exports = (function(modules) { var installedModules = {}; function webpack_require(moduleId) { // ... } return webpack_require("./util.js"); }) ({ "./util.js": generated_util, // "/path/to/jquery.js": generated_jquery 原本有這一行,現在被刪去。 });
可以看到jquery模塊沒有被打包進bundle文件,而對于util,它的生成代碼即generated_util函數中關于import jquery相關的語句也被保留了原意:
function generated_util(module, exports, webpack_require) { var $ = require("jquery"); // util的其它源代碼 // ... }
當然也并非完全沒有修改,例如將import的改回了傳統(tǒng)的require關鍵詞,因為我們這里用的是CommonJS風格的打包方式。不過這些都是次要的,關鍵是它保留了require這個關鍵詞,而沒有使用webpack_require將jquery真的引入進來。這就是說,當前的這個JS文件的模塊管理系統(tǒng)中是沒有jquery的,它是一個external的模塊,需要在這個JS文件被其它人引用并且在上層編譯時,jquery才可能被真的引入進來,到那個時候這里的require關鍵詞才會被替換為webpack_require。
對于external的依賴模塊,通常你可以這樣做,例如你使用npm發(fā)布你的庫,你可以將jquery在package.json文件中添加到dependencies,這樣別人npm install你發(fā)布的庫時,jquery也會被自動下載到node_modules供別人打包使用。
如果我們使用umd格式打包,我們可以看到在不同環(huán)境中,external模塊是如何發(fā)揮作用的:
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === "object" && typeof module === "object") // commonjs2 module.exports = factory(require("jquery")); else if(typeof define === "function" && define.amd) define("util", ["jquery"], factory); // amd else if(typeof exports === "object") exports["util"] = factory(require("jquery")); // commonjs else root["util"] = factory(root["jquery"]); // var }) (window, function(__webpack_external_module_jquery__) { return (function(modules) { var installedModules = {}; function webpack_require(moduleId) { // ... } return webpack_require("./util.js"); }) ({ "./util.js": generated_util, }); }
而generated_util也相應地增加一個參數__webpack_external_module_jquery__:
function generated_util(module, exports, webpack_require, __webpack_external_module_jquery__) { var $ = __webpack_external_module_jquery__; // util的其它源代碼 // ... }
這樣的寫法似乎結構和上面的CommonJS的編譯版本不太一樣,但實際上本質是一樣的。因為現在umd要照顧到不同的運行環(huán)境,所以它把require("jquery")提前了,作為factory的參數傳入。對于每種運行環(huán)境,各有各的做法:
CommonJS:保留require("jquery")語句。
AMD:在define中將jquery定義為依賴模塊。
Var:從全局域中取出jquery變量,這需要jquery在該模塊之前就已經被加載。
然后不管是哪種情況,它們都將載入后的jquery模塊作為參數傳入factory函數,這樣就能正確加載util模塊了。
以上涉及到Webpack生成代碼的部分可能有點繞,需要你比較了解Webpack打包模塊的機制和原理,關于這部分我在這篇文章里做了詳細討論。
總結以上就是關于Webpack的external選項的使用,并且從編譯后的JS代碼分析了它到底是如何起作用的。我想閱讀Webpack相關的生成代碼還是很重要的,這樣才算是真正地理解了external的機制,在碰到一些坑時才能知道怎么去debug。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.hztianpu.com/yun/93327.html
摘要:但是,隨者工程開發(fā)的復雜程度和代碼規(guī)模不斷地增加,暴露出來的各種性能問題也愈發(fā)明顯,極大的影響著開發(fā)過程中的體驗。對應的資源也可以直接由頁面外鏈載入,有效地減小了資源包的體積。 背景 如今前端工程化的概念早已經深入人心,選擇一款合適的編譯和資源管理工具已經成為了所有前端工程中的標配,而在諸多的構建工具中,webpack以其豐富的功能和靈活的配置而深受業(yè)內吹捧,逐步取代了grunt和gu...
摘要:每一個模塊的源代碼都會被組織在一個立即執(zhí)行的函數里。接下來看的生成代碼可以看到,的源代碼中關于引入的模塊的部分做了修改,因為無論是,或是風格的,都無法被解釋器直接執(zhí)行,它需要依賴模塊管理系統(tǒng),把這些抽象的關鍵詞具體化。 現在前端用Webpack打包JS和其它文件已經是主流了,加上Node的流行,使得前端的工程方式和后端越來越像。所有的東西都模塊化,最后統(tǒng)一編譯。Webpack因為版本的...
摘要:所以你編譯后的文件實際上應當只輸出,這就需要在配置里用來控制這樣上面的模塊加載函數會在返回值后面加一個,這樣就只返回的部分。 之前一篇文章分析了Webpack打包JS模塊的基本原理,所介紹的案例是最常見的一種情況,即多個JS模塊和一個入口模塊,打包成一個bundle文件,可以直接被瀏覽器或者其它JavaScript引擎執(zhí)行,相當于直接編譯生成一個完整的可執(zhí)行的文件。不過還有一種很常見的...
摘要:因此,你還是需要各種各樣雜七雜八的工具來轉換你的代碼噢,我可去你媽的吧,這些東西都是干嘛的我就是想用個模塊化,我到底該用啥子本文正旨在列出幾種可用的在生產環(huán)境中放心使用模塊化的方法,希望能幫到諸位后來者這方面的中文資源實在是忒少了。 原文發(fā)表在我的博客上。最近搗鼓了一下 ES6 的模塊化,分享一些經驗 :) Python3 已經發(fā)布了九年了,Python 社區(qū)卻還在用 Python 2...
摘要:和類似的預處理器還有等。的用處非常多,包括給自動加前綴使用下一代語法等,目前越來越多的人開始用它,它很可能會成為預處理器的最終贏家。 webpack實戰(zhàn) 查看所有文檔頁面:全棧開發(fā),獲取更多信息。快馬加鞭,加班加點,終于把這個文檔整理出來了,順便深入地學習一番,鞏固知識,就是太累人,影響睡眠時間和質量。極客就是想要把事情做到極致,開始了就必須到達終點。 原文鏈接:webpack實戰(zhàn),原...
閱讀 1303·2023-04-26 02:20
閱讀 3425·2021-11-22 14:45
閱讀 4330·2021-11-17 09:33
閱讀 1096·2021-09-06 15:00
閱讀 1557·2021-09-03 10:30
閱讀 4027·2021-07-26 22:01
閱讀 1067·2019-08-30 15:54
閱讀 602·2019-08-30 15:43