I'm using a lib that use dynamic import of wasm and js files.
https://github.com/terrastruct/d2/blob/0b2203c107df5319380c1d72753ae8c7814324d9/d2js/js/src/index.js#L37-L42 (d2 js)
The issue here is that to do these imports the lib uses
const __dirname = dirname(fileURLToPath(import.meta.url));
and when bundled import.meta.url returns something like file:///Users/user/project/contentlayer/.cache/v0.5.4/compiled-contentlayer-config-BQHZBO35.mjs?x=1743243337285 instead of the expected file:///Users/user/project/node_modules/@terrastruct/d2/dist/node-esm/index.js. with this, every import fails.
The config bundle happens here:
|
esbuild.makeAndSubscribe({ |
|
entryPoints: [configPath], |
|
entryNames: '[name]-[hash]', |
|
outfile: outfilePath, |
|
sourcemap: true, |
|
platform: 'node', |
|
target: 'es2020', |
|
format: 'esm', |
|
// needed in case models are co-located with React components |
|
jsx: 'transform', |
|
bundle: true, |
|
logLevel: 'silent', |
|
metafile: true, |
|
absWorkingDir: cwd, |
|
plugins: [contentlayerGenPlugin(), makeAllPackagesExternalPlugin(configPath)], |
|
}), |
|
S.mapEffectEitherRight((result) => getConfigFromResult({ result, configPath })), |
The fix would be to allow a custom list of external modules in the esbuild makeAndSubscribe call.
external: ["my-lib"],
an idea would be to pass a custom esbuild config param in the NextPluginOptions in
|
const runContentlayerBuild = async ({ configPath }: NextPluginOptions) => { |
|
if (contentlayerInitialized) return |
|
contentlayerInitialized = true |
|
|
|
await pipe( |
|
core.getConfig({ configPath }), |
|
T.chain((config) => core.generateDotpkg({ config, verbose: false })), |
|
T.tap(core.logGenerateInfo), |
|
OT.withSpan('next-contentlayer:runContentlayerBuild'), |
|
runMain, |
|
) |
|
} |
|
|
|
const runMain = core.runMain({ tracingServiceName: 'next-contentlayer', verbose: process.env.CL_DEBUG !== undefined }) |
|
|
|
export const runBeforeWebpackCompile = async ({ |
|
mode, |
|
pluginOptions, |
|
devServerStartedRef, |
|
}: { |
|
mode: WebpackOptionsNormalized['mode'] |
|
pluginOptions: NextPluginOptions |
|
devServerStartedRef: { current: boolean } |
|
}) => { |
|
const isNextDev = mode === 'development' |
|
const isBuild = mode === 'production' |
|
|
|
const { configPath } = pluginOptions |
|
|
|
if (isBuild) { |
|
checkConstraints() |
|
await runContentlayerBuild({ configPath }) |
|
} else if (isNextDev && !devServerStartedRef.current) { |
|
devServerStartedRef.current = true |
|
// TODO also block here until first Contentlayer run is complete |
|
runContentlayerDev({ configPath }) |
Repro:
- https://github.com/Vahor/contentlayer2-bundle-d2-repro
- commits:
- First commit is a nextjs init app;
- 2nd is to introduce a similar behavior as a rehype plugin using d2
- 3rd is a patch to show that using external option for esbuild fixes the issue (the only change is
external: ["@terrastruct/d2"],)
I'm using a lib that use dynamic import of wasm and js files.
https://github.com/terrastruct/d2/blob/0b2203c107df5319380c1d72753ae8c7814324d9/d2js/js/src/index.js#L37-L42 (d2 js)
The issue here is that to do these imports the lib uses
const __dirname = dirname(fileURLToPath(import.meta.url));and when bundled
import.meta.urlreturns something likefile:///Users/user/project/contentlayer/.cache/v0.5.4/compiled-contentlayer-config-BQHZBO35.mjs?x=1743243337285instead of the expectedfile:///Users/user/project/node_modules/@terrastruct/d2/dist/node-esm/index.js. with this, every import fails.The config bundle happens here:
contentlayer2/packages/@contentlayer/core/src/getConfig/index.ts
Lines 68 to 84 in 37c800c
The fix would be to allow a custom list of external modules in the esbuild makeAndSubscribe call.
external: ["my-lib"],an idea would be to pass a custom esbuild config param in the
NextPluginOptionsincontentlayer2/packages/next-contentlayer/src/plugin.ts
Lines 32 to 67 in 37c800c
Repro:
external: ["@terrastruct/d2"],)