日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

自己的模块给其他人调用是怎么打包的_webpack实战——模块打包

發布時間:2025/3/20 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自己的模块给其他人调用是怎么打包的_webpack实战——模块打包 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

寫在前面

這是webpack實戰系列的第二篇:模塊和模塊打包。上一篇:webpack實戰——打包第一個應用?記錄了webpack的一些基礎內容與一個簡單的小例子,開啟了webpack的實戰之路,這一篇記錄一下關于模塊和模塊打包。

模塊

先看一下模塊的定義:

模塊,是能夠單獨命名并獨立地完成一定功能的程序語句的集合(即程序代碼和數據結構的集合體)。它具有兩個基本的特征:外部特征和內部特征。外部特征是指模塊跟外部環境聯系的接口(即其他模塊或程序調用該模塊的方式,包括有輸入輸出參數、引用的全局變量)和模塊的功能;內部特征是指模塊的內部環境具有的特點(即該模塊的局部數據和程序代碼)。

可以從定義中看出,每個獨立的模塊負責不同工作,彼此之間又可以聯系在一起共同保證整體系統運行。那么在webpack中,如何將其打包成一個(或多個)文件呢?

想了解這些,我們還是先要熟悉在 Javascript 中的模塊。在 Javascript 模塊化中比較常見的有:

?CommonJS?ES6 module?AMD?CMD?UMD(AMD和CommonJS)?...

但由于在目前的使用場景中?CommonJS?和?ES6 module?居多,因此暫時就這兩者進行討論。

1. CommonJS

1.1 模塊

在 CommonJS 中規定每個文件都是一個模塊。

在 CommonJS 中,變量及函數的聲明不會造成全局污染。如:

// add.jsvar name = 'name: add.js';// index.jsvar name = 'name: index.js';reuqire('./add.js');console.log(name); // name: index.js

在上面 index.js 中通過 require 函數來加載 add.js ,輸出的結果是?name: index.js?,說明在 add 中定義的變量并不會影響 index ,可以得出使用 CommonJs 模塊,作用域只針對于該模塊,而不會造成全局污染,對外不可見

1.2 導出

前面說過模塊擁有自己的作用域,那么模塊是需要向外傳遞的,怎么辦呢??導出是一個模塊向外暴露自身的唯一方式。在 CommonJS 中,我們通過?module.exports?來導出模塊中的內容。如:

// add.jsmodule.exports = { name: 'add', add: function(a, b) { return a + b; }}

在 CommonJS 內部會有一個 module 對象用于存放當前模塊的信息。而 module.exports 則指定向外暴露的內容。

1.3 導入

導出自然是為了另外一個模塊來使用,這時便使用到了導入功能。在 CommonJS 中,使用 require 來進行模塊導入:

// add.jsmodule.exports = { name: 'add', add: function(a, b) { return a + b; }}// index.jsconst add = require('./add.js');const sum = add.add(1, 2);console.log(sum); // 3

上面這個例子,便是在 index.js 中通過 require 導入了 add.js ,并且調用了其中的 add() 方法。

而我們在 reuqire 一個模塊的時候,會分兩種情況:

1.如果 require 的模塊第一次被加載,那么會執行該模塊然后導出內容;2.如果非首次加載,那么該模塊代碼不會再次執行,而是直接導出上次代碼執行后所得到的結果。

有時候我們只想通過加載執行某個模塊讓它產生某種作用而不需要獲取它所導出的內容,則可以直接通過 require 來導入而不需要定義:

require('./task.js');...

而通過這個特性,加上 require 函數可以接收表達式,那么我們則可以動態指定模塊加載路徑:

const moduleList = ['add.js', 'subtract.js'];moduleList.forEach(item => { require(`./${item}`);});

2. ES6 Module

熟悉 JavaScript 語言的小伙伴知道,其實在 JavaScript 設計之初,并沒有模塊化這個概念。而伴隨 JavaScript 不斷的壯大發展,社區中也涌現出了不少模塊化概念。一直到 ES6 , JavaScript 終于正式的有了模塊化這一特性。

