Skip to content

Bare-package CSS @import 'pkg/file.css' is reported as a relative ./pkg/file.css unresolved import #252

@OmerGronich

Description

@OmerGronich

What happened?

Related (already fixed for SCSS/SASS, not for CSS): issue #245SCSS @use 'X' resolves to X.tsx instead of X.scss when both siblings exist — was fixed in commit a0944ea and shipped in v2.60.0. That fix touches the stylesheet resolver but only for .scss / .sass importers; the equivalent path for plain .css importers is unchanged. The reproduction below was re-run against v2.60.0 and the bug still reproduces.

When a .css file does a bare-package @import such as

@import 'tailwindcss/theme.css' layer(theme);
@import 'tailwindcss/utilities.css';

— which Tailwind CSS v4, npm-published CSS bundles (e.g. leaflet/dist/leaflet.css, cropperjs/dist/cropper.css, highlight.js/styles/github.css), and every modern CSS bundler resolve via the standard package-name lookup in node_modules/<pkg>/<file>.css — fallow reports them in unresolved_imports as if the source had written a relative path:

{
  "path": "src/main.css",
  "specifier": "./tailwindcss/theme.css",
  "line": 1
}

Notice the leading ./ that the source code does not contain. The original specifier in the file is tailwindcss/theme.css (a bare-package import); fallow is rewriting it to a relative path before attempting resolution and then complaining the relative file doesn't exist on disk.

This pattern is the default style for Tailwind v4 (PostCSS approach) and is widely used across npm-published CSS bundles.

Reproduction

A self-contained, copy-paste-runnable repro that produces the bug from a clean directory:

  1. Create a fresh project:

    mkdir repro-tailwind-css-import && cd repro-tailwind-css-import
  2. Add a minimal package.json that installs Tailwind v4:

    {
      "name": "repro-tailwind-css-import",
      "private": true,
      "dependencies": {
        "tailwindcss": "4.1.13"
      }
    }
  3. Add a stub tsconfig.json:

    {
      "compilerOptions": {
        "target": "ES2022",
        "module": "ES2022",
        "moduleResolution": "bundler",
        "strict": true,
        "skipLibCheck": true
      }
    }
  4. Create the entry CSS that uses the v4 bare-package imports:

    mkdir src
    cat > src/main.css <<'EOF'
    @import 'tailwindcss/theme.css' layer(theme);
    @import 'tailwindcss/utilities.css';
    EOF
  5. Add a stub TS entry that side-effect-imports the CSS so fallow follows it:

    cat > src/main.ts <<'EOF'
    import './main.css';
    export const VERSION = '1.0.0';
    EOF
  6. Add a fallow config:

    {
      "$schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/schema.json",
      "entry": ["src/main.ts"]
    }
  7. Install (no need to actually run Tailwind):

    npm install --ignore-scripts
  8. Verify Tailwind ships the imported files (sanity check that the bare-package lookup should succeed):

    ls node_modules/tailwindcss/theme.css node_modules/tailwindcss/utilities.css
  9. Run fallow and observe:

    fallow dead-code --format json --quiet | jq '.unresolved_imports'

Expected behavior

Fallow should resolve @import 'tailwindcss/theme.css' the same way every CSS bundler does:

  1. Try node_modules/tailwindcss/theme.css (exists ✅) — done.
  2. If that misses, fall back to the package's exports / style field.
  3. Only if both miss, report unresolved — and report the original specifier (tailwindcss/theme.css), not a rewritten relative form.

In this repro: no entry in unresolved_imports, and tailwindcss is correctly counted as used.

Fallow version

2.60.0

Operating system

macOS

Configuration

{
  "$schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/schema.json",
  "entry": ["src/main.ts"]
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions