惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
C
CERT Recently Published Vulnerability Notes
人人都是产品经理
人人都是产品经理
V
Visual Studio Blog
大猫的无限游戏
大猫的无限游戏
月光博客
月光博客
L
LangChain Blog
J
Java Code Geeks
B
Blog
博客园_首页
Engineering at Meta
Engineering at Meta
宝玉的分享
宝玉的分享
D
Docker
L
LINUX DO - 最新话题
Vercel News
Vercel News
aimingoo的专栏
aimingoo的专栏
Microsoft Security Blog
Microsoft Security Blog
Scott Helme
Scott Helme
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
The Blog of Author Tim Ferriss
U
Unit 42
T
Tenable Blog
F
Fortinet All Blogs
K
Kaspersky official blog
博客园 - 【当耐特】
T
Tailwind CSS Blog
Y
Y Combinator Blog
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Hacker News
The Hacker News
美团技术团队
S
Schneier on Security
P
Proofpoint News Feed
H
Hackread – Cybersecurity News, Data Breaches, AI and More
P
Proofpoint News Feed
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Microsoft Azure Blog
Microsoft Azure Blog
MongoDB | Blog
MongoDB | Blog
Cisco Talos Blog
Cisco Talos Blog
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
NISL@THU
NISL@THU
T
The Exploit Database - CXSecurity.com
L
Lohrmann on Cybersecurity
Martin Fowler
Martin Fowler
Blog — PlanetScale
Blog — PlanetScale
酷 壳 – CoolShell
酷 壳 – CoolShell
The Cloudflare Blog
I
Intezer
有赞技术团队
有赞技术团队

Nx Blog

Sharing Tailwind CSS Styles Across Apps in a Monorepo | Nx Blog How SiriusXM Stays Competitive by Iterating and Getting to Market Fast | Nx Blog Agentic Experience Is the New Developer Experience | Nx Blog Nx Joins the Linux Foundation and the Agentic AI Foundation | Nx Blog A Monorepo Is NOT a Monolith | Nx Blog Why we deleted (most of) our MCP tools | Nx Blog Teach Your AI Agent How to Work in a Monorepo | Nx Blog How Broadcom stays efficient and nimble with monorepos | Nx Blog Why Monorepos are King in the Age of AI | Nx Blog Nx 2026 Roadmap: Expanding Agent Autonomy, Improving Performance, Better Polyglot and More | Nx Blog End to End Autonomous AI Agent Workflows with Nx | Nx Blog Autonomous Agents at Scale | Nx Blog Scaling 700+ Projects: How Nx Became a 'No-Brainer' for Caseware | Nx Blog The Missing Multiplier for AI Agent Productivity | Nx Blog A Year of Nx Webinars | Nx Blog Wrapping Up 2025 | Nx Blog Nx 22.3 Release: Angular 21 Support, tsgo Compiler, and Prettier v3 | Nx Blog Nx Cloud Release: Agent Resource Usage | Nx Blog Nx Platform Outperforms DIY Cache by 5x | Nx Blog An Nx Carol: Past, Present, and Future of Your Monorepo | Nx Blog Nx 22.1 Release: Terminal UI on Windows, Storybook 10, Vitest 4, and more! | Nx Blog The Compounding Effect: How Nx Features Multiply Performance Gains | Nx Blog 10 Monorepo Myths Debunked: Separating Fact from Fiction | Nx Blog Nx Cloud Release: Enterprise Task Analytics | Nx Blog Watch and Rebuild Storybook Dependencies with Nx | Nx Blog Book - React for Enterprise: Timeless Architecture for Enterprise Apps | Nx Blog Beyond Remote Cache: Unlock 70% More CI Performance | Nx Blog Nx 22 Release: Expanding the build platform | Nx Blog What's the Point of Generating All This Code If You Can't Merge It? | Nx Blog What's New in Nx Self-Healing CI | Nx Blog Nx Highlights: Smarter AI integration, all-new graph UI, and big new versions of your favorite tools | Nx Blog Making the Case for Smarter Monorepos, and How to Not Get Fooled by Myths | Nx Blog Integrating Biome in 20 Minutes | Nx Blog S1ngularity - What Happened, How We Responded, What We Learned | Nx Blog Stop Babysitting Your PRs: Self-Healing CI Cuts Time to Green by 50% | Nx Blog UKG Unifies Their Codebase and Eliminates CI Overhead to Focus on Customer Value | Nx Blog How Git Worktrees Changed My AI Agent Workflow | Nx Blog Nx Cloud Workspace Graph: See Your Organization's Code Structure Like Never Before | Nx Blog Seamless Java Deployment in Nx Using Docker | Nx Blog Getting Mobile Into Your Monorepo: Android + Nx | Nx Blog Polyglot Projects Made Easy: Integrating Spring Boot into an Nx Workspace | Nx Blog The Journey of the Nx Plugin for Gradle: From Prototype to Production | Nx Blog Combining Predictability and Intelligence With Nx Generators and AI | Nx Blog A New UI For The Humble Terminal | Nx Blog Continuous tasks are a huge DX improvement | Nx Blog New and Improved Module Federation Experience with Nx | Nx Blog A New UI for Nx Migration | Nx Blog Custom Task Runners and Self-Hosted Caching Changes | Nx Blog Enterprise Angular Monorepo Patterns | Nx Blog Using Rspack with Angular | Nx Blog Angular Architecture Guide To Building Maintainable Applications at Scale | Nx Blog Modern Angular Testing with Nx | Nx Blog Nx Update: 20.5 | Nx Blog Are Monorepos the Answer to Better AI-Assisted Development? | Nx Blog Making Cursor Smarter with an MCP Server For Nx Monorepos | Nx Blog React Development for 2025 | Nx Blog Using Apollo GraphQL in an Nx Workspace | Nx Blog Angular State Management for 2025 | Nx Blog Tailoring Nx for Your Organization | Nx Blog Nx Cloud Pipelines Come To Nx Console | Nx Blog Define the relationship with monorepos | Nx Blog See your affected project graph in Nx Cloud | Nx Blog Handling CORS In Your Workspace | Nx Blog Improve your architecture and CI pipeline times with Nx projects | Nx Blog Announcing Nx 20 | Nx Blog Introducing Nx Powerpack | Nx Blog Nx 19.5 is here! Stackblitz, Bun, Incremental Builds for Vite, Gradle Test Atomizer | Nx Blog Introducing Explain with AI | Nx Blog Nx Enterprise Podcast Episode 2: Tine Kondo | Nx Blog Monorepos and CI can be a Mess - Here's How Nx and Nx Cloud Fixed It | Nx Blog Nx Enterprise Podcast Episode 1: Hicham El Hammouchi | Nx Blog Nx 19.0 Release!! | Nx Blog Manage Your Gradle Project using Nx | Nx Blog Making the Argument for Monorepos | Nx Blog Reliable CI. A new execution model fixing both flakiness and slowness | Nx Blog Monorepos - Why Speed Matters | Nx Blog Nx Agents Walkthrough: Effortlessly Fast CI Built for Monorepos | Nx Blog Launch Nx Week Recap | Nx Blog Versioning and Releasing Packages in a Monorepo | Nx Blog Fast, Effortless CI | Nx Blog Introducing @nx/nuxt Enhanced Nuxt.js Support in Nx | Nx Blog What if Nx Plugins Were More Like VSCode Extensions | Nx Blog Monorepos: the Benefits, Challenges, and Importance of Tooling Support | Nx Blog Nx — Highlights of 2023 | Nx Blog Nx 17.2 Update | Nx Blog Unit Testing Expo Apps With Jest | Nx Blog Nx Docs AI Assistant | Nx Blog State Management Nx React Native/Expo Apps with TanStack Query and Redux | Nx Blog Nx 17 has Landed | Nx Blog Nx Conf 2023 — Recap | Nx Blog Nx Raises $16M Series A | Nx Blog Introducing Playwright Support for Nx | Nx Blog Nx 16.8 Release!!! | Nx Blog Step-by-Step Guide to Creating an Expo Monorepo with Nx | Nx Blog Qwikify your Development with Nx | Nx Blog Create Your Own create-react-app CLI | Nx Blog Storybook Interaction Tests in Nx | Nx Blog Evergreen Tooling — More than Just CodeMods | Nx Blog Nx 16.5 Release!!! | Nx Blog A Practical Guide on Effective AI Use - AI as Your Peer Programmer | Nx Blog
Configure Tailwind v4 with Angular in an Nx Monorepo | Nx Blog
Juri Strumpflohner · 2026-01-15 · via Nx Blog