2.1 模塊

在前面我們使用 CommonJS 實現了一個例子來展示 CommonJS 的模塊、導出與導入,同樣在此處也先來一個例子,只需將上面例子稍微改寫即可:

// add.jsexport default { name: 'add', add: function(a, b) { return a + b; }}// index.jsimport add from './add.js';const sum = add.add(-1, 1);console.log(sum); // 0

ES6 Module 也是將每一個文件都作為一個模塊,并且每個模塊擁有自身的作用域,但是與 CommonJS 相比, 不同的是導入、導出語句。在 ES6 Module 中, import 和 export 也作為關鍵字被保留。

2.2 導出

在 ES6 Module 中,使用 export 來對模塊進行導出。

export 導出的兩種方式:

?命名導出?默認導出

2.2.1 命名導出

以下有兩種寫法,但其效果并無區別:

/*** 命名導出: 兩種寫法**/// 1. 聲明和導出寫在一起export const name = 'add';export const add = function(a, b) { return a + b;}// 2. 先聲明,再統一導出const name = 'add';const add = function(a, b) { return a + b;}export { name, add }

as關鍵字

在使用命名導出時,如果用寫法2(先聲明再統一導出),可以使用?as 關鍵字?來對導出的變量進行重命名。如:

const name = 'add';const add = function(a, b) { return a + b;}// add as sum : 在導入時,使用 name 和 sum 即可export { name, add as sum }

2.2.2 默認導出

說完了命名導出,來到默認導出:模塊的默認導出只能導出一個。舉例:

// 默認導出export defailt { name: 'add', add: function(a, b) { return a + b; }}

由上可見,我們可以將默認導出理解為向外輸出了一個命名為 default 的變量。

2.3 導入

ES6 Module 中使用 import 進行模塊導入。由于在 ES6 Module 的導出中,分為?命名導出?和?默認導出?,因此在導入的時候也有對應的兩種方式進行導入。

2.3.1 命名

// add.jsconst name = 'add';const add = function(a, b) { return a + b;}export { name, add }// index.jsimport { name, add } from './add.js';console.log(name, add(1, 2)); // add 3

可以看到,在使用 import 對命名導出模塊進行引入的時候, import 后面跟了一對花括號?{ }?將導入的變量名包裹起來,并且變量名需要與導出時的變量命名一樣。同樣,我們還是可以使用?as 關鍵字?來對變量進行重命名:

// index.jsimport { name, add as sum } from './add.js'sum(2, 2); // 4

值得注意的是,導入變量的效果相當于在當前作用域下聲明了變量(如 name 和 add),但不可對這些變量不能修改,只可當成只讀的來使用。

當然,我們還可以使用?*?來進行整體導入:

// index.jsimport * as add from './add.js';console.log(add.name); // addconsole.log(add.add(1, 1)); // 2

2.3.2 默認

對于默認導出的導入處理如下:

// add.jsexport default { name: 'add', add: function(a, b) { return a + b; }}// index.jsimport addMe from './add.js';console.log(addMe.name, addMe.add(2, 5)); // add 7

可以看到,如果是導入默認導出的模塊,那么在 import 后面直接跟變量名即可,并且這個變量名無需與導出模塊的變量名重復,可以自己指定新的變量名。

3. CommonJS 與 ES6 Module 的區別

介紹了 CommonJS 與 ES6 Module 的基礎應用之后,我們也要了解到在實際的開發過程中我們經常將這兩者在同一個項目中混用。為了避免不必要的麻煩,還是要說一下兩者的異同。

3.1 動態與靜態

CommonJS 對模塊依賴的解決是動態的,而 ES6 Module 對模塊依賴的解決是靜態的。

首先要了解這里說的動態與靜態是什么:

?動態:模塊依賴關系的建立發生在代碼運行階段;?靜態:模塊依賴關系的建立發生在代碼編譯階段;

