timlrx / contentlayer2

Contentlayer turns your content into data - making it super easy to import MD(X) and CMS content in your app
https://contentlayer.dev
MIT License
142 stars 10 forks source link

ConfigReadError: Cannot find module '.../compiled-contentlayer-config-xxxxx.mjs' #17

Open rakeshtembhurne opened 3 months ago

rakeshtembhurne commented 3 months ago

Getting cannot find module errors, twice when running npm run dev as well as while building.

ConfigReadError (/Users/rakesh/Projects/x/y/contentlayer.config.ts): Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/Projects/x/y/.contentlayer/.cache/v0.4.3/compiled-contentlayer-config-66FTXOAZ.mjs' imported from /Users/rakesh/Documents/Projects/x/y/node_modules/@contentlayer2/core/dist/getConfig/index.js
ConfigReadError (/Users/rakesh/Projects/x/y/contentlayer.config.ts): Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/Projects/x/y/.contentlayer/.cache/v0.4.3/compiled-contentlayer-config-66FTXOAZ.mjs' imported from /Users/rakesh/Documents/Projects/x/y/node_modules/@contentlayer2/core/dist/getConfig/index.js

Please note how path changes from /Users/rakesh/Projects to /Users/Projects for the compiled .mjs file in above lines. It indicates something might be wrong while calculating the file path.

The issue is long pending since contentlayer version > 0.3.1. Here is the unsolved same issue on old repo.

My Configs

OS: Mac OS Sonoma 14.5 Node: v20.13.1 NPM: v10.9.0 Yarn: 1.22.22 "contentlayer2": "^0.4.6", "next-contentlayer2": "^0.4.6", "next": "14.2.3",

Replicating the issue

Create a project with Next Saas Stripe Starter. All the config files are present and seem to be correct.

Step 1: Create Repo npx create-next-app my-saas-project --example "https://github.com/mickasmt/next-saas-stripe-starter"

Step 2: Create Env file with dummy content

  1. Run cp .env.example .env.local
  2. Use VAR=dummy for every empty variable

Step 3: Run the project Run npm run dev or yarn dev

Error will be shown on the terminal.

rakeshtembhurne commented 2 months ago

Updates:

Upon investigation, I found that the following code is causing an issue: path.join(cwd, _) in file node_modules/@contentlayer2/core/dist/getConfig/index.js. Actual values of both cwd and _ are given in the example code below:

import * as path from "node:path";

const pathOne = "/Users/rakesh/Projects/x/y";
const pathTwo =
  "../../../../Projects/x/y/.contentlayer/.cache/v0.4.3/compiled-contentlayer-config-7XUGISBK.mjs";

const joined = path.join(pathOne, pathTwo.replace("../", "./"));
console.log({ joined });

// {
//   joined: "/Users/rakesh/Projects/x/y/.contentlayer/.cache/v0.4.3/compiled-contentlayer-config-7XUGISBK.mjs",
// }

I am not sure why second path resolves prepending "../../../../" to three folders before the current working directory, but it is causing the issue for me.

Temporary Fix

I have temporarily made a fix in my package.json

