8

The goal is to create component modules as Angular Library and keep it separate from the main application. So, components library maintained as standalone package published to NPM, and then can be imported into different applications. Component styles written using Tailwind's @apply utility - https://tailwindcss.com/docs/extracting-components

Requisitions

  • Both components library and main application use Tailwind CSS.
  • Tailwind's purge (PurgeCSS) should be applied to final project including components from external library.

Problem

I have problem with components styling in library using TailwindCSS, as final AMD and ES2015 builds contain inlined styles, which can't be processed by Tailwind configuration in main application.

It works great as soon as I'm using Angular Library locally at the same main project (see example of the components "local presentment"). But when I'm publishing library as NPM package, classes inlined into modules together with @apply utility which can't be processed correctly.

Example of the released library component code (ES2015 module):

styles: ["@layer components{.first-component-base {@apply w-full;} .first-component-base.first-component-disabled {@apply opacity-50;} .first-component-base .first-component-wrapper {@apply rounded-lg bg-skin-fill;} .first-component-base .first-component-wrapper .first-component-block {@apply max-w-7xl mx-auto py-3 px-3 sm:px-6 lg:px-8;} .first-component-text {@apply ml-3 font-medium text-white truncate;}}\n"]

As you can see, built module styles contain @apply which can't be processed by Tailwind configuration of main application if you add components library as NPM package.

Source code example, and README here - https://github.com/maxcoffer/angular-tailwind-library

Possible Solutions

This is what I've tried so far, or tested as examples, but it doesn't work exactly perfect or has own downsides.

  1. Use components extraction as TailwindCSS plugin (see documentation) - huge pain in the ass as you have no intellisense support for that method, and you need to write all styles within JS/TS which can be included into Tailwind configuration.

  2. Use inline Tailwind class names instead of component extraction with @apply - does work at some point, until you have complex components with dynamic behavioural styling (which is why I'm using SCSS and @apply).

  3. Write it like others, using CSS in JS/TS or even create configuration for each component with JS objects - again, no intellisense, no SCSS, no way to write styles using standard component styling methods.

Question

Can you suggest how to use @apply utility while making components (or any other efficient method without huge customisation), but also extract Tailwind classes during NPM package build process? Or how to extract inlined @apply from modules at the main application level?

Max Coffer
  • 81
  • 2
  • Could you tell me if you solved this issue? I'm trying to fix it now – JerryLee Nov 03 '21 at 10:20
  • Hi @JerryLee, for now we kept the Angular Library within the main project source-code. This allow us to import it as the normal package as @company/library into main project, and because Tailwind processed within same codebase it correctly apply JIT and exclude duplicates from both: main project styles and library styles together. – Max Coffer Nov 04 '21 at 12:00
  • @MaxCoffer I have same situation when library is kept in main project but when I use tailwind `@apply` inside library it doesn't work. Inline tailwind classes work well in library. Maybe you know what else should be done to make `@apply` work in library? – Maksat Rahmanov Feb 21 '22 at 09:08

3 Answers3

3

I found a solution, it's a bit hacky but it does the job. let's say the component you publish is called ui-components.

Modify your tailwind config on the parent project (the one using your component) to have something like this:

module.exports = {
  content: ['./src/**/*.html', './src/**/*.ts', './node_modules/ui-components/**/*.{html,ts,js}'],
  variants: {},
  plugins: [],
  corePlugins: {
  },
};
Tonio
  • 4,082
  • 4
  • 35
  • 60
  • 1
    I got this solution working in angular v14x by including ESM format (mjs) './node_modules/ui-components/**/*.{html,ts,js,mjs}' – imPK May 16 '23 at 16:02
0

This solution does not work for imported libraries that have @apply in the SCSS or CSS files. The @apply will simply be served as broken CSS to the browser.

I got this to work for me, by turning all of my @apply usages into classes in the HTML file of the component. This is not needed if they are in the same NX repo as the library.

Losing the @apply is a real bummer, as it means you can't just swap out the CSS files with your own custom styles in the host project, if you want to change things up.

user3201785
  • 11
  • 1
  • 2
0

I left a possible answer on a somewhat duplicate question - https://stackoverflow.com/a/72208906/9404093

High-level summary:

  • Create a pre-build process to resolve @applys
  • Run build as normal
  • If utility classes used in HTML, instruct depender app to include your .mjs files from node_modules directory in their content configuration of tailwind to scan.
Charly
  • 881
  • 10
  • 19