由于 ES6 Module 中導入導出語句都是聲明式的,不支持導入表達式類路徑,并且導入導出語句必須位于模塊的頂層作用域。相比 CommonJS ,具備優勢如下:

?死代碼檢測和排除:可以使用靜態分析工具檢測出沒有被調用的模塊,減小打包資源體積;?模塊變量類型檢查:有助于確保模塊之間傳遞的值或者接口類型的正確性;?編譯器優化:ES6 Module 直接導入變量,減少層級引用,程序效率更高。

3.2 值拷貝和動態映射

在導入一個模塊時,對于 CommonJS 來說獲取的是一份導出值的拷貝,而在 ES6 Module 中則是值的動態映射,這個映射是只讀的。例如:

// add.jsvar count = 0;module.exports = { count: count, add: function(a, b) { count += 1; return a + b; }}// index.jsvar count = require('./add.js').count;var add = require('./add/js').add;console.log(count); // 0 (這里的count是對add.js中couunt的拷貝)add(2, 3);console.log(count); // 0 (add.js中變量值的改變不會對這里的拷貝值造成影響)count += 1;console.log(count); // 1 (拷貝的值 0 + 1 = 1,表示拷貝的值可以更改)

可以看出,index.js 中的 count 是 add.js 中 count 的一份值拷貝,因此在調用 add 函數時,即便更改了 add 中的 count,但不會對 index.js 中的值拷貝造成影響。

但在 ES6 Module 中,卻不一樣:

// add.jslet count = 0;const add = function(a, b) { count += 1; return a + b;};export { count, add };// index.jsimport { count, add } from './add.js';console.log(count); // 0 (對add.js中count值的映射)add(1, 1);console.log(count); // 1 (對add.js中count值的映射,會映射值的變化)count += 1; // 報錯,該count值不可更改

4. 模塊打包原理

前面描述了一些基礎的 CommonJS 與 ES6 Module 模塊化的一些知識,那么回到 webpack 中來:webpack是如何將各種模塊有序的組織在一起的呢?

// add.jsmodule.exports = { add: function(a, b) { return a + b; }}// index.jsconst add = require('./add.js');const sum = add(1, 2);console.log(`sum: ${sum}`);

還是之前的例子,但現在經過 webpack 打包之后,它會變成什么樣子呢?

bundle.js

如圖所示,這便是一個簡單的打包結果。我們可以觀察自己的 bundle.js 文件,從中看打包邏輯關系:

?首先一個立即執行匿名函數,包裹所有內容,構成自身作用域;?installedModule對象(模塊緩存),每個模塊在第一次被加載的時候執行,到處結果存儲到其中,以后再次調用模塊直接取值即可,不會再次執行模塊;?webpack_require函數:對模塊加載的實現,在瀏覽器中可以通過調用此函數加模塊id來進行模塊導入;?modules對象:工程中所有產生依賴關系的模塊都會以?key-value?形式放在此對象中, key 作為模塊 id,由數字或者 hash 字符串構成,value 則由一個匿名函數包裹的模塊構成,匿名函數的參數則賦予了每個模塊導出和導入能力。

小結

本篇記錄了關于 JavaScript 的模塊化與 webpack 的模塊打包原理簡介。

首先,介紹了關于模塊的概念,然后依次介紹了兩種模塊化:CommonJS 和 ES6 Module ,以及他們分別的模塊概念、導出和導入,接著介紹了他們之間的兩個差異:動態與靜態、值拷貝和映射。最后,提及了一下模塊化打包的簡單原理,對webpack打包工作有一個大概認知。

下一篇將會介紹在webpack中資源的輸入與輸出。敬請期待。

學習推薦:?本系列學習資源多來自于?《webpack實戰 入門、進階與調優》?,作者?居玉皓?, 感興趣的朋友可以購買實體書支持學習~

webpack實戰——打包第一個應用?

常用驗證碼之滑動驗證碼|圖形驗證碼

docker-nginx部署web項目

總結

以上是生活随笔為你收集整理的自己的模块给其他人调用是怎么打包的_webpack实战——模块打包的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。