Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preprocessor support #8

Closed
Conduitry opened this issue Jul 11, 2019 · 13 comments
Closed

Preprocessor support #8

Conduitry opened this issue Jul 11, 2019 · 13 comments
Labels
enhancement New feature or request

Comments

@Conduitry
Copy link
Member

If someone wants to publish a component that they've written that needs preprocessors, what they should be publishing is main/module pointing at a completely compiled version (like now), but svelte should point to the preprocesed component(s), not their original source. I'm not sure what the best way to do this is.

@Conduitry
Copy link
Member Author

Copying a piece of a conversation from chat from last month, so it has a more permanent home:

@Conduitry: Oh, I just had an idea: A one-off rollup plugin, embedded in rollup.config.js. That would be an easy way to find out about all of the components. It could also write out the preprocessed versions, and then pass along the component unchanged for the other plugins
@Conduitry: I haven't worked out how the entry point index.js should be handled yet
@pngwn: couldn't you just literally dupe it into the svelte dist path?
@pngwn: it should basically be identical as far as i can tell
@pngwn: But that sounds like a nice solution and we don't need random scripts sitting around, or need to parse the js entryfile to an ast to pull out the required information, rollup can do the heavy lifting.

@YogliB
Copy link

YogliB commented Oct 19, 2019

What's the process that's happening when we use the process feature?

Does Svelte transpiles the component into a preprocessors-free component before compiling it or compiles it directly?

@pngwn
Copy link
Member

pngwn commented Oct 19, 2019

Yeah. svelte.preprocess takes an invalid svelte component allows you to perform arbitrary transforms and returns an object containing a string that should be valid svelte component that can be fed directly to the compiler.

@Conduitry
Copy link
Member Author

The bundler plugins call svelte.preprocess() on the files and then pass the output to svelte.compile().

@YogliB
Copy link

YogliB commented Oct 19, 2019

So couldn't we just add an output option to the preprocess function that makes Svelte output the file before compiling it?

@pngwn
Copy link
Member

pngwn commented Oct 19, 2019

svelte.preprocess already outputs a svelte component, it is completely separate to the compiler, it is just the bundler plugins that integrate the two into a single step. I don't think short-circuiting the bundling process in the bundler plugins based on an option is a good idea, it could accidentally be switched on leading to very unexpected behaviour. This should be easy to handle in its own plugin.

@Conduitry
Copy link
Member Author

To make this simpler, I think it might be a good idea to make the pkg.svelte entry point of the package always be a .js file that re-exports the component or components. I guess this would mean something like export { default as default } from './Component.svelte';. People could edit that freely if they added more components. The one-off rollup plugin could copy over each file it encounters from src to dist - preprocessing .svelte files and leaving others untouched. I also think it makes sense to have this copying into dist always happen, even if there is no preprocessing. We don't want the build process to have to worry about (or have the directory layout change depending on) whether there are multiple components or whether there are preprocessors.

@BlackFenix2
Copy link

ay yo, i found a way we could use svelte.preprocess to spit out vanilla .svelte files for consumers that do not use a specific preprocessor. its not much right now but could be a stepping stone?

forgive the code formatting, i am using prettier 2.1.0 and it isn't playing well with svelte right now.

sample compile script

import { preprocess } from 'svelte/compiler';
import autoprocessor from 'svelte-preprocess';
import * as fs from 'fs';

const doStuff = async () => {
  const source = fs.readFileSync(
    `${__dirname}/src/Button/Button.svelte`,
    'utf-8'
  );

  await preprocess(source, autoprocessor(), { filename: 'Button.svelte' })
    .then((item) => {
      console.log('Svelte Code: ', item.code);
      fs.mkdirSync(`${__dirname}/dist/Button/`, {
        recursive: true,
      });
      fs.writeFileSync(`${__dirname}/dist/Button/Button.svelte`, item.code);
    })
    .catch((error) => {
      console.error(error.message);
    });
};

doStuff();

src svelte

<script lang="ts">
  export let text = '';

  export let rounded: boolean = false;
  export let circle: boolean = false;

  let buttonElement: HTMLElement;
  let spanElement: HTMLElement;

  let mouseX: number;
  let mouseY: number;

  function clickEvent(e: MouseEvent) {
    var { left, top } = buttonElement.getBoundingClientRect();
    mouseX = e.clientX - left;
    mouseY = e.clientY - top;
    spanElement.style.left = `${mouseX}px`;
    spanElement.style.top = `${mouseY}px`;
  }
