Skip to content

Endless Loop in "Building Federation Artefacts" When Using @tailwindcss/postcss with Tailwind CSS 4 #785

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
1 of 2 tasks
smarza opened this issue Mar 3, 2025 · 5 comments · May be fixed by #820
Open
1 of 2 tasks

Comments

@smarza
Copy link

smarza commented Mar 3, 2025

With what library do you have an issue?

native-federation

Reproduction of the bug/regression with instructions

I'm experiencing an issue when integrating Tailwind CSS 4 with the native-federation setup. Following the official Tailwind CSS Angular guide, I upgraded to Tailwind CSS 4 and moved @tailwindcss/postcss to devDependencies (as suggested in #746).

After running ng serve [any project], any file change triggers an endless loop where the "Building federation artefacts" message is printed repeatedly, even though there are no new output file changes. This makes development very cumbersome.

Steps to Reproduce:

Clone the nf-test repository.
Install Tailwind CSS 4 following the Tailwind CSS Angular guide.
Move @tailwindcss/postcss from dependencies to devDependencies.
Run ng serve [any project].
Make any file change and observe the endless loop in the federation artifacts build process.

Expected behavior

The federation artifacts should build once (or only when necessary) rather than repeatedly triggering an endless build loop after each file change.

Versions of Native/Module Federation, Angular, Node, Browser, and operating system

@angular-architects/native-federation: ^19.0.5
Angular: ^19.0.0
Node: v22.10.0
Browser: (Issue observed during development; browser details not directly relevant)
Operating System: (Tested on your development OS – please specify if needed)

Other information

No response

I would be willing to submit a PR to fix this issue

  • Yes
  • No
@ratsey
Copy link

ratsey commented Mar 7, 2025

@smarza @manfredsteyer I'm seeing the same in my current work project.

I took a fork of the test Stackblitz project for a completely different issue I'm chasing and interestingly that doesn't do the loop, despite seemingly having the same settings for N-F, PrimeNG, Tailwind 4, and PostCSS. Something must be different - hopefully this repo might help expose something?

Edit: Sadly, this repo does exhibit the problem, my mistake. The difference is that it doesn't do it until something is changed. My work project does it right from the initial ng serve shell.

@ratsey
Copy link

ratsey commented Apr 2, 2025

Quick update on this one for my setup ... I couldn't get it to work, so went back to using the Tailwind CLI to build the output.css file. It's really not that much more effort than using postCSS.

@kettei-sproutty
Copy link

kettei-sproutty commented Apr 3, 2025

Running ng-serve with verbose flag, It appears to loop on tsconfig.federation.json flagging it each time as "modified".

EDIT:
Ok, the problem is little bit odd:
angular-esbuild-adapter.ts:355 calls doesFileExist, which compares the old content with a possible new content:

 if (!fs.existsSync(path)) {
    return false;
  }
  const currentContent = fs.readFileSync(path, 'utf-8');
  return currentContent === content;

The problem here is that content is the result of JSON.stringify, while currentContent is just the result of fs.readFileSync.

When we try to return the comparison between currentContent and content the comparison will always be false, ending always creating a new tsconfig.federation.json

  if (!doesFileExist(tsconfigFedPath, content)) {
    fs.writeFileSync(tsconfigFedPath, JSON.stringify(tsconfig, null, 2));
  }

I think the solution here is to add a new argument/create a different function that actually check if two JSON are equal such as:

function doesFileExist(path, content, jsonCompare = false) {
    if (!fs.existsSync(path)) {
        return false;
    }
    const currentContent = fs.readFileSync(path, 'utf-8');
    if (jsonCompare) {
       // maybe inside a try/catch
        const currentJson = JSON.parse(currentContent);
        const newJson = JSON.parse(content);
        return JSON.stringify(currentJson) === JSON.stringify(newJson);
    }
    return currentContent === content;
}

and updating the if:

  if (!doesFileExist(tsconfigFedPath, content, true)) {
    fs.writeFileSync(tsconfigFedPath, JSON.stringify(tsconfig, null, 2));
  }

I'm not really confident with the library and I'm not sure my analysis it's 100% correct, let me know!

EDIT 2:

If someone wants to try it meanwhile, you can:

  • Install patch-package as devDependencies
  • Add "postinstall": "patch-package", as script
  • In the root of your project create a patches folder.
  • Create a file called @angular-architects+native-federation+19.0.16.patch inside the patches folder:
diff --git a/node_modules/@angular-architects/native-federation/src/utils/angular-esbuild-adapter.js b/node_modules/@angular-architects/native-federation/src/utils/angular-esbuild-adapter.js
index 1512337..084c3db 100644
--- a/node_modules/@angular-architects/native-federation/src/utils/angular-esbuild-adapter.js
+++ b/node_modules/@angular-architects/native-federation/src/utils/angular-esbuild-adapter.js
@@ -204,16 +204,26 @@ function createTsConfigForFederation(workspaceRoot, tsConfigPath, entryPoints) {
     }
     const content = json5_1.default.stringify(tsconfig, null, 2);
     const tsconfigFedPath = path.join(tsconfigDir, 'tsconfig.federation.json');
-    if (!doesFileExist(tsconfigFedPath, content)) {
+    if (!doesFileExist(tsconfigFedPath, content, true)) {
         fs.writeFileSync(tsconfigFedPath, JSON.stringify(tsconfig, null, 2));
     }
     tsConfigPath = tsconfigFedPath;
     return tsConfigPath;
 }
-function doesFileExist(path, content) {
+function doesFileExist(path, content, jsonCompare = false) {
     if (!fs.existsSync(path)) {
         return false;
     }
+
+    if (jsonCompare) {
+      try {
+        const currentContent = fs.readFileSync(path, 'utf-8');
+        const currentJson = JSON.parse(currentContent);
+        const newJson = JSON.parse(content);
+
+        return JSON.stringify(currentJson) === JSON.stringify(newJson);
+      } catch (e) {}
+    }
     const currentContent = fs.readFileSync(path, 'utf-8');
     return currentContent === content;
 }
  • Install dependencies with your package manager

EDIT 3:
Probably is it just possible to remove json stringify passed to the doesFileExist

@yasmany-santalla
Copy link

yasmany-santalla commented May 8, 2025

I have the same issue, How I can fixed. @kettei-sproutty @ratsey @smarza

@smarza
Copy link
Author

smarza commented May 8, 2025

Hi @yasmany-santalla , I haven’t found any solutions so far, so I ended up downgrading to Tailwind CSS 3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants