搜尋
首頁web前端js教程使用webpack模組給Library打包原理及實現

使用webpack模組給Library打包原理及實現

May 31, 2018 pm 01:53 PM
librarywebwebpack

這篇文章主要介紹了webpack組織模組打包Library的原理及實現,現在分享給大家,也給大家做個參考。

先前一篇文章分析了Webpack打包JS模組的基本原理,所介紹的案例是最常見的一種情況,即多個JS模組和一個入口模組,打包成一個bundle文件,可以直接被瀏覽器或其它JavaScript引擎執行,相當於直接編譯產生一個完整的可執行的檔案。不過還有一個很常見的情況,就是我們要建立發佈一個JavaScript的函式庫,像是你在npm社群發佈自己的函式庫,這時Webpack就需要對應的配置,編譯產生的程式碼也會略有不同。

和之前一篇文章一樣,本文主要分析的是Webpack的生成程式碼,並結合它來說明編譯函式庫時Webpack那些關於library的設定選項的具體作用,相應的官方文件在這裡。

寫JS的函式庫

我們還是從簡單的案例開始,我們隨便寫一個簡單的函式庫util.js:

import $ from 'jquery'

function sayHello() {
 console.log("Hello");
}

function hideImages() {
 $('img').hide();
}

export default {
 sayHello: sayHello,
 hideImages: hideImages
}

提供了兩個函數,當然它們之間毫無關係,也實際上沒有任何卵用,純粹是僅供教學參考。 。 。

接下來寫Webpack的設定:

// 入口文件
entry: {
 util: './util.js',
}

// 输出文件
output: {
 path: './dist',
 filename: '[name].dist.js'
}

但僅僅這樣是不夠的,這樣輸出的檔案就是一個立即執行的函數,最後會回到util.js的exports,參考上一篇文章中分析,最後產生的bundle程式碼結構大致上是這樣的:

(function(modules) {
 var installedModules = {};
 
 function webpack_require(moduleId) {
   // ...
 }

 return webpack_require('./util.js');
}) ({
 './util.js': generated_util,
 '/path/to/jquery.js': generated_jquery
});

##它如果執行完,那就結束了,將util.js的export部分回傳而已,而我們需要的是將這個回傳值交給編譯後的檔案的module.export,這樣編譯後的檔就成了一個可以被別人import的庫。所以我們希望得到的編譯檔應該是這樣的:

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
});

#要得到這樣的結果,Webpack設定output部分需要加入library資訊:

// 入口文件
output: {
 path: './dist',
 filename: '[name].dist.js',

 library: 'util',
 libraryTarget: commonjs2
}

這裡最重要的就是libraryTarget,我們現在採用commonjs2的格式,就會得到上面的編譯結果,也就是說Webpack會library把最後的輸出以CommonJS的形式export出來,這樣就實現了一個函式庫的發布。

其它發布格式

除了commonjs2,libraryTarget還有其它選項:

var (默认值,发布为全局变量)
commonjs
commonjs2
amd
umd

使用不同的選項,編譯出來的檔案就能夠在不同JavaScript執行環境中使用。這裡我們直接看萬金油umd格式的輸出是怎麼樣的:

