postcss-import
A PostCSS plugin that inlines @import rules, merging split CSS files into one stylesheet before other plugins run.
Repository Health
Technical Analysis
postcss-import is a PostCSS plugin that resolves and inlines CSS @import statements at build time. It can pull in content from local files, node_modules/web_modules packages, or data URLs, recursively following nested imports until a single flattened stylesheet remains. Because it runs as the first plugin in a PostCSS pipeline, every subsequent plugin sees one merged file instead of a tree of @import-linked partials, which avoids the correctness pitfalls that come from processing files independently.
Beyond straightforward inlining, it resolves node modules the same way Node’s own require algorithm does (checking a package’s style field, then main, then falling back to index.css), preserves @media/@layer/@supports conditions around imported content, detects and skips duplicate imports per-scope, and emits PostCSS dependency messages so watch-mode tooling knows which files to track. It has become a de facto standard for CSS import resolution and ships as a dependency inside many higher-level build tools and frameworks.
What You Get
- Recursive inlining of local, node_modules, and web_modules @import targets
- Preserved media/layer/supports conditions wrapped around inlined content
- Dependency messages on result.messages for watch-mode file tracking
- Configurable custom resolve/load functions for non-standard module setups
- Per-scope duplicate import detection to avoid redundant CSS output
Common Use Cases
- Splitting a large stylesheet into maintainable partials that get merged at build time
- Importing shared CSS packages published to npm by name, resolved like a JS require
- Feeding watch-mode build tools accurate per-file dependency information
- Running as the first step in a PostCSS pipeline ahead of Tailwind/Autoprefixer/etc.
Under The Hood
Architecture
The plugin follows a linear pipeline architecture rooted in a single AtImport factory (index.js) that returns a PostCSS plugin object with one Once hook; execution flows from parse-statements.js (which walks the root AST and classifies each node into import/charset/layer/nodes statements) into parse-styles.js, which recursively resolves each @import via resolve-id.js (a thin wrapper around the resolve package’s node-module algorithm) and load-content.js, then re-parses the loaded content and recurses back into itself to handle nested imports, accumulating a per-scope importedFiles map to dedupe by resolved path and by a media/layer/supports key computed in format-import-prelude.js. Once the tree is resolved, apply-conditions.js wraps content in the appropriate @media/@layer/@supports nodes, apply-raws.js normalizes whitespace, and apply-styles.js performs the final in-place AST replacement of the original import node. Each lib/*.js file has a single, narrow responsibility with no dependency-injection framework — resolve/load are passed as plain functions through an options object — and the main risk surface for change is the parseStyles/resolveImportId recursion contract that every other module relies on.
Tech Stack
The package targets Node >=22 and is built directly as a PostCSS 8 plugin (peerDependency postcss ^8.0.0), with runtime dependencies limited to postcss-value-parser (parsing/serializing @import prelude arguments like media queries and layer names), resolve (Node’s module-resolution algorithm, reused to resolve @import "some-package" against node_modules/web_modules), and read-cache (a small mtime-based cache around file reads to avoid re-reading unchanged files across builds). There is no bundler or transpiler step — the package ships plain CommonJS with no build step. Dev tooling is test/lint focused: ava and c8 for tests and coverage, eslint (with eslint-config-problems and eslint-plugin-prettier) and prettier for style, wired through an npm run ci script.
Code Quality
Testing uses ava with c8 coverage, and the suite is fixture-driven: a shared checkFixture helper runs a named CSS fixture through the plugin and diffs the output against an expected file, with extensive dedicated suites covering media queries, layers, filters, custom resolvers, custom loaders, sourcemaps, syntax errors, and plugin chaining — a genuinely thorough behavioral test suite for a package this size. Error handling is explicit and PostCSS-idiomatic: failures are thrown via node.error(...)/atRule.error(...) so they carry source-file and line context rather than generic errors, and async failures propagate naturally through async/await rather than being swallowed. The codebase is plain CommonJS with no TypeScript types, so there is no static type safety, but naming conventions are consistent across every lib file and a Prettier-integrated ESLint config enforces uniform style, gated by lint-then-test in CI.
API Design
The public API is a single factory function accepting a flat options object (root, path, plugins, resolve, load, skipDuplicates, addModulesDirectories, warnOnEmpty) with sensible defaults, so the zero-config case (postcss().use(atImport())) works immediately while advanced use (custom resolvers/loaders, extra plugin chains) is opt-in rather than required upfront. Documentation in the README is thorough for a small plugin, covering every option with type, default, and example usage, and the dependency message convention is a documented, stable extension point other tooling can rely on without reading source.
Used by 33 apps in this directory
Trigger.dev
AI Development · Automation · Developer Tools
Build and deploy fully-managed AI agents and background jobs in TypeScript — with no timeouts, durable retries, real-time observability, and elastic scaling built in.
Umami
Analytics
Privacy-first web analytics that respects your users — self-hosted, cookieless, and GDPR compliant out of the box.
Webiny JS
Blogging · CMS · Ecommerce
Open-source, self-hosted CMS on AWS serverless — a TypeScript framework you extend with code, not a product you configure through a UI.
Wiki.js
Collaboration · Knowledge Management
A modern, self-hosted wiki platform built on Node.js with a rich plugin ecosystem for authentication, search, storage, and rendering that adapts to any team's infrastructure.
Wire
Collaboration · Team Chat · Video Conferencing
Open source end-to-end encrypted messaging for teams and enterprises — self-host for complete control over your communications and data.
Zulip
Team Chat
Topic-based team chat that brings the structure of email threads to real-time messaging, so distributed teams never lose context across hundreds of concurrent conversations.