112

We're trying to use the new ways of exporting and importing modules for ES6 with Node.js. It's important for us to get the version number from the package.json file. The following code should do that:

import {name, version} from '../../package.json'

However, on execution the following error is thrown:

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".json" for T:\ICP\package.json imported from T:\ICP\src\controllers\about.js

Is there something we're missing?
Is the extension .json not supported?
Is there another way to retrieve this information using Node.js 13+?

DarkLite1
  • 13,637
  • 40
  • 117
  • 214

5 Answers5

159

From Node.js version 17.5.0 onward, importing a JSON file is possible using Import Assertions:

import packageFile from "../../package.json" assert { type: "json" };

const {
    name,
    version
  } = packageFile;
  • assert { type: "json" } is mandatory
  • Destructuring such as { name, version } is not possible in the import declaration directly
  • The contents of the JSON file are exported as a default export, so they need to be imported from default.

The dynamic import version looks like this:

const {
    default: {
      name,
      version
    }
  } = await import("../../package.json", {
    assert: {
      type: "json"
    }
  });

Since import assertions and JSON modules have only recently promoted to stage 3, older versions of Node.js might have supported an older syntax. According to the compatibility tables on MDN for import declarations and dynamic import, older versions of Node.js (16.0.0 – 16.14.0 and 17.0.0 – 17.4.0) had varying support:

  • These versions required the --experimental-json-modules flag:

    node --experimental-json-modules about.js
    
  • Some versions did not support import assertions on dynamic import

  • Some versions did not support the "json" type, specifically

  • Some versions relied on an older proposal which did not specify the assert syntax yet

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Idir Hamouch
  • 1,898
  • 1
  • 7
  • 13
60

You can sill import require in an ES6 module for Node.js:

import { createRequire } from "module"; // Bring in the ability to create the 'require' method
const require = createRequire(import.meta.url); // construct the require method
const my_json_file = require("path/to/json/your-json-file.json") // use the require method
Carter Cobb
  • 790
  • 7
  • 13
27

You can use it as in docs node-js as follow:

import { readFile } from 'fs/promises';

const json = JSON.parse(await readFile(new URL('../../package.json', import.meta.url)));
DevHub
  • 522
  • 6
  • 15
  • 2
    If you're doing this on a server... I highly recommend the cleaner `fs-extra`, which promises everything transparently and supports recursive directory copy – Ray Foss May 07 '21 at 18:10
  • 1
    eslint throws error on this as the `await` keyword can only be used within `async` functions – Sina Nov 23 '21 at 12:59
20

2022

From Node.js v16 & v18 official documentation:

import SomeJson from './some.json' assert { type: 'json' }

And run it with the matching experimental flag:

node --experimental-json-modules ./your-file.js
Ivan Gabriele
  • 6,433
  • 5
  • 39
  • 60
-14

try to use

process.env.npm_package_version

this might help you

Ahmed Khattab
  • 2,645
  • 2
  • 13
  • 19