Skip to content
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

Support tailwind css #1943

Closed
dattatreyapatil0 opened this issue Apr 14, 2021 · 17 comments · Fixed by #2460
Closed

Support tailwind css #1943

dattatreyapatil0 opened this issue Apr 14, 2021 · 17 comments · Fixed by #2460
Assignees
Labels

Comments

@dattatreyapatil0
Copy link

Adding custom postcss plugins is currently not supported, We'll be looking at this in the future.

Originally posted by @alan-agius4 in #1418 (comment)

@dattatreyapatil0
Copy link
Author

We have a custom component module built using tailwindcss and PostCSS as a dependency in an Angular app. We are now planning to make a library for that custom component module so that we can use in other apps. But I have realized that using customWebpacks is not allowed in Angular libraries. But building the components again right from scratch without using tailwind seems to be really tedious. Is there a workaround ?Could someone point me in right direction as how to proceed further?

@alan-agius4
Copy link
Member

Support for tailwincss has been included in Angular CLI 11.2, and add this support directly in ng-packagr is also being considered.

That being said so far we didn't receive any compelling use-case for this. Can you please elaborate which tailwinds features would you intend to leverage when building a library?

@dattatreyapatil0
Copy link
Author

Thanks for your reply @alan-agius4 .
What I mean is , in an Angular application we can use a custom webpack to make sure the tailwind and Postcss code is compiled.

"builder": "@angular-builders/custom-webpack:dev-server",
          "options": {
            "customWebpackConfig": {
              "path": "./webpack.config.js"
            },}

But however we can't use custom-webpack:dev-server in an Angular library because it uses
"builder": "@angular-devkit/build-angular:ng-packagr",.

As i mentioned earlier, we have a custom component module which was developed in an Angular Application and it uses tailwindCss and PostCss with a customWebpackConfig. But now, we need this component module in other applications also. The best way would be to create a private library so that other developers can just install and use it as and when required. But however I am not getting a way where I can proceed further because I can't use a customWebpackConfig for TailwindCss compilation?
Please correct me if I am wrong somewhere.

@alan-agius4
Copy link
Member

Hi @dattatreyapatil0,

JFYI, custom-webpack is no longer needed since Angular CLI 11.2 to enable Tailwind in an Application see: angular/angular-cli#19935

I am more interested to know, which features of tailwind you are going to use in the component library. I am asking because in many cases you'd want to limit the usage of tailwind in a component, in order to avoid generating duplicate CSS across components.

But I think allowing Tailwinds functions and directives, example @apply, @screen etc... to be used seems like a reasonable feature request.

@dattatreyapatil0
Copy link
Author

Hi @alan-agius4 ,
Yes, exactly features like @apply , @include etc. Because one of our developers has already built the component module using these, but in order to make a library for this seems not to work at the moment.
Could you suggest any work around or point me in a right direction?

@alan-agius4
Copy link
Member

Hi @dattatreyapatil0, at the moment the only workaround would be to patch the ng-packagr locally.

@alan-agius4 alan-agius4 changed the title Adding custom postcss plugins is currently not supported, We'll be looking at this in the future. Support tailwind css Apr 15, 2021
@alan-agius4 alan-agius4 pinned this issue Apr 15, 2021
@dattatreyapatil0
Copy link
Author

Hi @alan-agius4 ,
And how can i do that ? Any guide or reference to achieve that ?

@alan-agius4
Copy link
Member

@dattatreyapatil0, you can change this file https://github.com/ng-packagr/ng-packagr/blob/master/src/lib/styles/stylesheet-processor-worker.ts#L95 in your node_modules and than apply the patch using https://www.npmjs.com/package/patch-package

NB: by doing the above you are opting to be on the unsupported path.

@dattatreyapatil0
Copy link
Author

Hi @alan-agius4 ,
thank you for letting me know the steps.
But for now I have found a work around. Since we are using the components internally(within the team) , I am just exporting css files in the lib and then getting them compiled in the app once we install the lib. It's not ideal but serving the purpose as of now.

I will try the way you suggested in coming days.
Thank you again.

@Jimeh87
Copy link

Jimeh87 commented May 3, 2021

Based on @alan-agius4 I think I've got it working! Although I would love to see this feature added. More and more companies are building component libraries and now that Angular is providing first class support for Tailwind in Angular applications I could see the demand for tailwind skyrocketing.

Here is what I did:

Add the classic tailwind dependencies:
npm i -D tailwindcss autoprefixer postcss postcss-import postcss-loader postcss-scss

next get your tailwind config file created
npx tailwindcss init

then add patch-package:
npm i -D patch-package

