sveltejs / sapper

The next small thing in web development, powered by Svelte
https://sapper.svelte.dev
MIT License
6.99k stars 432 forks source link

rollup-plugin-postcss not working #699

Closed JadedBlueEyes closed 3 years ago

JadedBlueEyes commented 5 years ago

I can't seem to get postcss to work properly and extract my css like it does in pure svelte. With css extract option on it generates:

export default undefined;
export default undefined;
/* sourceMappingURL=./chunk.e3537e20.css.map */

but with it off, it generates:

var css = "a.link.svelte-131civd{color:#d3d3d3}";
export default css;
import styleInject from 'C:/Users/admin/Code/domainhax/node_modules/style-inject/dist/style-inject.es.js';
styleInject(css);
var css = "main.svelte-1joomdn{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto;width:64em}input.svelte-1joomdn{width:100%}#description.svelte-1joomdn>div.svelte-1joomdn{width:50%;padding:0;float:left}header.svelte-1joomdn{text-align:center}p.svelte-1joomdn{margin-top:0}a.svelte-1joomdn{color:#959595}h1.svelte-1joomdn a.svelte-1joomdn{color:#dfdfdf}";
export default css;
import styleInject from 'C:/Users/admin/Code/domainhax/node_modules/style-inject/dist/style-inject.es.js';
styleInject(css);
/* sourceMappingURL=./chunk.e3537e20.css.map */

In normal svelte when I do import './global.css', it generates a inlined bit of js with it off, and the processed file with it on, and does the same for svelte's generated CSS. I can't figure out what's going wrong, but I would like my css minified and prefixed.

maxmilton commented 5 years ago

For general support questions, you'll find https://stackoverflow.com/questions/tagged/svelte is probably a more appropriate place.


You need to give a bit more context for someone to understand your use case.

  1. What version of Svelte and Sapper?
  2. Which build tool, Webpack or Rollup?
  3. Are you trying to import that CSS file in a component or in a JS file?
  4. Are you using a Svelte preprocessor?
  5. How have you configured PostCSS?
  6. Are there any errors in your console?
  7. etc.
JadedBlueEyes commented 5 years ago
  1. This is sapper 0.26 with svelte 3.
  2. Rollup
  3. The CSS is both the css generated by svelte from the components and imported css, aka all the css that passes through rollup.
  4. No.
  5. postcss.config.js:
    module.exports = {
      extract: true,
      sourceMap: false,
      plugins: [
        require('@csstools/postcss-sass')(/* node-sass options */),
        require("postcss-import"),
        require("postcss-preset-env")({ stage: 4 }),
        require("autoprefixer")(),
        require("postcss-csso")
      ],
      parser: 'postcss-scss',
    }

    General standard across my projects.

  6. No - it's silent apart from babel telling me to specify core-js version
maxmilton commented 5 years ago

To process PostCSS in Svelte <style> blocks you need to set up a preprocessor such as https://github.com/TehShrike/svelte-preprocess-postcss or https://github.com/kaisermann/svelte-preprocess.

To process PostCSS imported in JS files you need to use a Rollup plugin such as https://github.com/egoist/rollup-plugin-postcss. Sapper will take care of emitting the CSS assets but you do need to process it first. The order of your Rollup plugins can also be important.

JadedBlueEyes commented 5 years ago

@MaxMilton As far as i'm aware, Svelte outputs the CSS file(s) to rollup, for rollup-plugin-postcss to take care of. This works fine with svelte by itself, but not with sapper! That's what I'm trying to say here, is sapper is somehow forcing the CSS files to be JS.

maxmilton commented 5 years ago

Svelte first parses the <style> blocks with css-tree in order to find any unused CSS selectors. Because of this the styles inside any <style> block must be valid CSS. Only then does it pass the styles through.

If you want your <style> blocks processed with PostCSS you need to use a preprocessor. See this comment for an example with SASS — the same thing applies using a PostCSS preprocessor.

If it's just the CSS files imported in JS that you're having issues with I suggest looking over your rollup PostCSS plugins docs.

JadedBlueEyes commented 5 years ago

