【译】JavaScript中require和import语句——详细指南

202 阅读8分钟

JavaScript中require和import语句的区别

在现代网络开发中,我们使用require或import来指代JavaScript的依赖关系。而且,有时候,我们会把两者结合起来使用,使用对库有用的东西。

但是,你知道为什么这两者都存在吗?这下面会发生什么?以及在使用其中一种时有什么最佳做法?

在这篇文章中,我将讨论require和import的用法,并回答一些常见的问题。

背景--JavaScript模块类型

在讨论 require 和 import 之前,有必要对 JavaScript 模块有一个了解。因此,让我们来看看有哪些不同类型的JavaScript模块可用。

1.AMD - 异步模块的定义

引入AMD模块是为了使模块对前端更友好。它们不需要任何捆绑器,所有的依赖关系都是动态解决的。

AMD的使用require函数是用来加载外部模块的,能够作为CommonJS模块的包装器。

define("exampleModule", [], () => {

然而,随着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的结合。它使用了CommonJS的语法和AMD的异步加载技术,使其同时适用于服务器端和客户端。

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);
  }
  function exampleFunction() {}
  return exampleFunction;
});

4.ESM - ES模块

ES模块(ECMAScript Modules)是JavaScript中使用的官方标准。ES Modules使用导入和导出语句来处理模块。它解决了CommonJS的一个最大的限制,即同步加载。

ES模块以异步方式导入引导模块,同时允许在构建时进行静态分析。

在引入ES Modules之后,考虑到与CommonJS的兼容性,开发者之间有很多争论。然而,开发者们已经适应了使用这两者,我们将在接下来的章节中讨论更多细节。

既然你已经了解了JavaScript模块的背景,我们就来讨论一下require和import。

"require "是NodeJS内置的

require通常在NodeJS中用来读取和执行CommonJS模块。

这些模块可以是像http这样的内置模块,也可以是自定义编写的模块。通过require,你可以在你的JavaScript文件中包含它们,并使用它们的函数和变量。

// built-in moduels
// local moduels

然而,如果你使用require来获取本地模块,首先你需要使用module.exports来导出它们。

例如,我们假设你有一个名为 blogDetails.js 的文件,你需要在 index.js 文件中使用该文件的一个函数。

medium.com/media/5422d…medium.com/media/a18a9…

你还可以使用modules.export一次导出多个模块,如下所示。

medium.com/media/83c28…

**注意:**不要在最后使用modules.export,你也可以在每个函数中附加export开始。Eg: exports.getBlogContent = () => {};

我想你现在明白了什么时候我们应该使用require,以及它是如何工作的。但是,在进入require的独特功能之前,让我们看看import是如何工作的。然后,我们将能够在更深的层次上对它们进行比较和理解。

"导入 "是与ES6模块一起引入的

import是一个ES模块,和export一起,它们被称为ES6的import和export。

我们不能在ES模块之外使用import或export。

我们可以看到,试图在ES模块之外导入是一个常见的开发者错误,有很多StackOverflow的线程都是关于这个的。

如果我以同样的例子为例,我唯一需要做的改变是修改modules.export为export default。

medium.com/media/ac813…

然后我们可以使用import将这个文件包含在我们的index.js文件中。

medium.com/media/4a6fb…

注意: 与require类似,你也可以通过在每个函数定义后面附加export来单独导出每个函数。

Eg: export const =getBlogContent = () => {};

所以,我希望你现在明白如何以及何时应该使用 require 和 import。但是,这还不是全部;它们的功能和用法有一些明显的区别。现在是进行比较的时候了。

Require Vs.导入

require和import都是用来包含模块的。但它们有几个重要的特点,你应该注意。

1.要求语句可以在代码的任何地方调用

通常情况下,我们在文件的开头调用import或require语句。

但你知道吗,你可以在代码的任何地方自由使用require语句?是的,你可以!

另一方面,import语句只能定义在文件的开头。在其他地方定义import语句会给你一个错误或自动转移到文件的开头。

2.Require可以被有条件地调用

当加载的模块名称没有预定义时,require语句允许你有条件地或动态地加载模块。

例如,你可以在一个函数或像下面这样的if条件中调用require。

if(articleCount>0){

require 语句具有这种灵活性,因为它们被当作函数处理。它们在运行时被调用,在这之前没有办法知道任何事情。但是,import 语句是静态的,我们不能有条件地或动态地使用它们。

**注意:**你可能会认为这是 require 的一个优势。但是,由于导入语句是静态的,你可以在运行应用程序之前发现任何错误。

3.导入语句是异步的

同步或异步在小规模的应用程序中可能不会起到很大的作用。但是,如果我们考虑到大规模的应用程序,会有数百个模块被使用。所以。

如果你使用require,模块将被逐一加载和处理。

另一方面,import语句通过异步工作解决了这个问题,与大规模应用中的require函数相比,它们的性能很好。

4.ES模块是未来的趋势

正如我们所讨论的,ES模块系统是作为维护客户端JavaScript模块的标准而引入的。它也被TypeScript采用,并增加了定义Type的内容。因此,我不认为require能够再次取代ES,因为它已经成为开发者中广泛使用的标准。

但由于有大量的NodeJS模块和库是用CommonJS编写的,我们不能把require完全放在一边。所以我们必须相应地使用它们两个。

另外,我们可以配置编译器来转换输出不同的模块类型。

如果你使用TypeScript,你可以通过对tsconfig.json文件做一些修改,将不同的模块系统作为输出目标。例如,让我们假设我们需要输出一个使用CommonJS的代码版本。

你需要做的是,通过扩展原来的tsconfig文件并修改CompilerOptions下的模块参数,为CommonJS输出创建一个新的tsconfig文件。

{

**注意:**你也可以使用Webpack等构建工具将ES模块转换为CommonJS模块。

除了这些显著的差异,它们之间在语法上也有一些小的变化。因此,我创建了一个信息图比较,总结了文章中讨论的所有内容,以清楚地了解require和import之间的差异。

用Bit构建和分享JS组件

比特 是一个可扩展的工具,可以让你用_独立_编写、版本和维护的组件创建_真正的_模块化应用程序 。

用它来构建模块化的应用程序和设计系统,编写和交付微型前端,或在应用程序之间共享组件。

一个独立的源码控制和共享的 "卡片 "组件。右边是=>它的依赖关系图,由Bit自动生成的。

比特:模块化网络的平台

总结

在这篇文章中,我解决了许多开发者的一个共同问题:require和import之间的区别。虽然ES的导入和导出是用来包含模块的新标准,但require函数在NodeJS中被广泛使用。

因此,了解它们之间的区别以及它们的用法将帮助你在你的应用程序中减少不必要的错误。

谢谢您的阅读!!

了解更多


JavaScript Require vs. Import最初发表于Bits and Pieceson Medium,在那里人们通过强调和回应这个故事来继续对话。