|
22 | 22 |
|
23 | 23 | import type { Compilation, Compiler, Module as WebpackModule } from "webpack"; |
24 | 24 | import { sources } from "webpack"; |
| 25 | +import fs from "fs"; |
| 26 | +import path from "path"; |
| 27 | +import { loadConfig } from "tsconfig-paths"; |
25 | 28 |
|
26 | 29 | interface Asset { |
27 | 30 | name: string; |
@@ -106,65 +109,52 @@ export default class CodePressWebpackPlugin { |
106 | 109 | } |
107 | 110 | } |
108 | 111 |
|
109 | | - // Always try to read @ alias from tsconfig.json if not already present |
110 | | - // resolve.alias usually has Next.js internals but not the @ path alias |
111 | | - const fs = require("fs"); |
112 | | - const path = require("path"); |
113 | | - |
114 | | - if (!aliases.has("@")) { |
115 | | - const tsconfigPath = path.join(compiler.context, "tsconfig.json"); |
116 | | - console.log("[CodePress] Looking for @ alias in tsconfig:", tsconfigPath); |
117 | | - |
| 112 | + // Load path aliases from tsconfig.json using tsconfig-paths library |
| 113 | + // This properly handles: |
| 114 | + // - JSON with comments (TypeScript's JSON5-like syntax) |
| 115 | + // - The "extends" field to resolve inherited configurations |
| 116 | + // - Complex path patterns |
| 117 | + const tsconfigPath = path.join(compiler.context, "tsconfig.json"); |
| 118 | + if (fs.existsSync(tsconfigPath)) { |
118 | 119 | try { |
119 | | - if (fs.existsSync(tsconfigPath)) { |
120 | | - const tsconfigContent = fs.readFileSync(tsconfigPath, "utf8"); |
121 | | - |
122 | | - // Extract paths directly using regex (avoids JSON parsing issues with comments/globs) |
123 | | - // Match: "paths": { "@/*": ["./src/*"] } or similar |
124 | | - const pathsMatch = tsconfigContent.match( |
125 | | - /"paths"\s*:\s*\{([^}]+)\}/ |
126 | | - ); |
127 | | - |
128 | | - if (pathsMatch) { |
129 | | - const pathsContent = pathsMatch[1]; |
130 | | - console.log("[CodePress] Found paths block:", pathsContent.trim()); |
131 | | - |
132 | | - // Extract individual path mappings: "@/*": ["./src/*"] |
133 | | - const pathPattern = /"([^"]+)"\s*:\s*\[\s*"([^"]+)"/g; |
134 | | - let match; |
135 | | - while ((match = pathPattern.exec(pathsContent)) !== null) { |
136 | | - const aliasPattern = match[1]; // "@/*" |
137 | | - const targetPattern = match[2]; // "./src/*" |
138 | | - |
139 | | - // Convert "@/*" -> "@" and "./src/*" -> "src" |
140 | | - const alias = aliasPattern.replace(/\/\*$/, ""); |
141 | | - const targetPath = targetPattern |
142 | | - .replace(/^\.\//, "") |
143 | | - .replace(/\/\*$/, ""); |
| 120 | + const config = loadConfig(compiler.context); |
| 121 | + |
| 122 | + if (config.resultType === "success" && config.paths) { |
| 123 | + for (const [pattern, targets] of Object.entries(config.paths)) { |
| 124 | + // Convert "@/*" -> "@" and "./src/*" -> "src" |
| 125 | + const alias = pattern.replace(/\/\*$/, ""); |
| 126 | + |
| 127 | + // Skip if we already have this alias from webpack config |
| 128 | + if (aliases.has(alias)) continue; |
| 129 | + |
| 130 | + // Get the first target path |
| 131 | + const targetPattern = targets[0]; |
| 132 | + if (targetPattern) { |
| 133 | + // Convert absolute or relative path to relative directory |
| 134 | + let targetPath = targetPattern |
| 135 | + .replace(/\/\*$/, "") // Remove trailing /* |
| 136 | + .replace(/^\.\//, ""); // Remove leading ./ |
| 137 | + |
| 138 | + // If it's an absolute path, make it relative to project root |
| 139 | + if (path.isAbsolute(targetPath)) { |
| 140 | + targetPath = path.relative(compiler.context, targetPath); |
| 141 | + } |
144 | 142 |
|
145 | 143 | aliases.set(alias, targetPath); |
146 | | - console.log( |
147 | | - "[CodePress] Added alias from tsconfig:", |
148 | | - alias, |
149 | | - "->", |
150 | | - targetPath |
151 | | - ); |
152 | 144 | } |
153 | | - } else { |
154 | | - console.log("[CodePress] No paths block found in tsconfig"); |
155 | 145 | } |
156 | 146 | } |
157 | 147 | } catch (e) { |
158 | | - console.warn("[CodePress] Error reading tsconfig.json:", e); |
| 148 | + console.warn("[CodePress] Error loading tsconfig.json paths:", e); |
159 | 149 | } |
| 150 | + } |
160 | 151 |
|
161 | | - // Fallback: Next.js convention is @/* -> ./src/* |
162 | | - if (!aliases.has("@")) { |
163 | | - const srcDir = path.join(compiler.context, "src"); |
164 | | - if (fs.existsSync(srcDir)) { |
165 | | - aliases.set("@", "src"); |
166 | | - console.log("[CodePress] Using default Next.js alias: @ → src"); |
167 | | - } |
| 152 | + // Fallback: Next.js convention is @/* -> ./src/* |
| 153 | + // Only applies if no @ alias was configured |
| 154 | + if (!aliases.has("@")) { |
| 155 | + const srcDir = path.join(compiler.context, "src"); |
| 156 | + if (fs.existsSync(srcDir)) { |
| 157 | + aliases.set("@", "src"); |
168 | 158 | } |
169 | 159 | } |
170 | 160 |
|
|
0 commit comments