隨著現代 Web 開發,我們要么使用 require 要么使用 import 引用 JAVAScript 依賴項。有時,我們將兩者結合使用。
但是,你知道為什么這兩者都存在嗎? 使用一種或另一種時的最佳實踐是什么?
在本文中,我將討論使用 require 和 import 并回答其中一些常見問題。
背景——JavaScript 模塊類型
在討論 require 和 import 之前,有必要對 JavaScript 模塊有一定的了解。 那么,讓我們看看有哪些不同類型的 JavaScript 模塊可用。
1. AMD——異步模塊定義
引入了 AMD 模塊以使模塊更加前端友好。 它們不需要任何打包器,并且所有依賴項都是動態解析的。
AMD使用 require 函數用于加載外部模塊,并且能夠充當 CommonJS 模塊的包裝器。
define("exampleModule", [], () => {
return {
print: () => console.log("Hello World!");
}
}
define("main", ["require", "exampleModule"], (require) => {
const exampleModule= require("exampleModule");
exampleModule.print();
});
但是,隨著 ES 模塊的引入,AMD 的使用量急劇減少。
2. CommonJS 模塊
CommonJS 是 NodeJS 用來在模塊中封裝 JavaScript 的標準。 module.exports用于導出 CommonJS 模塊,以及 import 函數用于將模塊包含到單獨的文件中。
盡管 CommonJS 模塊在 NodeJS 中被廣泛使用,但在前端開發中并沒有使用它們。 這背后的主要原因是require函數的同步行為。
但是,NodeJS 從 v13 開始才開始支持 ES 模塊。 在那之前,大多數 NodeJS 模塊,包括 NPM 庫,都是使用 CommonJS 模塊開發的。
因此,CommonJS 模塊仍然在開發人員中廣泛使用。
而且,CommonJS 模塊與 ES 模塊同樣重要,我將在本文接下來的部分中討論更多。
3.UMD——通用模塊定義
UMD 是 AMD 和 CommonJS 的組合。 它使用了 AMD 的 CommonJS 語法和異步加載技術,使其適用于服務器端和客戶端。
UMD 在 Webpack 等打包器中用作回退模塊,下面顯示了一個簡單的 UMD 模塊示例:
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define(["jquery"], factory); // AMD } else if (typeof exports === "object" ) { module.exports = factory(require("jquery")); //CommonJS } else { root.returnExports = factory(root.jQuery); }
})(this, function ($) {
function exampleFunction() {}
return exampleFunction;
});
4. ESM — ES 模塊
ES Modules (ECMAScript Modules) 是 JavaScript 中使用的官方標準。 ES 模塊使用 import和 export 處理模塊的語句。 它解決了 CommonJS 的最大限制之一,即同步加載。
在引入 ES Modules 之后,開發者之間有很多爭論,考慮到與 CommonJS 的兼容性。 但是,開發人員已經適應使用這兩種方法,我們將在接下來的部分中討論更多詳細信息。
已經了解了 JavaScript 模塊的背景,那么讓我們繼續討論 require 和 import.
“Require” 是 NodeJS 內置的
require通常與 NodeJS 一起使用來讀取和執行 CommonJS 模塊。
這些模塊可以是內置模塊,如 http或自定義編寫的模塊。 使用 require,可以將它們包含在 JavaScript 文件中并使用它們的函數和變量。
// 內置模塊
const http= require('http');
// 本地模塊
const getBlogName = require('./blogDetails.js')
但是,如果要使用 require 要獲取本地模塊,首先需要使用 module.exports 導出它們.
例如,假設您有一個名為 blogDetails.js,并且您需要使用該文件中的函數 index.js文件。
// blogDetails.js
const getBlogTitle = (name, author) => {
return name + " by " + author;
}
modules.export = getBlogTitle;
// index.js
const getBlogTitle = require('./blogDetails.js');
var title = getBlogTitle ('Require vs Import in JavaScript', 'Chameera Dulanga');
還可以使用一次導出多個模塊 modules.export 如下:
const getBlogTitle = (name, author) => {
return name + " by " + author;
}
const getBlogContent = () => {
return content
}
modules.export = {
getBlogTitle,
getBlogContent,
};
注意: 如果最后不是使用 modules.export,可以附加 exports 。 例如: exports.getBlogContent = () => {};
我想現在你明白什么時候應該使用 require以及它是如何工作的。 接下來讓我們看看如何 import 。 然后我們將能夠以更深層次的理解來比較和對比它們。
“import”是在 ES6 模塊中引入的
import 是一個 ES 模塊,并帶有 export,它們被稱為 ES6 import 和 export.
我們不能用 import 或導出到 ES 模塊之外。
試圖 import ES 模塊之外是一個常見的開發人員錯誤。
如果我舉同樣的例子,我需要做的唯一改變就是修改 modules.export到 export default.
const getBlogTitle = (name, author) => {
return name + " by " + author;
}
export default getBlogTitle;
然后我們可以使用 import 將此文件包含在我們的 index.js文件。
import getBlogTitle from "./blogDetails.js";
var title = getBlogTitle ('Require vs Import in JavaScript', 'Chameera Dulanga');
注意: 類似于 require,還可以通過將導出附加到每個函數定義來單獨導出每個函數。
例如: export const = getBlogContent = () => {};
所以,我想你現在明白應該如何以及何時使用 require和 import。但是,這還不是全部; 它們的功能和用法存在一些顯著差異。 是時候進行比較了。
require Vs import
require 和 import 都用于包含模塊。 但是它們有幾個應該注意的重要功能。
1. require 語句可以在代碼的任何地方調用
import 語句只能在文件的開頭定義。 定義一個 import 其他地方的語句會給你一個錯誤或自動轉移到文件的開頭。
2. require 可以有條件地調用
聲明 require 時,當加載的模塊名稱未預定義時,允許有條件地或動態地加載模塊。
例如,你可以調用 require 在函數或 if 條件中,如下所示:
if(articleCount>0){
const getBlogTitle = require(‘./blogDetails.js’);
}
require語句具有這種靈活性,因為它們被視為函數。 它們在運行時被調用,在此之前沒有辦法知道任何事情。 但, import 語句是靜態的,我們不能有條件地或動態地使用它們。
注意: 由于 import 語句是靜態的,所以可以在運行應用程序之前檢測到任何錯誤
3. import 語句是異步的
在小型應用程序中,同步或異步可能不會發揮主要作用。 但是,如果我們考慮大型應用程序,則會使用數百個模塊。 所以,如果你使用 require, 模塊將被一 一加載和處理。
而 import 語句通過異步工作解決了這個問題,這比 require 在大規模應用中更能發揮作用。
4. ES 模塊是未來
正如我們所討論的,ES 模塊系統是作為維護客戶端 JavaScript 模塊的標準引入的。 TypeScript 也采用了它,并添加了用于定義 Type 的內容。 因此,我不認為 require可以再次取代 ES,因為它已成為開發人員中廣泛使用的標準。
但是由于有大量的 NodeJS 模塊和庫是用 CommonJS 編寫的,我們不能保留 require完全放在一邊。 所以我們必須相應地使用它們。
如果你使用的是 TypeScript,則可以通過配置 tsconfig.json文件。 例如,假設我們需要輸出一個使用 CommonJS 的代碼版本。
需要做的就是創建一個新的 tsconfig 通過擴展原始文件用于 CommonJS 輸出 tsconfig文件并修改 module下參數 CompilerOptions.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "CommonJS",
"outDir": "./lib/cjs"
},
}
注意: 還可以使用 Webpack 等構建工具將 ES 模塊轉換為 CommonJS 模塊。
以下表格為比較兩者
特征 |
require |
import |
語法 |
const x=require() |
import x from './' |
模塊 |
CommonJS |
ES |
異步 |
不支持 |
支持 |
條件(if) |
支持 |
不支持 |
Node |
支持 |
V13+ |
TypeScript |
支持 |
支持 |