Tailwind CSS v4 brought significant simplifications: no more tailwind.config.js, minimal dependencies, and a simple CSS import to get started. But if you're using Angular with Tailwind v4 in an Nx monorepo, there's a catch: your production CSS might be larger than it needs to be.

This article explains how Tailwind v4's scanning works with Angular's PostCSS setup, why it can lead to bloated CSS output, and how to optimize it using @source directives and Nx Sync Generators.

Using Vite in an NPM Workspace?

Setting Up Tailwind v4 with Angular

Setting up Tailwind v4 with Angular is straightforward. Both the Angular docs and Tailwind docs have guides for this. But they miss one important aspect when working in a monorepo, which is what we're digging into today.

Since Angular uses PostCSS for CSS processing, you need the PostCSS plugin.

Install the required packages:

{
  "dependencies": {
    "@tailwindcss/postcss": "^4.1.13",
    "tailwindcss": "^4.1.13"
  }
}

Configure PostCSS in your application:

apps/demoapp/.postcssrc.json

{
  "plugins": {
    "@tailwindcss/postcss": {}
  }
}

Import Tailwind in your styles entry point:

apps/demoapp/src/styles.css

@import 'tailwindcss';

That's it. Your Angular app now has Tailwind v4 configured. But here's where things get interesting in a monorepo setup.

The Problem: Over-Scanning in Monorepos

Consider a typical Nx workspace structure:

apps/
  demoapp/           # Your Angular application
libs/
  ui-design-system/  # Shared UI components (used by demoapp)
  another-ui/        # Another library (NOT used by demoapp)

When you run nx build demoapp, you'd expect only the Tailwind classes from demoapp and its dependency ui-design-system to end up in the final CSS. But that's not what happens by default.

Let's say another-ui has a component with this template:

libs/another-ui/src/lib/another-ui/another-ui.html

<p class="text-red-500">AnotherUi works!</p>

Even though demoapp never imports another-ui, if you check your production CSS output, you'll find text-red-500 in there. This happens for every unused class in every library in your workspace.

Why Does This Happen?

The @tailwindcss/postcss plugin uses process.cwd() as its default scanning base:

// @tailwindcss/postcss source
let base = opts.base ?? process.cwd();

When you run nx build demoapp, process.cwd() is your workspace root. Tailwind scans from there, finding all .html, .ts, and other template files across your entire monorepo.

This is different from the @tailwindcss/vite plugin, which uses the Vite config root (typically the app directory) as its base. With Vite you have the opposite problem: not enough is included by default, so you must explicitly add library sources. If you're using Vite with React or other frameworks, check out the Tailwind v4 with Vite in an NPM Workspace guide.

You could restrict the scanning by providing the base property in your PostCSS config:

apps/demoapp/.postcssrc.json

{
  "plugins": {
    "@tailwindcss/postcss": {
      "base": "./apps/demoapp/src"
    }
  }
}

But then you'd need to manually add @source directives for all your library dependencies. We'll look at a more automated approach.

Comparing PostCSS vs Vite Plugin Behavior

