QwikDev / qwik

Instant-loading web apps, without effort
https://qwik.dev
MIT License
20.68k stars 1.29k forks source link

Pure qwik app/library: CSS from library doesn't load in the app by default #948

Closed dzearing closed 8 months ago

dzearing commented 2 years ago

Qwik Version

0.0.39

Operating System (or Browser)

windows

Node Version (if applicable)

No response

Which component is affected?

Qwik Rollup / Vite plugin

Expected Behaviour

  1. Create a component library from starter and add a component which imports styles in module.css.
  2. Build the component library to produce the /lib/ folder content. This produces a concatenated .css file.
  3. Create a qwik app and npm link to the library. Add the component to your page.

Expected: Component renders and is styled.

Actual Behaviour

Component renders and is missing styling. It is ok if there is a manual step here as long as it's documented somewhere, but I'm not sure what the strategy currently is. Either it should just work, or there should be some docs here.

I also want to suggest: concatenating the css at the library layer seems less ideal. If I export 20 components and the consumer uses 3 of them, I'd prefer to only have 3 modules worth of styling processed.

A better approach perhaps: let the library emit extractable but functional intermediate output so that optimization can happen later. Make the app build extract the module css referenced in the build graph and do this work once we understand the bundle output.

This essentially is what we are working on here: https://github.com/microsoft/griffel (runtime injectable css but extractable at app build time.) Similar to stylex from facebook or Linaria.

Additional Information

No response

manucorporat commented 2 years ago

I will look into this issue this weekend, can you share a small component that reproduces the issue?

dzearing commented 2 years ago

@manucorporat Created a small repro repo here: https://github.com/dzearing/qwik-library-styling-repro

README explains everything; look for the "red background Counter". Works in isolation within the library, but styling won't come along to the app on usage.

dzearing commented 1 year ago

@manucorporat did you get anywhere on this one?

wtho commented 1 year ago

@dzearing I think it makes sense to update the example to the current qwik version - just to make it easier to look at it

wmertens commented 1 year ago

@dzearing the .css inclusion is done by Vite I think, and apparently it doesn't do that for libraries?

In any case, it's probably a better approach to insert the style with useStyles$, that way it's only added when used.

zanettin commented 1 year ago

Hi @dzearing 👋 Does any of the provided tipps helped to solve the issue?

soluml commented 1 year ago

Not sure if this will help but hopefully additional context helps: Astro also has issues with CSS-in-JS tools and it's related to how Vite works. Hopefully some of the other tools dedicated Vite plugins can help!

I love how fast Vite is but it's always been a constant pain for me whenever trying to do CSS with tooling beyond Tailwind or CSS Modules.

faridarzpeyma commented 1 year ago

Almost have a similar issue with combination of qwik component lib in NX monorepo and using tailwind in that. Tailwind styles won't be picked up from component library unless I use same tailwind classes in another component in the quick city project. After that even if I remove the component tailwind styles remains on the document and applies correctly till restarting qwik city project.

Project structure: NX monorepo -> app/my-qwik-app (uses tailwind) -> libs/my-qwik-lib (uses tailwind but styles won't be picked up unless they are being used in my-qwik-app and works in dev even after removing usages till next restart)

I was trying this with qwik 1.0.0

noeliadv commented 1 year ago

Hi @dzearing 👋 Did you solve the problem?

limotek commented 1 year ago

I have the same issue. For now I add all needed classes in safelist in tailwind.config.js in my app just to get it going, but would love a better solution?

motss commented 12 months ago

Lib mode is completely broken. Does anyone have any workaround for this issue?

dzearing commented 11 months ago

@zanettin sorry for the slow response! I missed the notifications. I hadn't gotten anywhere on this, and just tried latest qwik with the same repro.

(cc @noeliadv - nope, hopefully we can find a solution here.)

dzearing commented 11 months ago

OK so I did manage to get some styles rendering in the host app, but it needs some automation I think. Maybe a better solution.

I'm not 100% familiar with how vite/qwik plugin css extraction might emit results, but after yarn build in the library folder, I see a lib/build/q-00e5211c.css file with the raw css styling. this is what we need to inject into the app.

The first challenge is how to access this styling from the app. I manually adding an exports path to resolve this file easily from an external consuming package:

{
   ...,
   "./styles.css": "./lib/build/q-00e5211c.css"
}

That means at the app level, I can pull styles manually:

// ...
import styles from 'qwik-library/styles.css';

export default component$(() => {
  useStyles$(styles);
}

This populated the styles the library defined in the host app. That said, it's probably not the right solution, but a workaround.

  1. I don't know how many of these css files could be generated. Will multiple css files be emitted as I add more components or async imports creating split points?
  2. As a consumer, I'd prefer to just import a component and only have THAT component's css be in my final page load - not every component in the library. How can we maintain the tiniest impact on the library styling to the app's page load?
wmertens commented 11 months ago

@dzearing checking to make sure: are the files that contain Qwik components and import css named as .qwik.(m)js?

That's necessary for the optimizer to work. However, importing css should normally be handled by vite, so probably that's not what's wrong.

dzearing commented 11 months ago

I don't think so. At least, the boilerplate "component library" template components which npm create qwik@latest produces look like this:

image

But... none of the files in the example are named .qwik.* (or load css.) I can try to change my component name and see what happens.

dzearing commented 11 months ago

I think the optimizer, or at least css extraction, really should not be operating on a component library. The component library is going to produce an intermediate npm package that should be easy to consume. It should (for dev mode) be bundlable as a standalone esm package, with css embeded in the js so that consumers don't need to fuss with loading css assets.

Then at the app layer, particularly for production builds, we run optimizer and css extraction, and other nice things like tree shaking and common chunks. These are slow (but awesome and critical) linear scale monolithic steps that need the full graph of information to make decisions.

Bascially - building a library should have a different set of steps than building an app. I think right now they might be the same.

dzearing commented 11 months ago

@wmertens I did try to rename my button.tsx to button.qwik.tsx but no change. The component-library demo app gets styles. The app importing the button does not get button styles without the workarounds.

wmertens commented 11 months ago

Hmm, there's a couple of moving parts here.

So, if you want to magically provide CSS for your user, your components should use useStyles$. Otherwise, you provide a .css file for them to import, and they can decide whether to use useStyles$ or add to their global .css themselves.

PS: Here it tests for .qwik.js https://github.com/BuilderIO/qwik/blob/270a7beaf9efd733849af946ab14eb15c8e7362d/packages/qwik/src/optimizer/src/plugins/plugin.ts#L564 - needed because library files can't have a .tsx extension

EggDice commented 11 months ago

Thank you @wmertens it works for me! :)

gioboa commented 8 months ago

@dzearing did you try the @wmertens solution? is it working for you?

hamatoyogi commented 8 months ago

Re checking - @dzearing any update here? did the solution work for you?

If it is, I'm marking this resolved.

in case the solution doesn't work, please re-open.