Super Simple Start to ESModules in Node.js

On April 30th 2021, Node v10 will officially reach it’s “end of life” (learn
more on the Node Releases page). This
is exciting because it means that every supported version of the Node.js
JavaScript runtime will support Node’s official EcmaScript Modules! There are
mixed feelings on this change (some would have preferred we stick with CommonJS
in the Node ecosystem), but whatever your opinion on the matter the fact is that
ESModules are here and they are the future. So let’s learn how to use them in a
Node.js environment.

Note: You might be interested in my companion post
Super Simple Start to ESModules in the Browser

First, we need the JavaScript we want to run:

// 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}

Next, let’s make a JavaScript file that imports this and runs it:

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

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

Great, now let’s try to run it:

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

Here’s the thing. The Node.js project will sometimes experience breaking changes
and that’s reasonable, but breaking the module system is just a non-starter. So
using ESM is an opt-in. You can either opt-in a single file by changing from
.js to .mjs, or you can opt-in an entire directory by adding a
package.json with "type": "module".

Let’s go with the second option so we don’t have to rename all our files. Put
this in a package.json:

{
  "type": "module"
}

Now let’s run it:

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'
  }
]

That’s it. We’ve got native ESM running in Node.js.

There’s plenty more to talk about here but this should get you started. You may
be interested in reading
the official initial announcement of ESM support.
Good luck!


Source link

مدونة تقنية تركز على نصائح التدوين ، وتحسين محركات البحث ، ووسائل التواصل الاجتماعي ، وأدوات الهاتف المحمول ، ونصائح الكمبيوتر ، وأدلة إرشادية ونصائح عامة ونصائح