Sapper: rollup-plugin-postcss not working

Created on 18 May 2019  Â·  32Comments  Â·  Source: sveltejs/sapper

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.

bundling

Most helpful comment

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,

All 32 comments

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.
  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:
    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

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.

@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.

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.

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?

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,

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

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.

@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

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.

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?

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?

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

  • What is the bug that you're having trouble with
  • What is the workaround you are using
  • What is the proposed solution (a documentation update, perhaps?)

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!

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.

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.

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.

@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.

Thanks for the excellent investigation @krzysztof-grzybek!

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

I used @dephiros workaround.

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.

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

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

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).

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

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).

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

@krzysztof-grzybek nice work!!

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)

Thanks @csaltos

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Snugug picture Snugug  Â·  4Comments

Rich-Harris picture Rich-Harris  Â·  3Comments

Rich-Harris picture Rich-Harris  Â·  3Comments

mylastore picture mylastore  Â·  3Comments

milosdjakovic picture milosdjakovic  Â·  3Comments