svelte.preprocess

Created on 28 Sep 2017  Â·  10Comments  Â·  Source: sveltejs/svelte

One of the dangers of adding preprocessor support to svelte.compile is the possibility of fragmentation — if I install a component from npm and it uses SASS and CoffeeScript, I can't use the uncompiled version in my app without mirroring the component author's preprocessing step.

An idea for satisfying both needs simultaneously — a svelte.preprocess function that generates a 'standard' (i.e. plain CSS/JS) component file:

import postcss from 'svelte-postcss';
import vars from 'postcss-simple-vars';

const component = await svelte.preprocess(`
<h1>Hello {{name}}!</h1>

<style lang='postcss'>
  h1 {
    color: $somevar;
  }
</style>
`, {
  preprocessors: {
    postcss: postcss({
      plugins: [
        vars({
          somevar: 'red'
        })
      ]
    })
  }
});

assert.equal(component.toString(), `
<h1>Hello {{name}}!</h1>

<style>
  h1 {
    color: red;
  }
</style>
`);

That would work in its current form. Sourcemaps would be broken though. We could go a step further and allow separated inputs to svelte.compile, like so:

compiled = svelte.compile({
  html: {
    code: `<h1>Hello {{name}}!</h1>`,
    map: {...}
  },
  css: {
    code: `h1 { color: red; }`,
    map: {...}
  }
}, opts);

If svelte.preprocess generated output like that, and svelte.compile knew how to stitch sourcemaps together, then a) we'd retain accurate sourcemaps and b) we could even allow separated input files, which is something people have asked for.

That could happen in a second step though — as long as the output from svelte.preprocess has a toString method, it'd work with svelte.compile today.

I think I probably prefer this to changing the behaviour of svelte.compile. Need to consider the impact it would have on build tool plugins. Also, something we should bear in mind is if we want to think about sharing CSS between components via @import (with encapsulation, without duplication) to ensure we don't make any design decisions that make that difficult.

Most helpful comment

I have started working on a very basic implementation for css preprocessing, but I wish I had read this issue first, as no thought was given for properly handling the sourceMaps.

It is basically a simple decorator for the compile function, that synchronously calls a user provided preprocessor function. The plus side of that is that the framework will not have dependencies to css preprocessing libraries.

I would really appreciate any feedback on this, as I would really like to spend more time on making it a proper feature.

All 10 comments

So in this proposal what would the default export from svelte-postcss look like? Would it get a reference to each <style> block in the component? Would it have access to rewrite the HTML?

My use-case is integrating modular-css with single-file svelte components, so that's gonna slant all my questions to that particular bent. I could of course write my own tool that can pre-process svelte components & rewrite the CSS/HTML but I'm curious how official support for that sort of a workflow might work.

I'd imagined the default export would look something like this:

export default postcss(css) {
  return {
    code: '...',
    map: {...}
  };
}

Would it get a reference to each