Skip to content

Commit

Permalink
Use enhanced-resolve to load files
Browse files Browse the repository at this point in the history
  • Loading branch information
thecrypticace committed Sep 23, 2024
1 parent 2d46805 commit 98c4812
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 19 deletions.
23 changes: 23 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"ast-types": "^0.14.2",
"clear-module": "^4.1.2",
"cpy-cli": "^5.0.0",
"enhanced-resolve": "^5.17.1",
"esbuild": "^0.19.8",
"escalade": "^3.1.1",
"import-sort-style-module": "^6.0.0",
Expand Down
10 changes: 6 additions & 4 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import loadConfigFallback from 'tailwindcss/loadConfig'
import resolveConfigFallback from 'tailwindcss/resolveConfig'
import type { RequiredConfig } from 'tailwindcss/types/config.js'
import { expiringMap } from './expiring-map.js'
import { resolveFrom, resolveIn } from './resolve'
import { resolveJsFrom } from './resolve'
import type { ContextContainer } from './types'

let sourceToPathMap = new Map<string, string | null>()
Expand Down Expand Up @@ -104,7 +104,7 @@ async function loadTailwindConfig(
let tailwindConfig: RequiredConfig = { content: [] }

try {
let pkgFile = resolveIn('tailwindcss/package.json', [baseDir])
let pkgFile = resolveJsFrom(baseDir, 'tailwindcss/package.json')
let pkgDir = path.dirname(pkgFile)

try {
Expand Down Expand Up @@ -160,7 +160,8 @@ function createLoader<T>({

async function loadFile(id: string, base: string) {
try {
let resolved = resolveFrom(base, id)
let resolved = resolveJsFrom(base, id)

let url = pathToFileURL(resolved)
url.searchParams.append('t', cacheKey)

Expand All @@ -180,7 +181,8 @@ async function loadV4(
entryPoint: string | null,
) {
// Import Tailwind — if this is v4 it'll have APIs we can use directly
let pkgPath = resolveIn('tailwindcss', [baseDir])
let pkgPath = resolveJsFrom(baseDir, 'tailwindcss')

let tw = await import(pathToFileURL(pkgPath).toString())

// This is not Tailwind v4
Expand Down
39 changes: 24 additions & 15 deletions src/resolve.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
import { createRequire as req } from 'node:module'
import resolveFrom from 'resolve-from'
import fs from 'node:fs'
import { fileURLToPath } from 'node:url'
import { CachedInputFileSystem, ResolverFactory } from 'enhanced-resolve'
import { expiringMap } from './expiring-map'

const localRequire = req(import.meta.url)
const fileSystem = new CachedInputFileSystem(fs, 30_000)

const esmResolver = ResolverFactory.createResolver({
fileSystem,
useSyncFileSystemCalls: true,
extensions: ['.mjs', '.js'],
mainFields: ['module'],
conditionNames: ['node', 'import'],
})

const cjsResolver = ResolverFactory.createResolver({
fileSystem,
useSyncFileSystemCalls: true,
extensions: ['.js', '.cjs'],
mainFields: ['main'],
conditionNames: ['node', 'require'],
})

// This is a long-lived cache for resolved modules whether they exist or not
// Because we're compatible with a large number of plugins, we need to check
Expand All @@ -11,17 +28,11 @@ const localRequire = req(import.meta.url)
// failed module resolutions making repeated checks very expensive.
const resolveCache = expiringMap<string, string | null>(30_000)

export function resolveIn(id: string, paths: string[]) {
return localRequire.resolve(id, {
paths,
})
}

export function maybeResolve(name: string) {
let modpath = resolveCache.get(name)

if (modpath === undefined) {
modpath = freshMaybeResolve(name)
modpath = resolveJsFrom(fileURLToPath(import.meta.url), name)
resolveCache.set(name, modpath)
}

Expand All @@ -39,12 +50,10 @@ export async function loadIfExists<T>(name: string): Promise<T | null> {
return null
}

function freshMaybeResolve(name: string) {
export function resolveJsFrom(base: string, id: string): string {
try {
return localRequire.resolve(name)
return esmResolver.resolveSync({}, base, id) || id
} catch (err) {
return null
return cjsResolver.resolveSync({}, base, id) || id
}
}

export { resolveFrom }

0 comments on commit 98c4812

Please sign in to comment.