Next either update node_modules/ng-packagr/lib/styles/stylesheet-processor-worker.js based on the patch I pasted below and then run npx patch-package ng-packagr or you can take the patch I pasted and add it as patches/ng-packagr+11.2.4.patch where 11.2.4 is the version of ng-packagr.

patch:

diff --git a/node_modules/ng-packagr/lib/styles/stylesheet-processor-worker.js b/node_modules/ng-packagr/lib/styles/stylesheet-processor-worker.js
index 0dae92e..32b93cc 100644
--- a/node_modules/ng-packagr/lib/styles/stylesheet-processor-worker.js
+++ b/node_modules/ng-packagr/lib/styles/stylesheet-processor-worker.js
@@ -7,6 +7,11 @@ const postcssUrl = require("postcss-url");
 const cssnano = require("cssnano");
 const stylesheet_processor_1 = require("./stylesheet-processor");
 const fs_1 = require("../utils/fs");
+
+const postcssimport = require('postcss-import');
+const tailwindcss = require("tailwindcss");
+const tailwindConfig = require("../../../../tailwind.config");
+
 async function processCss({ filePath, browserslistData, cssUrl, styleIncludePaths, basePath }) {
     // Render pre-processor language (sass, styl, less)
     const renderedCss = await renderCss(filePath, basePath, styleIncludePaths);
@@ -80,6 +85,8 @@ function optimizeCss(filePath, css, browsers, cssUrl) {
     if (cssUrl !== stylesheet_processor_1.CssUrl.none) {
         postCssPlugins.push(postcssUrl({ url: cssUrl }));
     }
+    postCssPlugins.push(postcssimport);
+    postCssPlugins.push(tailwindcss(tailwindConfig));
     // this is important to be executed post running `postcssUrl`
     postCssPlugins.push(autoprefixer(browsers));
     postCssPlugins.push(cssnano({

Next add "postinstall": "patch-package" to your base package.json

Finally you need to add your tailwind imports. To test things out I would suggest adding them to one of your component scss files and seeing if it works.

@import '~tailwindcss/base';
@import '~tailwindcss/utilities';
@import '~tailwindcss/components';

I'm not sure what the best strategy for having a common styles spreadsheet between components is. Right now I just have a styles.scss in my lib directory that import the tailwindcss that all of my other components add via the styleUrls.

Hope this helps!

@nicolaric
Copy link

hey guys, are there any updates on that? It would be super helpful, if this would be supported.

@pbrennand-francis
Copy link

Support for tailwind functions like @apply would be awesome. Any updates on this would be much appreciated :)

@gfsd3v
Copy link

gfsd3v commented Mar 23, 2022

I would also love this feature. Could u guys point me to some guidelines about making a PR for it? I'm down to help with anything possible.

@DibyodyutiMondal
Copy link

DibyodyutiMondal commented Apr 17, 2022

At the moment, the best workaround I have found is that the consuming project (example: website) adds the output/source folder of the library in the content part of the tailwind config.

(The disadvantages/shortcomings for this method is mentioned at the bottom)

Example A: Using the Library source directly

Folder structure

projects
  - website
    - src
    - tailwind.config.js
    - ... other stuff
  - library
    - src
    - tailwind.config.js
    - ... other stuff
angular.json
tsconfig.base.json
... other stuff

To use the library with tailwind, update /projects/website/tailwind.config.js

module.exports = {
  content: [
    // how you resolve the folder is up to you. I always run build from the workspace root, hence path.join and process.cwd() is used
    // the regex is essentially telling tailwind process the given file extensions, but ignore tests and storybook files
    // the following will process the website's files. I use scss for stylesheets. If you use vanilla css/sass, 
    // include the respective extension in the regex
    join(process.cwd(), 'projects/website/src', '**/!(*.stories|*.spec).{ts,html,scss}')  

    // the following will process the library's files.
    join(process.cwd(), 'projects/libary/src', '**/!(*.stories|*.spec).{ts,html,scss}')  
  ],
}

Example B: Library in node_modules or in dist

Folder structure

projects
  - website
    - src
    - tailwind.config.js
    - ... other stuff
  - internal-library (output to dist/internal-library)
    - src
    - tailwind.config.js
    - ... other stuff
node_modules
  - external-library
  - ... other stuff
angular.json
tsconfig.base.json
... other stuff

To use the libraries with tailwind, update /projects/website/tailwind.config.js

module.exports = {
  content: [
    // this the website's source files
    join(process.cwd(), 'projects/website/src', '**/!(*.stories|*.spec).{ts,html,scss}')  

    // the following will process the library's files. If you look into the output/node_modules of the library you depend on
    // you will see that the code exists in .mjs files (at least, in my case), so we'll only need that extension. 
    join(process.cwd(), 'dist/internal-library', '**/!(*.stories|*.spec).{mjs}'),
    join(process.cwd(), 'node_modules/external-library', '**/!(*.stories|*.spec).{mjs}')  
  ],
}

Disadvantages

The caveat is that this method expects similar configuration for the tailwind theme. It's not strictly necessary, but essentially, what'll happen is that the website's tailwind config is going to wipe away the tailwind config of the library (repeat: not override - completely replace), unless you import the library's tailwind config into the website's tailwind config and merge the theme objects as you need. This is easy for a local library, but if you are publishing the library, you might want to include the tailwind.config.js as an asset in the angular configuration, so that it is available to consumers.

Note: I have not tested whether ViewEncapsulation has any effect on this. I use angular material, and anything apart from the default breaks that, so I stayed away from playing with that.

@kryshac
Copy link
Contributor

kryshac commented May 24, 2022

patch for version 13.3.1

diff --git a/node_modules/ng-packagr/lib/styles/stylesheet-processor.js b/node_modules/ng-packagr/lib/styles/stylesheet-processor.js
index b58c1d8..e40d2ff 100644
--- a/node_modules/ng-packagr/lib/styles/stylesheet-processor.js
+++ b/node_modules/ng-packagr/lib/styles/stylesheet-processor.js
@@ -36,6 +36,11 @@ const postcss_url_1 = __importDefault(require("postcss-url"));
 const esbuild_executor_1 = require("../esbuild/esbuild-executor");
 const cache_1 = require("../utils/cache");
 const log = __importStar(require("../utils/log"));
+
+const postcssimport = require("postcss-import")
+const tailwindcss = require("tailwindcss")
+const tailwindConfig = require("../../../../tailwind.config")
+
 var CssUrl;
 (function (CssUrl) {
     CssUrl["inline"] = "inline";
@@ -137,6 +142,10 @@ class StylesheetProcessor {
         if (this.cssUrl !== CssUrl.none) {
             postCssPlugins.push((0, postcss_url_1.default)({ url: this.cssUrl }));
         }
+
+        postCssPlugins.push(postcssimport)
+        postCssPlugins.push(tailwindcss(tailwindConfig))
+
         postCssPlugins.push((0, postcss_preset_env_1.default)({
             browsers: this.browserslistData,
             autoprefixer: true,

@michaelfaith
Copy link
Contributor

michaelfaith commented Oct 18, 2022

With the announcement of flex-layout's deprecation, would it be possible to prioritize this support? Tailwind is listed as a viable migration route for projects using flex-layout (https://blog.angular.io/modern-css-in-angular-layouts-4a259dca9127). It would be nice to be able to move to it more officially in libraries, for our layout needs.

@alan-agius4 alan-agius4 self-assigned this Oct 21, 2022
alan-agius4 added a commit to alan-agius4/ng-packagr that referenced this issue Oct 21, 2022
This feature adds detection of the `tailwindcss` package (https://tailwindcss.com) and provides a mechanism to automatically include support. To enable tailwindcss for a project, two actions must be taken:
1) Install `tailwindcss` (`npm install -D tailwindcss`/`yarn add -D tailwindcss`)
2) Create a tailwindcss configuration file (`tailwind.config.js`) in the project root.  A configuration file in the project root takes precedence over one in the workspace root.

Closes ng-packagr#1943
alan-agius4 added a commit to alan-agius4/ng-packagr that referenced this issue Oct 21, 2022
This feature adds detection of the `tailwindcss` package (https://tailwindcss.com) and provides a mechanism to automatically include support. To enable tailwindcss for a project, two actions must be taken:
1) Install `tailwindcss` (`npm install -D tailwindcss`/`yarn add -D tailwindcss`)
2) Create a tailwindcss configuration file (`tailwind.config.js`) in the project root.  A configuration file in the project root takes precedence over one in the workspace root.

Closes ng-packagr#1943
@alan-agius4 alan-agius4 unpinned this issue Oct 21, 2022
alan-agius4 added a commit that referenced this issue Oct 21, 2022
This feature adds detection of the `tailwindcss` package (https://tailwindcss.com) and provides a mechanism to automatically include support. To enable tailwindcss for a project, two actions must be taken:
1) Install `tailwindcss` (`npm install -D tailwindcss`/`yarn add -D tailwindcss`)
2) Create a tailwindcss configuration file (`tailwind.config.js`) in the project root.  A configuration file in the project root takes precedence over one in the workspace root.

Closes #1943
@github-actions
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

This action has been performed automatically by a bot.

@github-actions github-actions bot locked and limited conversation to collaborators Nov 21, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

Successfully merging a pull request may close this issue.

9 participants