"scripts": {
    "fixme": "sed -i '' -e 's/path.join(cwd, _)/path.join(cwd, _.replace(\"..\\/\", \".\\/\"))/g' node_modules/@contentlayer2/core/dist/getConfig/index.js",
    ...

I hope it is helpful, and someone will create a fix soon.

fsansalvadore commented 2 months ago

➕ Having the same issue sporadically on builds.

timlrx commented 2 months ago

Thanks for the bug report, will look into it

timlrx commented 2 months ago

Hi @rakeshtembhurne, I am running on Mac OS Sonoma 14.5 as well but I am not able to replicate the example and it does not seem to be the same problem as the issue you linked. You are suggesting that the issue is with path.join(cwd, _) but _ over here should be the file path that matches: /compiled-contentlayer-config-.+.mjs$/ and should be the form of

.contentlayer/.cache/v0.4.3/compiled-contentlayer-config-A54NOJDW.mjs

I am not sure why there's a ../../../../ prepended in your path. Could you help me to log result.metafile.outputs in node_modules/@contentlayer2/core/dist/getConfig/index.js i.e.

const outfilePath = pipe(Object.keys(result.metafile.outputs),
        console.log(result.metafile.outputs),
...

I want to see where the entrypoint for the file is coming from, thanks.

timlrx commented 2 months ago

@fsansalvadore I took a look at your patch in the supabase repo. It appears similar but seems different from the above case as well.

let modifiedContent = data.replace('../../../../', '../../../')

It looks like in a monorepo setup the path might be wrong?

rakeshtembhurne commented 2 months ago

@timlrx I placed console.logs like below in file node_modules/@contentlayer2/core/dist/getConfig/index.js:

    // Deriving the exact outfilePath here since it's suffixed with a hash
    console.log("Metadata Output", JSON.stringify(result.metafile.outputs, null, 2));
    const outfilePath = pipe(Object.keys(result.metafile.outputs), 
    // Will look like `path.join(cacheDir, 'compiled-contentlayer-config-[SOME_HASH].mjs')
    Array.find((_) => _.match(/compiled-contentlayer-config-.+.mjs$/) !== null), 
    (response) => {
      console.log("PIPE DATA", response);
      return response;
    },
    // Needs to be absolute path for ESM import to work
    O.map((_) => path.join(cwd, _.replace("../", "./"))), O.map(unknownToAbsolutePosixFilePath), O.getUnsafe);

Here is the terminal ouput:


  ▲ Next.js 14.2.3
  - Local:        https://localhost:3000
  - Environments: .env.local, .env

 ✓ Starting...
Metadata Output {
  "../../../../Projects/x/y/.contentlayer/.cache/v0.4.3/compiled-contentlayer-config-66FTXOAZ.mjs.map": {
    "imports": [],
    "exports": [],
    "inputs": {},
    "bytes": 8119
  },
  "../../../../Projects/x/y/.contentlayer/.cache/v0.4.3/compiled-contentlayer-config-66FTXOAZ.mjs": {
    "imports": [
      {
        "path": "contentlayer2/source-files",
        "kind": "import-statement",
        "external": true
      },
      {
        "path": "rehype-autolink-headings",
        "kind": "import-statement",
        "external": true
      },
      {
        "path": "rehype-pretty-code",
        "kind": "import-statement",
        "external": true
      },
      {
        "path": "rehype-slug",
        "kind": "import-statement",
        "external": true
      },
      {
        "path": "remark-gfm",
        "kind": "import-statement",
        "external": true
      },
      {
        "path": "unist-util-visit",
        "kind": "import-statement",
        "external": true
      }
    ],
    "exports": [
      "Author",
      "Doc",
      "Guide",
      "Page",
      "Post",
      "default"
    ],
    "entryPoint": "contentlayer.config.ts",
    "inputs": {
      "contentlayer.config.ts": {
        "bytesInOutput": 4313
      }
    },
    "bytes": 4501
  }
}
PIPE DATA Some {
  value: '../../../../Projects/x/y/.contentlayer/.cache/v0.4.3/compiled-contentlayer-config-66FTXOAZ.mjs',
  _tag: 'Some'
}
Metadata Output {
  "../../../../Projects/x/y/.contentlayer/.cache/v0.4.3/compiled-contentlayer-config-66FTXOAZ.mjs.map": {
    "imports": [],
    "exports": [],
    "inputs": {},
    "bytes": 8119
  },
  "../../../../Projects/x/y/.contentlayer/.cache/v0.4.3/compiled-contentlayer-config-66FTXOAZ.mjs": {
    "imports": [
      {
        "path": "contentlayer2/source-files",
        "kind": "import-statement",
        "external": true
      },
      {
        "path": "rehype-autolink-headings",
        "kind": "import-statement",
        "external": true
      },
      {
        "path": "rehype-pretty-code",
        "kind": "import-statement",
        "external": true
      },
      {
        "path": "rehype-slug",
        "kind": "import-statement",
        "external": true
      },
      {
        "path": "remark-gfm",
        "kind": "import-statement",
        "external": true
      },
      {
        "path": "unist-util-visit",
        "kind": "import-statement",
        "external": true
      }
    ],
    "exports": [
      "Author",
      "Doc",
      "Guide",
      "Page",
      "Post",
      "default"
    ],
    "entryPoint": "contentlayer.config.ts",
    "inputs": {
      "contentlayer.config.ts": {
        "bytesInOutput": 4313
      }
    },
    "bytes": 4501
  }
}
PIPE DATA Some {
  value: '../../../../Projects/x/y/.contentlayer/.cache/v0.4.3/compiled-contentlayer-config-66FTXOAZ.mjs',
  _tag: 'Some'
}
Contentlayer config change detected. Updating type definitions and data...
Generated 20 documents in .contentlayer
 ✓ Ready in 2.6s
timlrx commented 2 months ago

@rakeshtembhurne thanks! Strange that it includes ../../../../ section of the path... Not entirely clear to me what's the issue right now since I can't replicate it. If someone has encountered the same issue, feel free to report over here and perhaps we can find some commonalities between the cases.