使用Node.js require与ES6导入/导出

2020/09/19 08:01 · javascript ·  · 0评论

在我正在合作的项目中,关于可以使用哪种模块系统,我们有两个选择:

  1. 导入使用的模块require,并使用导出module.exportsexports.foo
  2. 使用ES6导入模块import,并使用ES6导出export

相互使用是否对性能有好处?如果要在Node模块上使用ES6模块,还有其他什么应该知道的吗?

相互使用是否对性能有好处?

请记住,还没有JavaScript引擎本身支持ES6模块。您说自己正在使用Babel。无论如何,Babel都会默认将其转换importexport声明为CommonJS(require/ module.exports)。因此,即使您使用ES6模块语法,但如果在Node中运行代码,也将在后台使用CommonJS。

CommonJS和ES6模块之间存在技术差异,例如,CommonJS允许您动态加载模块。ES6不允许这样做,但是正在为此开发一个API

由于ES6模块是标准的一部分,因此我将使用它们。


更新2020

从Node v12开始,默认情况下启用对ES模块的支持,但是在撰写本文时仍处于试验阶段。包含节点模块的文件必须以结尾,.mjs或者最近的package.json文件必须包含"type": "module"节点的文件有一吨的详细信息,还约CommonJS的和ES模块之间的互操作。

在性能方面,总是存在新功能未如现有功能那样优化的机会。但是,由于模块文件仅被评估一次,因此性能方面可能会被忽略。最后,您必须运行基准测试才能获得明确的答案。

ES模块可以通过该import()功能动态加载不像require,这会返回一个承诺。

您可能要考虑几种用法/功能:

要求:

  • 您可以在未预定义/静态的模块名称的情况下进行动态加载,也可以仅在“确实需要”模块时才有条件地加载模块(取决于某些代码流)。
  • 加载是同步的。这意味着,如果您有多个require,它们将被一个接一个地加载和处理。

ES6导入:

  • 您可以使用命名导入来有选择地仅加载所需的片段。这样可以节省内存。
  • 导入可以是异步的(实际上是在当前的ES6 Module Loader中),并且可以执行得更好。

另外,Require模块系统也不基于标准。由于存在ES6模块,因此极不可能成为标准。将来,将在各种实现中对ES6模块提供本地支持,这在性能方面将是有利的。

主要优点是语法:

  • 更多说明性/紧凑语法
  • ES6模块将基本上使UMD(通用模块定义)过时-实质上消除了CommonJS和AMD(服务器与浏览器)之间的分裂。

您不太可能看到ES6模块的任何性能优势。即使浏览器完全支持ES6功能,您仍将需要一个额外的库来捆绑模块。

相互使用是否对性能有好处?

当前的答案是否定的,因为当前的浏览器引擎都没有实现import/exportES6标准。

一些比较表http://kangax.github.io/compat-table/es6/没有考虑到这一点,因此当您看到Chrome的几乎所有绿色时,请小心。import未考虑来自ES6的关键字。

换句话说,包括V8在内的当前浏览器引擎无法通过任何JavaScript指令主JavaScript文件导入新的JavaScript文件

直到V8根据ES6规范实现这一功能,我们可能还有几步之遥,也可能只有年之遥。)

这个文件是我们需要的,而这个文件是我们必须服从。

ES6标准说,在像使用编程语言C那样拥有(头文件).h文件的方式读取模块之前,应该存在模块依赖性

这是一个经过良好测试的良好结构,并且我相信创建ES6标准的专家会牢记这一点。

这使Webpack或其他程序包捆绑器可以在某些特殊情况下优化包,并减少不需要的依赖。但是,如果我们有完美的依赖关系,那就永远不会发生。

import/export原生支持尚需时日,而require关键字很长一段时间都不会出现。

什么require

这是node.js加载模块的方式。https://github.com/nodejs/node

Node使用系统级方法来读取文件。使用时,基本上可以依靠它requirerequire将以某些系统调用uv_fs_open(取决于最终系统,Linux,Mac,Windows)结束,以加载JavaScript文件/模块。

要检查是否正确,请尝试使用Babel.js,您会看到该import关键字将转换为require

在此处输入图片说明

使用ES6模块对于“摇树”很有用;例如,启用Webpack 2,汇总(或其他捆绑程序)以标识未使用/导入的代码路径,因此不要将其放入结果捆绑包中。通过消除不需要的代码,可以大大减少文件的大小,但是CommonJS是默认捆绑的,因为Webpack等无法知道是否需要它。

这是通过对代码路径进行静态分析来完成的。

例如,使用:

import { somePart } 'of/a/package';