(function webpackUniversalModuleDefinition(root, factory) {
 if(typeof exports === 'object' && typeof module === 'object') // commonjs2
  module.exports = factory();
 else if(typeof define === 'function' && define.amd)
  define("util", [], factory); // amd
 else if(typeof exports === 'object')
  exports["util"] = factory(); // commonjs
 else
  root["util"] = factory(); // var
}) (window, function() {
 return (function(modules) {
  var installedModules = {};
  function webpack_require(moduleId) {
    // ...
  }
  return webpack_require('./util.js');
 }) ({
  './util.js': generated_util,
  '/path/to/jquery.js': generated_jquery
 });
}

比之前的commonjs2的情況要複雜得多,因為它需要處理各種不同的case,但其實後面的部分都是一樣的,最重要的就是最前面的幾行,這是umd模組的標準寫法。它運行傳入的factory函數,實際上就是載入模組的函數,然後把傳回的結果根據不同的運行環境交給對應的物件。例如var,那就會把結果設為一個全域變量,這用於瀏覽器透過<script>標籤直接匯入該JS檔;如果是CommonJS,它則交給exports物件;如果是AMD環境,它也是用標準的AMD的寫法。這樣這個發佈出來的JS函式庫就可以在任意的環境中都能被其他人使用。 <p>targetExport控制輸出內容<p>如果用umd格式打包,可能會有一個坑需要注意,如果你的函式庫的原始碼是用ES6格式export default來輸出的,正如上面的例util.js,你直接把編譯後的JS函式庫檔案放到瀏覽器中使用,可以是<script>,或是RequireJS,可能不會得到你想要的結果。這是因為你的JS檔案回傳給你的物件是這樣的:<p><p class="jb51code"><pre class='brush:php;toolbar:false;'>{ &amp;#39;default&amp;#39;: { sayHello: sayHello, hideImages: hideImages } }</pre><p>而不是你所期望的:<p><p class="jb51code"><pre class='brush:php;toolbar:false;'>{ sayHello: sayHello, hideImages: hideImages }</pre><p>不僅是瀏覽器,在不支援ES6的模組系統中同樣會出這個問題,就是因為它們並不認識default。所以你編譯後的JS檔其實要當只輸出default,這就需要在Webpack配置裡用targetExport來控制:<p>library: 'util',<p>libraryTarget: umd,<br/>targetExport: 'default'<br/>這樣上面的模組載入函數factory會在回傳值後面加上一個['default'],這樣就只回傳exports的default部分。 <p>這個坑在umd格式下其實還是挺容易踩到的,例如你發布一個Vue元件,.vue檔案中的JavaScript部分一般都是把Component物件以export default的格式導出的,就像這樣:<p><p class="jb51code"><pre class='brush:php;toolbar:false;'>export default { name: &amp;#39;xxx&amp;#39;, data: { return // ... }, props: { // ... } methods: { // ... } }</pre><p>如果你把編譯後的JS檔直接放在瀏覽器裡運行,並且用CDN的方式透過<script>載入Vue,你會發現Vue無法辨識這個Component,因為你得到的這個物件多了一層不必要的default。 <p><p>你可能會問如果我把輸出內容改成了default,會不會影響這個模組在ES6環境下的使用?一般來說是不會的。之前一篇文章已經談到,Webpack的生成程式碼在引入一個模組時,會透過一個叫__esModule的值來設定和判斷它是不是ES6格式的export,現在如果只導出default部分,那麼這個物件是被視為非ES6的,因為它不含__esModule。這樣其它模組透過import來引入這個模組時,會引入整個對象,這實際上變相地就等價於只引入原模組的export default部分。 <p>當然以上討論的前提是,你所有需要export的內容全部都在export default裡。如果你既有default,又有正常的export,那編譯後的檔案只匯出default部分顯然是不行的。 <p>上面是我整理給大家的,希望今後對大家有幫助。 <p>相關文章:<p><a href="http://www.php.cn/js-tutorial-399225.html" target="_blank">200行程式碼實作blockchain 區塊鏈實例詳解<br/><p><a href="http://www.php.cn/js-tutorial-399226.html" target="_blank">vue使用facebook twitter分享範例<br/><p><a href="http://www.php.cn/js-tutorial-399224.html" target="_blank">react以create-react-app為基礎建立專案<br/><p><p class="clearfix"><span class="jbTestPos"></script>

以上是使用webpack模組給Library打包原理及實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript引擎:比較實施JavaScript引擎:比較實施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

如何使用Next.js(前端集成)構建多租戶SaaS應用程序如何使用Next.js(前端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript:探索網絡語言的多功能性JavaScript:探索網絡語言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的演變:當前的趨勢和未來前景JavaScript的演變:當前的趨勢和未來前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

神秘的JavaScript:它的作用以及為什麼重要神秘的JavaScript:它的作用以及為什麼重要Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python還是JavaScript更好?Python還是JavaScript更好?Apr 06, 2025 am 12:14 AM

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。1.Python以简洁语法和丰富库生态著称,适用于数据分析和Web开发。2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)