Node.js中ESModules的超级简单开始

165 阅读2分钟

2021年4月30日,Node v10将正式达到它的 "生命终点"(在Node发布页面了解更多信息)。这很令人兴奋,因为这意味着每个支持的Node.js JavaScript运行时版本都将支持Node的官方EcmaScript模块人们对这一变化褒贬不一(有些人希望我们在Node生态系统中坚持使用CommonJS),但无论你对此事的看法如何,事实是ESModules已经到来,它们是未来的趋势。所以让我们来学习如何在Node.js环境中使用它们。

注意:你可能会对我的配套文章《浏览器中的ESMODULE超级简单入门》感兴趣。

首先,我们需要我们想要运行的JavaScript。

// get-files.js
import path from 'path'
import fs from 'fs/promises'

const isDir = async d => (await fs.lstat(d)).isDirectory()

async function getFiles(dir) {
  const list = await fs.readdir(dir)
  const filePromises = list.map(async filename => {
    const filepath = path.join(dir, filename)
    if (await isDir(filepath)) {
      return {type: 'dir', filepath}
    } else {
      const content = String(await fs.readFile(filepath))
      return {type: 'file', filepath, content}
    }
  })
  return Promise.all(filePromises)
}

export {getFiles}

接下来,让我们做一个JavaScript文件,导入这个文件并运行它。

// index.js
import {getFiles} from './get-files.js'

console.log(await getFiles('.'))

很好,现在让我们试着运行它。

node .
(node:5369) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/Users/kentcdodds/Desktop/super-simple-start-to-esm-in-node/index.js:1
import {getFiles} from './get-files.js'
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:979:16)
    at Module._compile (internal/modules/cjs/loader.js:1027:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
    at internal/main/run_main_module.js:17:47

事情是这样的。Node.js项目有时会遇到破坏性的变化,这也是合理的,但破坏模块系统就是不可能的。所以使用ESM是一种选择。你可以通过将.js 改为.mjs 来选择加入单个文件,也可以通过将package.json"type": "module" 来选择加入整个目录。

让我们选择第二个选项,这样我们就不必重新命名我们所有的文件。把这个放在package.json

{
  "type": "module"
}

现在让我们运行它。

node .
[
  {
    type: 'file',
    filepath: 'get-files.js',
    content: "import path from 'path'\n" +
      // clipped for brevity
      'export {getFiles}\n'
  },
  {
    type: 'file',
    filepath: 'index.js',
    content: "import {getFiles} from './get-files.js'\n" +
      '\n' +
      "console.log(await getFiles('.'))\n"
  },
  {
    type: 'file',
    filepath: 'package.json',
    content: '{\n  "type": "module"\n}\n'
  }
]

就这样了。我们已经在Node.js中运行了本地ESM。

这里还有很多要谈的,但这应该让你开始。你可能有兴趣阅读官方最初宣布的ESM支持。 祝你好运