1

I am new to JS and Node. From what I been reading it seems like ES6 import is not supported in Node so I am forced to use experiment mode (renaming my file to mjs)

This works for the most part unless the mjs file needs to use require. My current solution is to break out the chunk of code that depends on require to a seperate .js file and import that js file

foo.mjs

import readFileSync from './util.js'
... 
//orignally just do require('fs') and do fs.readFileSync()
const configFile = readFileSync(configFilePath);

util.js

const fs = require('fs');
const path = require('path');

function readFileSync(filePath) {
  console.log(__dirname)
  console.log(path.resolve(__dirname, filePath))
  return fs.readFileSync(path.resolve(__dirname, filePath), 'utf8');
}

module.exports = readFileSync

Is there a way I can avoid doing this? My app.js has lots of require and I don't want to break out all those parts into separate js files.

I tried changing require to import

// const express = require('express');
import * as express from 'express';

but when run node --experimental-modules app.mjs

I get an error

TypeError: express is not a function

I think I need to either

  • find a way to use require in mjs
  • or find a way to import stuff in mjs into a js file
OLIVER.KOO
  • 4,857
  • 2
  • 21
  • 47

1 Answers1

0

You have three decent options:

  • Use Babel or TypeScript to get interoperability between the two types of modules
  • Write a little wrapper to redefine require in ESM code
  • Use import() (dynamic import) in your CJS to import ESM code

The wrapper to use require in ESM code:

import { createRequire } from 'module'
const require = createRequire(import.meta.url)
const cjsFile = require('./test') // test is regular .js file using module.exports

Dynamic imports:

// foo.mjs:
export const foo = () => true
// index.js:
import('./foo.mjs').then(x => console.log(x.foo()))

Large projects with mixed module types frequently use Babel and/or TypeScript, both of which handle the mixed types just fine. Babel would be simpler to learn and get set up. But if you don't have a ton of code to deal with, the createRequire method works just fine.

As for the issue with Express, it failed because the default export is what you want: import express from 'express', not import * as express....

Zac Anger
  • 3,159
  • 1
  • 9
  • 29
  • I see. I tried your code above and see that `SyntaxError: The requested module 'module' does not provide an export named 'createRequire'` – OLIVER.KOO Jan 19 '21 at 01:09
  • What version of Node are you on? That was added in v12.2.0 (Node 14 is currently the Active LTS version). – Zac Anger Jan 19 '21 at 01:15
  • I am on v10.23.1 – OLIVER.KOO Jan 19 '21 at 01:16
  • I'm not sure what you can do in that case, then. Node 10 has only seen security patches for the last year and will be EOL in three months from now... it's probably time to update :) 12 is in maintenance mode now, 14 is active LTS, and 16 will be coming out in April. 14 would be a good version to switch to if you can. – Zac Anger Jan 19 '21 at 01:18
  • I will give it an update and try it out! Thanks for the quick response :) – OLIVER.KOO Jan 19 '21 at 01:21
  • You're welcome! – Zac Anger Jan 19 '21 at 01:22