From 0b41467d1a51f7190f634609d93fb2b9f4aba746 Mon Sep 17 00:00:00 2001 From: markshawn2020 Date: Thu, 6 Nov 2025 11:36:26 +0800 Subject: [PATCH] fix: improve pnpm link compatibility and file path resolution Resolve MODULE_NOT_FOUND errors when using pnpm link for local development. Problems solved: 1. Use relative paths instead of NPM specifiers for generated files 2. Write generated files to project cache dir (node_modules/.code-inspector) 3. Ensure cache directory exists before write operations 4. Better Next.js compatibility with relative path imports This enables smooth local development workflow: - pnpm/npm/yarn link support - Testing unpublished changes in real projects - Better contributor development workflow Changes: - packages/core/src/server/use-client.ts: Switch to relative path imports - packages/code-inspector-plugin/src/index.ts: Use project cache directory - packages/core/src/shared/record-cache.ts: Add directory creation --- packages/code-inspector-plugin/src/index.ts | 15 +++++------- packages/core/src/server/use-client.ts | 26 ++++++++++++++------- packages/core/src/shared/record-cache.ts | 5 ++++ 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/packages/code-inspector-plugin/src/index.ts b/packages/code-inspector-plugin/src/index.ts index 1c073ee..a76c549 100644 --- a/packages/code-inspector-plugin/src/index.ts +++ b/packages/code-inspector-plugin/src/index.ts @@ -5,12 +5,11 @@ import { TurbopackCodeInspectorPlugin } from '@code-inspector/turbopack'; import { MakoCodeInspectorPlugin } from '@code-inspector/mako'; import { CodeOptions, - fileURLToPath, getEnvVariable, resetFileRecord, } from '@code-inspector/core'; import chalk from 'chalk'; -import path, { dirname } from 'path'; +import path from 'path'; export interface CodeInspectorPluginOptions extends CodeOptions { /** @@ -39,16 +38,14 @@ export function CodeInspectorPlugin(options: CodeInspectorPluginOptions): any { } } - let compatibleDirname = ''; - if (typeof __dirname !== 'undefined') { - compatibleDirname = __dirname; - } else { - compatibleDirname = dirname(fileURLToPath(import.meta.url)); - } + // Write generated files to user project's node_modules/.cache directory + // This ensures relative imports work correctly with pnpm link + const outputDir = path.resolve(process.cwd(), 'node_modules/.cache/code-inspector'); + const params = { ...options, close, - output: path.resolve(compatibleDirname, './'), + output: outputDir, }; resetFileRecord(params.output); if (options.bundler === 'webpack' || options.bundler === 'rspack') { diff --git a/packages/core/src/server/use-client.ts b/packages/core/src/server/use-client.ts index 9692d8c..20a2680 100644 --- a/packages/core/src/server/use-client.ts +++ b/packages/core/src/server/use-client.ts @@ -332,17 +332,18 @@ export async function getCodeWithWebComponent({ ); if (isNextjs || options.importClient === 'file') { writeEslintRcFile(record.output); - const webComponentNpmPath = writeWebComponentFile( + const webComponentPath = writeWebComponentFile( record.output, injectCode, - getProjectRecord(record)?.port || 0 + getProjectRecord(record)?.port || 0, + file ); - if (!file.match(webComponentNpmPath)) { + if (!file.match(webComponentPath)) { if (isNextjs) { - code = addImportToEntry(code, webComponentNpmPath); + code = addImportToEntry(code, webComponentPath); code = addNextEmptyElementToEntry(code); } else { - code = `import '${webComponentNpmPath}';${code}`; + code = `import '${webComponentPath}';${code}`; } } } else { @@ -370,13 +371,22 @@ module.exports = { function writeWebComponentFile( targetPath: string, content: string, - port: number + port: number, + fromFile: string ) { const webComponentFileName = `append-code-${port}.js`; - const webComponentNpmPath = `code-inspector-plugin/dist/${webComponentFileName}`; const webComponentFilePath = path.resolve(targetPath, webComponentFileName); fs.writeFileSync(webComponentFilePath, content, 'utf-8'); - return webComponentNpmPath; + + // Calculate relative path from the importing file to the generated file + // This works with pnpm link and is required by Next.js + const relativePath = path.relative(path.dirname(fromFile), webComponentFilePath); + // Ensure path starts with ./ or ../ + const normalizedRelative = relativePath.startsWith('.') + ? relativePath + : `./${relativePath}`; + + return normalizePath(normalizedRelative); } export function isNextjsProject() { diff --git a/packages/core/src/shared/record-cache.ts b/packages/core/src/shared/record-cache.ts index 6b77c81..c6002da 100644 --- a/packages/core/src/shared/record-cache.ts +++ b/packages/core/src/shared/record-cache.ts @@ -3,6 +3,11 @@ import fs from 'fs'; import { RecordInfo } from './type'; export const resetFileRecord = (output: string) => { + // Ensure output directory exists + if (!fs.existsSync(output)) { + fs.mkdirSync(output, { recursive: true }); + } + const recordFilePath = path.resolve(output, './record.json'); const projectDir = process.cwd(); let content: {