Fixing Inconsistent Imports Across OS

2 minute read | 3 months ago

While building React Native Paper Abstracted, I encountered an issue where file imports behaved inconsistently between operating systems, particularly macOS and Windows.

Since I was developing the CLI on macOS, I structured the import paths based on macOS conventions. Everything worked fine during development, so I assumed the package was ready for release. However, after publishing, users on Windows reported unexpected import issues.

For example, when a component import path was supposed to be:

@/components/foo/bar/Button.tsx

On Windows, the import would only resolve to:

@/components

Debugging the Issue

After investigating, I discovered that my script was splitting file paths using /, which works on macOS but not on Windows, where paths use \. To fix this, I updated my script to handle both cases properly.

Previous Implementation (Buggy)

const handleTraversePath = (currentImport: string) => { const folderPath = ensureString(filePath?.split("/").slice(0, -1).join("/")); const fullPath = path.resolve(folderPath, currentImport); if (!fullPath.includes(relativeOutDir) && currentImport.includes("../")) { const traversedPath = currentImport.split(/^..\//).join(""); // Recursively traverse back handleTraversePath(traversedPath); } else { const resolvedPath = path.resolve(folderPath, currentImport); const newImport = alias + resolvedPath.split(relativeOutDir).slice(1).join(""); s.setLiteralValue(newImport); } }; handleTraversePath(literal);

Fixed Implementation (OS-Agnostic)

const getFolderPath = (filePath: string | undefined) => { let resolvedPath = ""; if (filePath) { resolvedPath = ensureString( filePath.split(path.sep).slice(0, -1).join("/") ); } return resolvedPath; }; const normalizeImportPath = (componentFolderPath: string) => { return componentFolderPath.replaceAll("\\", "/"); }; const handleTraversePath = (currentImport: string) => { const folderPath = getFolderPath(filePath); const fullPath = path.resolve(folderPath, currentImport); if (!fullPath.includes(relativeOutDir) && currentImport.includes("../")) { const traversedPath = currentImport.split(/^..\//).join(""); // Recursively traverse back handleTraversePath(traversedPath); } else { const resolvedPath = path.resolve(folderPath, currentImport); const componentFolderPath = resolvedPath.split(relativeOutDir).slice(1).join(""); const newImport = alias + normalizeImportPath(componentFolderPath); s.setLiteralValue(newImport); } }; handleTraversePath(literal);

Explanation of Fix

This change ensured that import paths worked correctly across both macOS and Windows, preventing unexpected behavior when running the package on different operating systems.