PluginDefault BaseMonorepo BehaviorNeeds @source for libs?
@tailwindcss/postcssprocess.cwd()Scans entire workspaceOnly if you restrict with source()
@tailwindcss/viteconfig.rootScans app directory onlyYes, always

With the PostCSS plugin, you get all classes from all libraries. With the Vite plugin, you get only classes from the app and must explicitly add library sources. Both approaches benefit from automation to manage @source directives.

Solution: Restricting Scanning with @source Directives

Tailwind v4 provides the source() function and @source directive to control which directories get scanned.

Step 1: Restrict Automatic Scanning

Update your styles entry point to limit automatic scanning to just your app:

apps/demoapp/src/styles.css

@import 'tailwindcss' source('./app');

The source("./app") modifier tells Tailwind to only auto-scan the app subdirectory relative to this CSS file.

Step 2: Add Library Dependencies

Now you need to explicitly add your library dependencies:

apps/demoapp/src/styles.css

@import 'tailwindcss' source('./app');

@source "../../../libs/ui-design-system/src";

With this configuration:

  • Classes from apps/demoapp/src/app/** are included (via source("./app"))
  • Classes from libs/ui-design-system/src/** are included (via @source)
  • Classes from libs/another-ui/** are NOT included

Your production CSS now contains only what you actually use.

Automating @source with Nx Sync Generators

Manually maintaining @source directives works, but introduces maintenance burden:

  • Easy to forget when adding new dependencies
  • Missing styles don't break builds (just cause visual bugs)
  • Every team member needs to remember to update paths

Nx Sync Generators solve this by automatically keeping your @source directives in sync with your project dependencies.

Using @juristr/nx-tailwind-sync

In the Tailwind v4 with Vite in an NPM Workspace article, I explained how to build a custom sync generator to automate @source directive management. I've since packaged this into @juristr/nx-tailwind-sync so you can use it directly.

Install it:

npm install @juristr/nx-tailwind-sync

Register the sync generator in your application's project.json:

apps/demoapp/project.json

{
  "name": "demoapp",
  "targets": {
    "build": {
      "executor": "@angular/build:application",
      "syncGenerators": ["@juristr/nx-tailwind-sync:source-directives"],
      ...
    },
    "serve": {
      "executor": "@angular/build:dev-server",
      "syncGenerators": ["@juristr/nx-tailwind-sync:source-directives"],
      ...
    }
  }
}

Now when you run nx build demoapp or nx serve demoapp, the sync generator:

  1. Analyzes your application's dependency graph
  2. Generates @source directives for each dependency
  3. Updates your styles.css automatically

Your styles file gets managed markers:

apps/demoapp/src/styles.css

@import 'tailwindcss' source('./app');

/* nx-tailwind-sources:start */
@source "../../../libs/ui-design-system";
/* nx-tailwind-sources:end */

When you add a new library dependency, the next build or serve detects the change and updates the directives automatically.

How Sync Generators Work

Sync generators run before certain targets (like build or serve) and check if generated files are in sync with your source code. If something is out of sync, Nx prompts you to apply the changes.

This is the same mechanism Nx uses to keep TypeScript project references in sync with your dependency graph. Learn more in the Sync Generators documentation.

Alternative: PostCSS Plugin Approach

Community member Poul Hansen created a PostCSS plugin that achieves similar automation at build time rather than through sync generators.

This approach uses the createGlobPatternsForDependencies function from @nx/angular/tailwind to dynamically inject sources during the PostCSS processing phase. Check out the gist for implementation details.

Conclusion

Tailwind v4's simplified setup is great for standalone projects, but requires attention in monorepos. With Angular's PostCSS-based setup, the default behavior scans your entire workspace, potentially bloating your production CSS with unused classes.

By combining source() restrictions with @source directives and automating their maintenance through Nx Sync Generators, you get optimal CSS output without manual upkeep.

Learn More