argyleink / open-props

CSS custom properties to help accelerate adaptive and consistent design.
https://open-props.style
MIT License
4.78k stars 193 forks source link

JIT duplicates variables when used with SvelteKit #315

Closed knpwrs closed 2 years ago

knpwrs commented 2 years ago

I am not sure if this happens with other frameworks as well. In SvelteKit, using the following postcss.config.cjs file:

const postcssJitProps = require('postcss-jit-props');
const OpenProps = require('open-props');

module.exports = {
  plugins: [postcssJitProps(OpenProps)],
};

And the following svelte.config.js file:

import adapter from '@sveltejs/adapter-auto';
import preprocess from 'svelte-preprocess';

/** @type {import('@sveltejs/kit').Config} */
const config = {
  // Consult https://github.com/sveltejs/svelte-preprocess
  // for more information about preprocessors
  preprocess: preprocess({
    postcss: true,
  }),

  kit: {
    adapter: adapter(),
  },
};

export default config;

And with two .svelte files, each defining a class with color: var(--red-6);, I get the following CSS output in both development and production:

:root{--red-6:#fa5252}h1.s-7IPF32Wcq3s8{color:var(--red-6)}.s-7IPF32Wcq3s8{}
:root{--red-6:#fa5252}h2.s-jKAGgCyjj-PQ{color:var(--red-6)}.s-jKAGgCyjj-PQ{}

In Tailwind's SvelteKit setup docs their jit setup generates a single CSS file to import into your app. Is something like this possible with Open Props? Essentially generate a single CSS file that contains only the props I use and then include that CSS file in the app.

argyleink commented 2 years ago

CSS modules make JIT difficult because each css file is individually evaluated and the postcss plugin isn't given awareness of this, so each file gets its own scope. AKA, this does happen in other frameworks, like Next that uses CSS modules. Next has a concept of :global which almost helps, but can result in similar things as you have above.

You could work around this by running a follow up plugin on the output of the css processes, that combines media queries and then another pass with like UnCSS which can remove duplicates.

Again tho yeah, the problem is that the plugins are ran per file without any context or provided any stylesheet that's a global file to put the discovered props into. With CSS modules, i think the best route forward for a minimal amount of props shipped, is to individually import a color palette, or sizes, from open props, and drop them into a global file you have. then all the module files can just use them, without jit props, and you can add or remove prop packs as you need. this will lead to shipping more reds, for exaple, then you may be using, but it's not going to bulk up your stylesheet by an amount to be worried about.

knpwrs commented 2 years ago

Is there a way to implement the way Tailwind does it?

argyleink commented 2 years ago

probably! it's all code and connective tissue could get made so that jit-props gets given a file like app.css to inject the discovered props into. looks like with sveltekit and tailwind, there's a file established as a global space and then their plugin uses that file for the destination of injection. jit-props can be provided a selector context for props, it could be extended to accept a file also.

argyleink commented 2 years ago

going to close this here as we should continue to convo in the jit-props plugin