我刚刚开始研究一个将与 MongoDB 交互的小型节点项目。但是,我似乎无法正确导入相关节点模块,即使我已通过 npm
正确安装它们。
例如,下面的代码会抛出一个错误,告诉我“express 没有默认导出”:
import express from "express";
但是,此代码有效:
const express = require("express");
所以我的问题是,import 和 variable/require 方法的功能有什么区别?我想解决困扰我在项目中的导入的任何问题,因为它似乎可能会在未来引起其他问题。
express
的类型将是 any
。您可以在此处包含定义 npmjs.com/package/@types/express
import x = require('x')
与 var x = require('x')
不同。
这个简单的图表将帮助您了解 require
和 import
之间的区别。
https://i.stack.imgur.com/5WgFJ.png
除此之外,
您不能使用 require
选择性地仅加载您需要的片段,但使用 import
,您可以选择性地仅加载您需要的片段,这可以节省内存。
require
的加载是同步的(逐步),而 import
可以是异步的(无需等待之前的导入),因此它的性能比 require
。
require
和 import
的主要区别在于 require
会自动扫描 node_modules
以查找模块,而来自 ES6 的 import
不会。
大多数人使用 babel 来编译 import
和 export
,这使得 import
的行为与 require
相同。
Node.js 的未来版本可能会支持 import
本身(实际上是 the experimental version already does),从 Node.js 的注释来看,import
不会支持 node_modules
,它基于 ES6,并且必须指定模块的路径。
所以我建议你不要在 babel 中使用 import
,但是这个功能还没有确认,将来可能会支持 node_modules
,谁知道呢?
作为参考,下面是 babel 如何将 ES6 的 import
语法转换为 CommonJS 的 require
语法的示例。
假设文件app_es6.js
包含此导入:
import format from 'date-fns/format';
这是从节点包 date-fns 导入 format 函数的指令。
相关的 package.json
文件可能包含如下内容:
"scripts": {
"start": "node app.js",
"build-server-file": "babel app_es6.js --out-file app.js",
"webpack": "webpack"
}
相关的 .babelrc
文件可能是这样的:
{
"presets": [
[
"env",
{
"targets":
{
"node": "current"
}
}
]
]
}
package.json
文件中定义的这个 build-server-file
脚本是 babel 解析 app_es6.js
文件并输出文件 app.js
的指令。
运行 build-server-file
脚本后,如果您打开 app.js
并查找 date-fns
导入,您将看到它已转换为:
var _format = require("date-fns/format");
var _format2 = _interopRequireDefault(_format);
该文件的大部分内容对大多数人来说都是 gobbledygook,但是计算机可以理解它。
另外作为参考,作为如何创建模块并将其导入项目的示例,如果您安装 date-fns
,然后打开 node_modules/date-fns/get_year/index.js
,您会看到它包含:
var parse = require('../parse/index.js')
function getYear (dirtyDate) {
var date = parse(dirtyDate)
var year = date.getFullYear()
return year
}
module.exports = getYear
使用上面的 babel 进程,您的 app_es6.js
文件可能包含:
import getYear from 'date-fns/get_year';
// Which year is 2 July 2014?
var result = getYear(new Date(2014, 6, 2))
//=> 2014
babel 会将导入转换为:
var _get_year = require("date-fns/get_year");
var _get_year2 = _interopRequireDefault(_get_year);
并相应地处理对该函数的所有引用。
require
import won't support node_modules
你的意思是什么?
import
和 require
都在 node_modules
中扫描语句指定的包。 require
将包中分配给 module.exports
的任何内容加载到分配给它的变量中,如果没有声明左手,则加载到全局范围。但是,import
将仅按名称加载 es6 默认导出,除非所有内容都分配给别名:import * as X from 'pkg'
。您也可以使用 object destructuring 导入没有默认值的 es6 包:import { X } from 'pkg'
。如果您将整个包(包括所有导出)导入全局范围 import 'package'
,它将与 require
一样工作。
让我举一个例子,用 require 和 import 包含 express 模块
-要求
var express = require('express');
-进口
import * as express from 'express';
因此,在使用上述任何语句后,我们将拥有一个名为“express”的变量。现在我们可以将“app”变量定义为,
var app = express();
所以我们使用 'require' 和 'CommonJS' 和 'import' 和 'ES6'。
有关“要求”和“导入”的更多信息,请阅读以下链接。
需要 - Requiring modules in Node.js: Everything you need to know
进口 - An Update on ES6 Modules in Node.js
import
语句时遇到问题,并且对 express has no default export 错误感到困惑。这个答案提供了解决方案。具有多个(甚至单个)导出但未定义 default export
的模块将需要将所有导出分配给命名变量,如答案所述:import * as whatever from 'package';
node_modules
中检查您所依赖的包的代码(入口点将在其 package.json
main
键下列出)。 module.export = whatever
之类的内容意味着您可能必须将其作为 import * as whatever from 'package';
导入。
我会让它变得简单,
导入和导出是 ES6 特性(下一代 JS)。
Require 是从其他文件导入代码的老式方法
主要区别在于require,整个JS文件被调用或包含。即使你不需要它的一部分。
var myObject = require('./otherFile.js'); //This JS file will be included fully.
而在导入中,您只能提取所需的对象/函数/变量。
import { getDate }from './utils.js';
//Here I am only pulling getDate method from the file instead of importing full file
另一个主要区别是您可以在程序中的任何位置使用 require
,因为 import
应始终位于文件顶部
编辑:在最新的节点版本中,您可以使用解构。它看起来像这样
const { getDate } = require('./date.js');
require
一起使用,例如 const { getDate } = require('./utils.js');
require
而 import
仅在文件顶部的声明也在掩饰重要的细节。当您使用范围为函数(或应用程序代码中某处的块范围)而不是范围为模块/文件的 require
时,这与 ES 模块(又名 import
语法)等效。虽然这是一个异步操作,但这种“动态导入”需要使用 .then()
或 await
关键字。
require
不会“调用”或“包含”文件,它会加载并执行模块。当然,它评估模块的整个代码,而不仅仅是某个部分 - 就像 import
一样!
新的 ES6:
'import' 应与 'export' 关键字一起使用,以在 js 文件之间共享变量/数组/对象:
export default myObject;
//....in another file
import myObject from './otherFile.js';
老学校:
'require' 应与 'module.exports' 一起使用
module.exports = myObject;
//....in another file
var myObject = require('./otherFile.js');
这之间有很大的不同:
import express from "express";
和这个:
import * as express from "express";
从 CommonJS 到 ES6 的正确翻译
const express = require("express");
是第二次进口。
基本上,这是因为在第一次导入中,您正在寻找名为 express
的模块 express
中的导出。第二个是导入名称为 express
的整个 express 模块。
不定期副业成功案例分享
module.exports
的内容。在尝试使单个模块同时适用于 ESM 和 CommonJS 时,仅此差异就会造成兼容性问题。