UNPKG

@marcuwynu23/webpack-plugin-alias-resolver

Version:

A Webpack plugin that rewrites path aliases like @/ into relative paths during build time.

113 lines (96 loc) 3.33 kB
import fs from "fs"; import path from "path"; type MinimalCompiler = { hooks: { beforeRun: { tap: (pluginName: string, callback: () => void) => void; }; }; }; type PluginOptions = { alias?: string; baseDir?: string; targetDir?: string; fileTypes?: string | string[]; }; class AliasResolverPlugin { alias: string; baseDir: string; targetDir: string; fileTypes: string[]; constructor(options: PluginOptions = {}) { this.alias = options.alias || "@/"; this.baseDir = path.resolve(options.baseDir || "dist"); this.targetDir = path.resolve(options.targetDir || "dist"); this.fileTypes = this.normalizeFileTypes(options.fileTypes); } normalizeFileTypes(fileTypes?: string | string[]): string[] { if (!fileTypes) return ["js"]; if (typeof fileTypes === "string") { if (fileTypes === "both") return ["js", "ts"]; return [fileTypes.replace(/^\./, "").toLowerCase()]; } return fileTypes.map((ext) => ext.replace(/^\./, "").toLowerCase()); } shouldProcessFile(filePath: string): boolean { const ext = path.extname(filePath).replace(/^\./, "").toLowerCase(); return this.fileTypes.includes(ext); } toRelativeImport(currentFilePath: string, targetPath: string): string { const relPath = path.relative(path.dirname(currentFilePath), targetPath); return "./" + relPath.replace(/\\/g, "/").replace(/\.js$/, ""); } fixFile(filePath: string): void { let content = fs.readFileSync(filePath, "utf8"); const regex = new RegExp( `(?:from\\s+['"]${this.alias}(.*?)['"]|require\\(['"]${this.alias}(.*?)['"]\\))`, "g" ); const updated = content.replace( regex, ( _match: string, esImport: string | undefined, requireImport: string | undefined ): string => { const importPath = esImport || requireImport; if (!importPath) return _match; const targetPath = path.resolve(this.baseDir, `${importPath}.js`); if (!fs.existsSync(targetPath)) { console.warn( `⚠️ Cannot resolve: ${filePath} -> ${this.alias}${importPath}` ); return _match; } const relative = this.toRelativeImport(filePath, targetPath); return _match.startsWith("from") ? `from '${relative}'` : `require('${relative}')`; } ); fs.writeFileSync(filePath, updated, "utf8"); } walk(dir: string): void { for (const item of fs.readdirSync(dir)) { const fullPath = path.join(dir, item); if (fs.statSync(fullPath).isDirectory()) { this.walk(fullPath); } else if (this.shouldProcessFile(fullPath)) { this.fixFile(fullPath); } } } apply(compiler: MinimalCompiler): void { compiler.hooks.beforeRun.tap("AliasResolverPlugin", () => { console.log( `🔧 [AliasResolverPlugin] Rewriting ${ this.alias } imports in [${this.fileTypes.join(", ")}] files...` ); this.walk(this.targetDir); console.log("✅ [AliasResolverPlugin] Import rewriting complete."); }); } } module.exports = AliasResolverPlugin; module.exports.default = AliasResolverPlugin;