preactjs / preact-cli

😺 Your next Preact PWA starts in 30 seconds.
MIT License
4.69k stars 375 forks source link

preact build ignores CSS files #931

Closed DerDrodt closed 4 years ago

DerDrodt commented 4 years ago

Do you want to request a feature or report a bug? Bug

What is the current behaviour? When importing a CSS file, preact build ignores it while preact watch puts it in the build.

If the current behaviour is a bug, please provide the steps to reproduce. Import a CSS file without specifying imports.

import "@material/radio/dist/mdc.radio.css";

And run build. The CSS file will not be in the build folder and the page will miss this styles.

What is the expected behaviour? Preact bundles the styles in the CSS file, without changing the class names.

If this is a feature request, what is motivation or use case for changing the behaviour?

Please mention other relevant information.

Please paste the results of preact info here. Unknown argument: info

Version is 2.2.1

bojan88 commented 4 years ago

I guess the file you're trying to import is not being copied to the build folder.

I'm not sure if preact-cli supports CSS @import, but even if it does, it's not the best solution in most cases because it's making a request chain, and slowing down your web page. Better approach is to bundle your CSS in one file which preact-cli is currently doing.

If you want to import CSS files, you might wanna consider adding support for SASS to your project. In that case the file would be imported in build process and be part of your CSS chunk.

DerDrodt commented 4 years ago

I'm not sure if preact-cli supports CSS @import, but even if it does, it's not the best solution in most cases because it's making a request chain, and slowing down your web page.

I am not using @import in CSS. I am using CSS modules like it is done in the default template. However instead of import * as styles from './styles.css'; I just import it because I want all styles to be included.

Better approach is to bundle your CSS in one file which preact-cli is currently doing.

Whether it is its won CSS file or bundled doesn't matter to me. The problem is that these styles aren't included at all.

If you want to import CSS files, you might wanna consider adding support for SASS to your project. In that case the file would be imported in build process and be part of your CSS chunk.

I tried that, but it changed all the class names in the styles, which made them unusable. The problem with that is that material components use the class names in their JS code.

It is possible that these styles are included and I have not found them (even though I looked through the output files), but the class names are changed. But that would still be unexpected behavior, because the development build keeps the class names as is.

Is there a way to tell preact to just copy this file to the styles?

bojan88 commented 4 years ago

@DerDrodt sorry, my bad. I didn't quite understand the problem.

I have 2 possible workarounds for you:

  1. I think CSS files included in src/index.js don't have hashed class names. So moving your import "@material/radio/dist/mdc.radio.css"; to src/index.js might solve your issue.
  2. Install SASS and include your file like this from another .scss file:
    :global {
    @import "@material/radio/dist/mdc.radio.css";
    }
DerDrodt commented 4 years ago

Thanks, the second one did the trick!

mguentner commented 4 years ago

@DerDrodt What did you do exactly? If I include css files scss files like (2), I still get hashed class names in the resulting output.

mguentner commented 4 years ago

I am using the typescript template.

If module: true is not added here: https://github.com/preactjs-templates/typescript/blob/6849d32f667dde836602bbe426315079af87360f/template/preact.config.js#L23

typings for css files are not generated (css -> css.d.ts).

If it is enabled, so modules: true, class names will be hashed, imports do not work. No matter from css or from scss.

Similar issue (without solution): https://github.com/preactjs-templates/typescript/issues/16

DerDrodt commented 4 years ago

@DerDrodt What did you do exactly? If I include css files scss files like (2), I still get hashed class names in the resulting output.

I used SASS and added the following code:

:global {
    @import "@material/switch/mdc-switch";
}

Classes in :global don't seem to be hashed

mguentner commented 4 years ago

@DerDrodt Thanks. I couldn't figure out how to solve it with the typescript template and finally removed the typed css module loader and switched to https://github.com/Quramy/typed-css-modules which gives me a correct output.

ForsakenHarmony commented 4 years ago

The issue might happen if you include the css files in src/components or src/routes, because files imported from there get treated as css modules

wagg-matt commented 4 years ago

The issue might happen if you include the css files in src/components or src/routes, because files imported from there get treated as css modules

Is there a config setting where we can turn hashing of CSS off from files in these locations?

Essentially all i'm looking to do is have any component CSS sit with the component and simply import it into the file without the class name being hashed.

Found it:

let css = helpers.getLoadersByName(config, 'css-loader')[0];
css.loader.options.modules = false;
jp06 commented 4 years ago

@wagg-matt Thank you for the snippet. I'm working on a small project with the Simple template and came across the same problem. I started having all styles at src/styles.css and later, I thought it was big enough to split the styles into src/components/component-name/component-name.css files but I found out that the CSS files in the src/components doesn't seem to build which led me to this thread.

In my case, I didn't have didn't have a preact.config.js, so I just created it and put the following (with small changes):

export default {
    webpack(config, env, helpers, options) {
        const [ css ] = helpers.getLoadersByName(config, 'css-loader');
        css.loader.options.modules = false;
    }
};
dstudzinski commented 3 years ago

It's not closed so I'm posting my solutions to this. My project is started with preact-cli with typescript and I use sass (installation tips are in preact cli docs)

I installed https://github.com/TeamSupercell/typings-for-css-modules-loader and created preact.config.js file with:

export default {
  webpack(config, env, helpers, options) {
    const [css] = helpers.getLoadersByName(config, 'css-loader');
    css.rule.use.splice(1, 0, '@teamsupercell/typings-for-css-modules-loader');
  },
};

My classes are hashed and I can import sass files correctly in tsx files (like import {someClass} from './file.scss) as d.ts files are created side by side with scss files.

bmitchinson commented 2 years ago

dstudzinski's solution worked great for me.

My Example Repo