I made a repo to demonstrate my issue. https://github.com/JoelEllis/sapper-postcss-issue

Quick side note - sapper seems to not work in Git Bash - if you run it in a fresh repo, it give some kind of error about can't find undefined\client.js. Possibly to do with git bash making windows paths POSIX so \ is an escape character rather than the path seperator in git bash?

dephiros commented 5 years ago

I run into this issues as well. What I am trying to do is to use the preprocessor to process svelte css Use rollup-plugin-postcss to process css imported by js Maybe if there is a way to make rollup-plugin-postcss ignore files emitted by svelte

Adding these to svelte rollup config fix it for me:

        emitCss: false,
        css: true,
JadedBlueEyes commented 5 years ago

@dephiros That works great. Thanks. TBH, this seems really unintuitive though - what makes it behave like this? @MaxMilton

JadedBlueEyes commented 5 years ago

In some of my projects it doesn't work though. I'm working around that by removing psotcss form the build, getting sapper to output css seperately and running postcss __sapper__/build/client/**/*.css --dir __sapper__/build/client --base __sapper__/build/client.

ghost commented 4 years ago

@JoelEllis This is based on the official template https://github.com/nhristov/sapper-template-rollup. It adds postcss, purgecss, cssnano, tailwindcss and svelte-preprocess without having to modify the build script in your package.json

JadedBlueEyes commented 4 years ago

Just reposting here what I replied to @nhristov's email with:

