javascriptnode.jsrequirejsesmodulesimport-require

How do I use both `require` and `import` in a Node.js script?


having a node js basic project setup with package.json , install a package and try to use both require and import statment in the same file; to do that here is what did so far but not working.

First Trial

// package.json (v1)
{
  "main": "src/index.js",
  "scripts": {
    "start": "node src/index.js"
  },
  "dependencies": {
    "@xkeshav/day": "latest"
  }
}

and called as below

// src/index.js
const { oneDay } = require("@xkeshav/day");
console.log({ oneDay });
console.log("Hello from template repository");

above works fine


now changes from require to import statament

import { oneDay } from "@xkeshav/day";
console.log({ oneDay });

and when run the file, it throws error

(node:14233) 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)
/home/recursive/dev/template/src/index.js:1
import { oneDay } from "@xkeshav/day";
^^^^^^

SyntaxError: Cannot use import statement outside a module

highlight

add type:"module" in package.json

so added as below

// package.json ( v2 )
{
  "type": "module",
  "main": "src/index.js",
  "scripts": {
    "start": "node src/index.js"
  },
  "dependencies": {
    "@xkeshav/day": "latest"
  }
}

and now this works.


now removed import statment and added require statment

const { oneDay } =  require("@xkeshav/day");
console.log({ oneDay });

and run the file ; it throws error

at /src/index.js:1
const { oneDay } = require("@xkeshav/day");
                   ^

ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and '/home/recursive/dev/template/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

hightlight is

package.json contains "type": "module", To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

so rename index.js to index.cjs and make changes in package.json also

// package.json ( v3 )
{
  "type": "module",
  "main": "src/index.cjs",
  "scripts": {
    "start": "node src/index.cjs"
  },
  "dependencies": {
    "@xkeshav/day": "latest"
  }
}

this works.


import and require together

now addd the import statement along with require as below

const { oneDay } = require("@xkeshav/day");

import { oneDay as dayOne } from "@xkeshav/day";

console.log({ oneDay, dayOne });
console.log("Hello from template repository");

and when run the file; it throws error

(node:14757) 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)
at src/index.cjs:3
import { oneDay as dayOne } from "@xkeshav/day";
^^^^^^

SyntaxError: Cannot use import statement outside a module

Highlight

set "type": "module" in the package.json or use the .mjs extension

so rename index.cjs to index.mjs and run in package.json also

 // # package.json ( v4 )
{
  "type": "module",
  "main": "src/index.mjs",
  "scripts": {
    "start": "node src/index.cjs"
  },
  "dependencies": {
    "@xkeshav/day": "latest"
  }
}

now gives another error


> @xkeshav/template@0.0.3 start
> node src/index.mjs
at src/index.mjs:1
const { oneDay } = require("@xkeshav/day");
                   ^

ReferenceError: require is not defined in ES module scope, you can use import instead

so how can we use both kind of syntax in same file? and what that file extension would be '.mjs' or '.cjs' or '.js` and any changes in package.json required ?


Solution

  • To use both require and import in the same file, you need to handle them based on whether you're using CommonJS or ES Modules:

    Option 1: CommonJS (.cjs file)

    // src/index.cjs
    const { oneDay } = require("@xkeshav/day");
    
    (async () => {
      const { oneDay: dayOne } = await import("@xkeshav/day");
      console.log({ oneDay, dayOne });
    })();
    

    In package.json, set "type": "commonjs".

    Option 2: ES Module (.mjs file)

    // src/index.mjs
    import { oneDay as dayOne } from "@xkeshav/day";
    import { createRequire } from "module";
    const require = createRequire(import.meta.url);
    const { oneDay } = require("@xkeshav/day");
    
    console.log({ oneDay, dayOne });
    

    In package.json, set "type": "module".

    Which to Use?

    This way, you can mix require and import in the same file.