Home > database >  require a JSON file throws a Node.js loader error "Error: Cannot find module 'example.json
require a JSON file throws a Node.js loader error "Error: Cannot find module 'example.json

Time:01-13

There are several similar questions related to importing or requiring JSON (.json) files when building the code in TypeScript. My question is specifically about requiring a JSON file in an ES6 module that is transpiled to the current node target using Babel (core and cli). I see no config option like TypeScript's resolveJsonModule for Babel, which leads me to believe it should work without any config.

I am importing a JSON file (example.json) from a JS file (index.js) in the same directory, by doing:

const myObj = {};
myObj.myJSON = require("./example.json");

I have also tried importing using the newer ES6 syntax as:

import * as myJson from "./example.json";

I am using VSCode, and in both cases the auto-complete suggests to me the correct relative path to the JSON file in the source code.

The directory looks like:

src/
  |_dir/
    |_index.js
    |_example.json

In both cases, when transpiling with the babel-cli using the command: babel src --out-dir build, the produced build looks like:

src/
  |_dir/
    |_index.js

For some reason, the example.json file is not included, despite it being required in the compiled index.js file:

...

const myObj = {};

myObj.myJSON = require("./example.json");
...

As such, when running the transpiled build with node using node build/index.js, it throws the error:

internal/modules/cjs/loader.js:883
  throw err;
  ^

Error: Cannot find module './example.json'
Require stack:
- ...
- .../build/index.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
    at Function.Module._load (internal/modules/cjs/loader.js:725:27)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (.../index.js:15:25)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    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 Module.require (internal/modules/cjs/loader.js:952:19) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    ...
  ]
}

Here is the relevant configuration:

package.json

  ...
  "scripts": {
    "build": "babel src --out-dir build",
    "start": "node build/index.js",
    ...
  },
  "devDependencies": {
    "@babel/cli": "^7.16.8",
    "@babel/core": "^7.16.7",
    "@babel/preset-env": "^7.16.8",
    ...
  },
  "dependencies": {
    "@babel/plugin-transform-runtime": "^7.16.8",
    ...
  }

.babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "current"
        }
      }
    ]
  ],
  "plugins": [
    "@babel/plugin-transform-runtime"
  ]
}

CodePudding user response:

I think the boring answer is that Babel only processes JavaScript files. Anything that's not JavaScript (e.g. JSON) gets left behind, even though it "feels" like the JSON file is a code dependency that Babel should "just do the right thing with" (since you required or imported it) -- or at least give you an error or a warning. But that is not how Babel was designed in this use-case.

You need to do extra work to copy data files. I suggest three main alternatives to choose from:

  1. Use a bundler like WebPack or Gulp which has tools for copying non-JS files around
  2. Use Babel's --copy-files which copies everything. You can sprinkle in --ignore patterns to try to avoid copying things you don't want copied.
  3. Use something like the shx npm package which lets you run Unix-style filesystem commands in a cross-platform way from inside package.json scripts.

"build": "babel src --out-dir build && npx shx cp src/*.json dist/"

CodePudding user response:

use __dirname '/example.json'

  •  Tags:  
  • Related