首页 文章

使用Node.js需要与ES6导入/导出

提问于
浏览
637

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

  • 使用 require 导入模块,并使用 module.exportsexports.foo 导出 .

  • 使用ES6 import 导入模块,并使用ES6 export 导出

使用一个优于另一个是否有任何性能优势?如果我们使用ES6模块而不是Node模块,还有什么我们应该知道的吗?

7 回答

  • 539

    使用其中一个是否有任何性能优势?

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

    CommonJS和ES6模块之间存在技术差异,例如: CommonJS允许您动态加载模块 . ES6不允许这样,but there is an API in development for that .

    由于ES6模块是标准的一部分,我会使用它们 .

  • 19

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

    要求:

    • 您可以在加载的模块名称为't predefined /static, or where you conditionally load a module only if it' s "truly required"(取决于特定代码流)的情况下进行动态加载 .

    • 加载是同步的 . 这意味着如果您有多个 require ,则会逐个加载和处理它们 .

    ES6进口:

    • 您可以使用命名导入来有选择地仅加载您需要的部分 . 这可以节省内存 .

    • 导入可以是异步的(在当前的ES6模块加载器中,它实际上是)并且可以执行得更好 .

    此外,Require模块系统不是基于标准的 . 现在ES6模块存在的可能性很小 . 将来,在各种实现中将对ES6模块提供原生支持,这在性能方面将是有利的 .

  • 116

    使用ES6模块可以用于“树摇动”;即启用Webpack 2,Rollup(或其他捆绑包)来识别未使用/导入的代码路径,因此不会将其放入生成的捆绑包中 . 这可以通过消除您永远不需要的代码来显着减少其文件大小,但默认情况下捆绑了CommonJS,因为Webpack等人无法知道是否需要它 .

    这是使用代码路径的静态分析完成的 .

    例如,使用:

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

    ...给捆绑者一个提示,即 package.anotherPart 不是't required (if it'未导入,它可以打扰它 .

    要为Webpack 2启用此功能,您需要确保您的转换器没有使用带有babel的 es2015 插件,您可以在 .babelrc 中禁用它,如下所示:

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

    Rollup和其他人可能会有不同的工作方式 - 如果您有兴趣,请查看文档 .

  • 34

    主要优点是句法:

    • 更多声明/紧凑语法

    • ES6模块基本上会使UMD(通用模块定义)过时 - 基本上消除了CommonJS和AMD(服务器与浏览器)之间的分裂 .

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

  • 24

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

    import {foo, bar} from "dep";
    

    FileName:dep.js

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

    归功于Paul Shan . More info .

  • 8

    当谈到异步或延迟加载时, import () 更强大 . 查看我们何时以异步方式需要组件,然后使用 awaitconst 变量中的某种异步方式使用 import .

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

    或者如果你想使用 require() 那么,

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

    事实上 import() 实际上是异步的 . 正如neehar venugopal在ReactConf中所提到的,您可以使用它来动态加载客户端架构的反应组件 .

    在路由方面也更好 . 当用户将特定网站连接到其特定组件时,这是使网络日志下载必要部分的一个特殊事物 . 例如 . 仪表板前的登录页面不会下载仪表板的所有组件 . 因为需要当前即登录组件,只会下载 .

    export 也是如此:ES6 export 与CommonJS module.exports 完全相同 .

    NOTE - If you are developing a node.js project, then you have to strictly use require() as node will throw exception error as invalid token 'import' if you will use import . So node does not support import statements

    UPDATE - As suggested by Dan Dascalescu: Since v8.5.0 (released Sep 2017), node --experimemntal-modules index.mjs lets you use import without Babel. You can (and should) also publish your npm packages as native ESModule, with backwards compatibility for the old require way.

    有关清除何处使用异步导入的信息,请参阅此内容 - https://www.youtube.com/watch?v=bb6RCrDaxhw

  • 4

    使用其中一个是否有任何性能优势?

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

    一些比较图表http://kangax.github.io/compat-table/es6/没有考虑到这一点,所以当你看到Chrome的几乎所有果岭时,要小心 . 来自ES6的 import 关键字未被考虑在内 .

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

    (根据ES6规范,我们可能仍然只是a few bugs away或几年之后,直到V8实现了这一点 . )

    我们需要这个document,这是我们必须遵守的 .

    并且ES6标准表示在我们读取模块之前模块依赖应该存在,就像在编程语言C中那样,我们有(头文件) .h 文件 .

    这是一个很好且经过良好测试的结构,我相信创建ES6标准的专家会考虑到这一点 .

    这使得Webpack或其他软件包捆绑包能够在某些特殊情况下优化捆绑包,并减少捆绑包中不需要的依赖关系 . 但是如果我们有完美的依赖关系,这将永远不会发生 .

    它将需要一些时间,直到 import/export 本机支持生效,并且 require 关键字将不会长时间在任何地方 .

    什么是 require

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

    Node使用系统级方法来读取文件 . 使用 require 时,你基本上都依赖它 . require 将在某些系统调用中结束,如 uv_fs_open (取决于终端系统,Linux,Mac,Windows)以加载JavaScript文件/模块 .

    要检查这是否属实,请尝试使用Babel.js,您将看到 import 关键字将转换为 require .

    enter image description here

相关问题