</script>

<style lang="scss">
  button {
    position: relative;
    overflow: hidden;
    padding: 8px 16px;
    border: solid thin black;
    background-color: inherit;
    color: black;
    cursor: pointer;
    font-size: inherit;
    outline: none;
    transition: all 0.3s;

    &:hover {
      background-color: lightgrey;
    }

    & > span {
      position: absolute;
      display: none;
      width: 100px;
      height: 100px;
      margin-top: -50px;
      margin-left: -50px;
      animation: ripple 1s;
      background-color: rgba(0, 0, 0, 0.3);
      border-radius: 50%;
      content: '';
      opacity: 0;
      transition: background-color 0.3s;
    }

    &:focus:not(:active) span {
      display: block;
    }
  }

  @keyframes ripple {
    from {
      opacity: 1;
      transform: scale(0);
    }

    to {
      opacity: 0;
      transform: scale(10);
    }
  }

  .rounded {
    border-radius: 5px;
  }

  .circle {
    padding: 8px;
    border-radius: 50%;
  }
</style>

<template>
  <button
    class:rounded
    class:circle
    on:click={clickEvent}
    bind:this={buttonElement}>
    <slot />
    {text}
    <span class="active" bind:this={spanElement} />
  </button>
</template>

dist svelte

<script>
    export let text = '';
    export let rounded = false;
    export let circle = false;
    let buttonElement;
    let spanElement;
    let mouseX;
    let mouseY;
    function clickEvent(e) {
        var { left, top } = buttonElement.getBoundingClientRect();
        mouseX = e.clientX - left;
        mouseY = e.clientY - top;
        spanElement.style.left = `${mouseX}px`;
        spanElement.style.top = `${mouseY}px`;
    }
</script>

<style>
button {
  position: relative;
  overflow: hidden;
  padding: 8px 16px;
  border: solid thin black;
  background-color: inherit;
  color: black;
  cursor: pointer;
  font-size: inherit;
  outline: none;
  transition: all 0.3s; }
  button:hover {
    background-color: lightgrey; }
  button > span {
    position: absolute;
    display: none;
    width: 100px;
    height: 100px;
    margin-top: -50px;
    margin-left: -50px;
    animation: ripple 1s;
    background-color: rgba(0, 0, 0, 0.3);
    border-radius: 50%;
    content: '';
    opacity: 0;
    transition: background-color 0.3s; }
  button:focus:not(:active) span {
    display: block; }

@keyframes ripple {
  from {
    opacity: 1;
    transform: scale(0); }
  to {
    opacity: 0;
    transform: scale(10); } }

.rounded {
  border-radius: 5px; }

.circle {
  padding: 8px;
  border-radius: 50%; }
</style>


  <button
    class:rounded
    class:circle
    on:click={clickEvent}
    bind:this={buttonElement}>
    <slot />
    {text}
    <span class="active" bind:this={spanElement} />
  </button>

@TheComputerM
Copy link

TheComputerM commented Oct 19, 2020

I am using @use statements with scss and it cannot resolve file paths:

<style lang="scss" global>
@use "./Alert.scss";
</style>
Can't find stylesheet to import.
  ╷
2 │   @use "./Alert.scss";
  │   ^^^^^^^^^^^^^^^^^^^
  ╵

I solved this problem using process.chdir

@josdejong
Copy link

Any news on this?

I have a Svelte component where I use SASS, and I would like to prevent consumers from having to configure SASS themselves. So ideally, I would like to publish my component in such a way that SASS is already preprocessed.

I tried the proof of concept posted by @BlackFenix2 in #8 (comment) which looks like it should do the trick, but can't get that working for SASS unfortunately.

@Conduitry
Copy link
Member Author

The planned way forward with this is sveltejs/kit#518 which will replace this whole template repo and will also handle preprocessors.

@josdejong
Copy link

Thanks @Conduitry for your fast response, I actually commented there some time ago 😁. Makes sense to focus effort on SvelteKit, I'm really looking forward to that. I started using Svelte not that long ago, and right now I feel like I'm in no man's land - just trying to get something working for the time being.

@antony
Copy link
Member

antony commented Nov 11, 2021

Closing in favour of focusing on svelte-kit package

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

7 participants