It seems to work great (excluding that it doesn't minify global.css automatically, but that can be fixed by importing it in the JS rather than the HTML IIRC).

Just to note now, I'm not really in the same environment as I was when I made that issue - I used to be on windows (10 home), I've moved to a Linux system full-time now. I went back and tested the repo I made for the bug and it does seem to have similar/the same behaviour as before, with the same configurations being broken.

JadedBlueEyes commented 4 years ago

After some testing, I figured out how the repo works, and it seems a bit weird to have a ganerated & minifed style comitted to git?

JadedBlueEyes commented 4 years ago

Dispite this solving my problem, I don't think this really solves the bug (or incompatibility). It's a workaround, in my opinion. The issue is what causes the incompatibility with postcss, and how do we fix it without requiring a non-obvious workaround. This could be a bug in rollup, but I've only seen it occur with sapper.

If this is going to be a WONTFIX bug, can we get it documented?

antony commented 4 years ago

@JoelEllis I'm struggling to determine from this reading issue, because it's not clear:

Regarding the third point - from what I can ascertain, your problem stems from using postCSS in Sapper. Sapper doesn't natively support PostCSS, so we wouldn't necessarily document a solution for PostCSS in the main Sapper docs.

If this is a problem with Rollup then we can raise the issue / fix the issue there.

Also I notice your reproduction is archived. Do you have a new, simplified reproduction so that we can see the issue for ourselves?

Thanks!

JadedBlueEyes commented 4 years ago

Hey! The bug I'm encountering is when rollup is configured with sapper with emitCSS: true, when put through postCSS the CSS is either converted to CSS with a javascript wrapper whilst still being loaded as a stylesheet, or being a file of export default undefined. With emitCSS set to false, I don't think it goes through PostCSS at all. This is demonstrated in the original repo, and I've made branches with a few of the configurations. I archived the repo as this issue hadn't seen activity in a long time.

The work around I'm using/have been given is https://github.com/nhristov/sapper-template-rollup - use PostCSS as a preprocessor for css inline in svelte, use PostCSS's rollup plugin to minify external CSS files (imported in server.js). This isn't ideal as CSS imported in client.js is not processed and the CSS from sapper is not processed as a whole, meaning minifers can't work at their full potential and there are newlines left in the files. However, it's good enough.

My ideal solution is to make situations 1 & 2 output valid CSS, or to document the workaround, @nhristov told me to document their workaround by making a question/answer on stackoverflow.

JadedBlueEyes commented 4 years ago

In situation 1, main.css is outputted as: image and the page renders as: image In situation 2, main.css is ouputted as: image

and it renders the same. 3 and 4, from what I can tell, don't get processed by postcss as the CSS is embedded in the javascript.

antony commented 4 years ago

I can't determine that there is an actual issue with Sapper from this ticket, so closing. Feel free to re-open if you can isolate/point at an exact issue with Sapper itself.

krzysztof-grzybek commented 4 years ago

@antony I think I know why this bug occurs.

  1. We collect css files for bundle on the transform rollup hook (here).
  2. rollup-plugin-postcss emit new files for bundle on the generateBundle rollup hook (here).

Therefore, postcss plugin emits files after we collect files for bundle. It seems also, that emitting file during generateBundle is a valid case. I'm new to svelte/rollup ecosystem, so correct me if I'm wrong, but I think that we should collect css files on writeBundle rollup hook.

Note, that this is probably this is only the part of the problem.

benmccann commented 4 years ago

Thanks for the excellent investigation @krzysztof-grzybek!

Evertt commented 4 years ago

Is there a workaround for now? Because I'd really like to be able to use this soon.

krzysztof-grzybek commented 4 years ago

I used @dephiros workaround.

Evertt commented 4 years ago

That doesn't work for me. I did find out how to fix the bug mostly. I'm gonna submit a very bad PR in a few minutes, hoping that other people are willing to improve it so that it can be merged.

benmccann commented 4 years ago

There's a template that @babichjacob has provided at https://github.com/babichjacob/sapper-postcss-template. As far as I know, he hasn't hit this issue (feel free to correct me @babichjacob). Would using his setup work for you all? I'd be curious to know if it has some issue or if it only happens when some other setting is present

dimfeld commented 4 years ago

It's been a while since I tried it, but IIRC the problem appears when using emitCss: true, in the rollup config.

babichjacob commented 4 years ago

We don't have this issue because we don't import CSS-like files in JS. We also don't use emitCss for the server, only the client.

svelte-preprocess takes care of it (and rollup-plugin-postcss isn't involved at all). The nearest equivalent of import ./styles.css is probably

<style lang="postcss"> <!-- possibly with global -->
  @import "./styles.css";
</style>

with postcss-import as a PostCSS plugin. (This doesn't work outside Svelte files, but I'm not sure why it would be needed for that not to be the case).

Evertt commented 4 years ago

Ah yes I see that it does work if I import the css in a <style> tag instead of in a <script> tag.

babichjacob commented 4 years ago

We also don't use emitCss.

Oh no, I said this off of memory and was wrong. We actually do have emitCss: true for the client, but not the server. (I felt this warranted its own reply to update everyone who needed to know).

benmccann commented 4 years ago

Ah, so this bug seems to me to really be specific to rollup-plugin-postcss and not PostCSS in general

lmf-git commented 4 years ago

@krzysztof-grzybek nice work!!

csaltos commented 4 years ago

Just in case here a reference using Sapper with PostCSS fixed -> https://dev.to/csaltos/sapper-with-material-ui-35id (it uses SMUI as a bonus)

lehno commented 4 years ago

Thanks @csaltos

benmccann commented 3 years ago

I would recommend using the postcss option with svelte-preprocess instead of using rollup-plugin-postcss. I'm going to close this since that seems to be a working path forward for most people. If anyone has a use case that solution doesn't address, please share it here and we can consider how best to solve your issue and whether rollup-plugin-postcss support is necessary

benbabics commented 3 years ago

I would recommend using the postcss option with svelte-preprocess instead of using rollup-plugin-postcss. I'm going to close this since that seems to be a working path forward for most people. If anyone has a use case that solution doesn't address, please share it here and we can consider how best to solve your issue and whether rollup-plugin-postcss support is necessary

What exactly does that look like for those of us struggling with this that aren't familiar with bundler configurations.

preprocess: sveltePreprocess({
  sourceMap: !production,
  postcss: {
    plugins: [ 
      require('autoprefixer')(),
      // do something here?
    ]
  }
}),

CC: @benmccann

benmccann commented 3 years ago

I would recommend switching to SvelteKit. Then you can simply run npx svelte-add@latest postcss: https://github.com/svelte-add/postcss