……为捆绑程序提供了package.anotherPart不需要的提示(如果未导入,则无法使用,对吗?),因此不会打扰它。

要为Webpack 2启用此功能,您需要确保您的编译器不会吐出CommonJS模块。如果您使用es2015带babel 插件,则可以按以下方式禁用它.babelrc

{
  "presets": [
    ["es2015", { modules: false }],
  ]
}

汇总和其他工具的工作方式可能有所不同-如果您有兴趣,请查看文档。

当涉及到异步或延迟加载时,它的功能要强import ()大得多。看看何时我们需要异步方式的组件,然后import以某种异步方式使用它,就像const使用变量using一样await

const module = await import('./module.js');

或者,如果您想使用require()

const converter = require('./converter');

事情是import()实际上是异步的性质。正如neehar venugopal在ReactConf中提到的那样,您可以使用它为客户端架构动态加载React组件。

在路由方面也更好。这是使用户在连接到特定网站的特定组件时网络日志下载必要部分的一件事。例如,在仪表板无法下载仪表板的所有组件之前的登录页面。因为当前需要什么,即登录组件,所以将仅下载该组件。

这同样适用于export:ES6 export是为CommonJS的完全相同module.exports

注意 -如果你正在开发一个项目的Node.js,那么你必须严格使用require()的节点会抛出异常错误的invalid token 'import',如果你会使用import因此,节点不支持导入语句。

更新-正如Dan Dascalescu所建议:自v8.5.0(2017年9月发布)以来,node --experimental-modules index.mjsimport无需Babel即可使用您还可以(并且应该)将npm软件包发布为本机ESModule,并向后兼容require方法。

有关在哪里使用异步导入的更多信息,请参见此-https: //www.youtube.com/watch?v=bb6RCrDaxhw

从现在开始,ES6导入,导出始终被编译为CommonJS,因此使用两者都不会有任何好处尽管建议使用ES6,因为当发布来自浏览器的本机支持时,它应该是有利的。原因是,您可以从一个文件导入部分文件,而使用CommonJS则需要所有文件。

ES6→ import, export default, export

CommonJS→ require, module.exports, exports.foo

以下是这些的常见用法。

ES6导出默认

// hello.js
function hello() {
  return 'hello'
}
export default hello

// app.js
import hello from './hello'
hello() // returns hello

ES6导出多个和导入多个

// hello.js
function hello1() {
  return 'hello1'
}
function hello2() {
  return 'hello2'
}
export { hello1, hello2 }

// app.js
import { hello1, hello2 } from './hello'
hello1()  // returns hello1
hello2()  // returns hello2

CommonJS module.exports

// hello.js
function hello() {
  return 'hello'
}
module.exports = hello

// app.js
const hello = require('./hello')
hello()   // returns hello

CommonJS module.exports多个

// hello.js
function hello1() {
  return 'hello1'
}
function hello2() {
  return 'hello2'
}
module.exports = {
  hello1,
  hello2
}

// app.js
const hello = require('./hello')
hello.hello1()   // returns hello1
hello.hello2()   // returns hello2

最重要的是,ES6模块确实是一个官方标准,而CommonJS(Node.js)模块则不是。

在2019年,84%的浏览器都支持ES6模块尽管Node.js将它们放在--experimental-modules标志的后面,但还有一个方便的节点程序包esm,它使集成更加流畅。

您可能会在这些模块系统之间遇到的另一个问题是代码位置。Node.js假定源代码保存在node_modules目录中,而大多数ES6模块则以平面目录结构进行部署。这些不容易调和,但是可以通过package.json使用安装前和安装后脚本来入侵文件来完成下面是一个例子同构模块文章解释它是如何工作的。

我个人使用import是因为,我们可以使用import导入所需的方法,成员。

import {foo, bar} from "dep";

文件名: dep.js

export foo function(){};
export const bar = 22

归功于Paul Shan。更多信息

不知道为什么(可能是优化-延迟加载?)是否可以那样工作,但是我注意到,import如果不使用导入的模块可能无法解析代码。

在某些情况下,这可能不是预期的行为。

以讨厌的Foo类作为我们的示例依赖项。

foo.ts

export default class Foo {}
console.log('Foo loaded');

例如:

索引

import Foo from './foo'
// prints nothing

索引

const Foo = require('./foo').default;
// prints "Foo loaded"

索引

(async () => {
    const FooPack = await import('./foo');
    // prints "Foo loaded"
})();

另一方面:

索引

import Foo from './foo'
typeof Foo; // any use case
// prints "Foo loaded"
本文地址:http://javascript.askforanswer.com/shiyongnode-js-requireyues6daoru-daochu.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!