svelte icon indicating copy to clipboard operation
svelte copied to clipboard

Preprocess Svelte modules (or deprecate preprocessors?)

Open fcrozatier opened this issue 1 year ago • 6 comments

Describe the problem

Currently a Svelte preprocessor only runs on .svelte files, but with Svelte 5 the scope is not limited to these files anymore.

Example: to transform $state("foo") -> $state("bar") everywhere I need to transform both .svelte and .svelte.ts files but for now I can't do it with a Svelte preprocessor.

  1. Easy one might say, just write a Vite plugin. Sure, but the transform has more to do with Svelte, it doesn't really make sense as a Vite plugin, even though it will work. Also I can already do half the job with a Svelte preprocessor, only the .svelte part.

  2. If I make a lib depending on this transform, I'll run into troubles when packaging, since the svelte files are only preprocessed and copied, the Vite plugins do not run. So now I also have to manually postprocess the lib files

Describe the proposed solution

I think it makes sense to allow the preprocessing of .svelte.(js|ts) files.

Only the script function makes sense for these file, but since the markup and style functions are optionnal anyway, it shouldn't be too bad?

Importance

would make my life easier

fcrozatier avatar Aug 06 '24 12:08 fcrozatier

I'd really rather we didn't do this. Preprocessors are a source of woe — they're a necessary evil for supporting non-standard languages (though Svelte 5 supports TypeScript natively, and there's really no reason to use things like Sass in the year 2024), and they're a modest convenience for markup transformations (e.g. understanding things like <enhanced:img> without having to build parsing infrastructure), but beyond that they're just a bloody nuisance. They make code less portable, create fragmentation in the ecosystem, fuck up sourcemaps unless you're extremely careful, and if I had my druthers we'd get rid of them in Svelte 6.

A better solution would be to do it all in a Vite plugin, and for Svelte to provide utilities for parsing .svelte files so that your $state("foo") -> $state("bar") transformation can run on both .svelte and .svelte.* files before it reaches the svelte plugin. Such a transformation doesn't seem like it belongs in a Svelte preprocess step.

Rich-Harris avatar Aug 06 '24 13:08 Rich-Harris

cc @dominikg because i remember you actually had the idea of moving every svelte preprocessor to be a vite plugin.

paoloricciuti avatar Aug 06 '24 13:08 paoloricciuti

OT:

that was actually Ben and the other way around. Inside v-p-s generate a separate vite plugin for each preprocessor so that you can see the transformations in vite-plugin-inspect.

But it kind of proves a point that with the change of precedence we did (respect ordering or the array instead of markup-script-style) you can do most of it without involving svelte.preprocess, as long as there is a bundler with transforms where you can do it.

Now this might be where there is a bit of use left.

  1. the svelte.preprocess api gives the community a uniform api to build things like mdsvex without having to care for n bundlers
  2. it can be helpful if you run without any bundler at all

BTT:

i agree that the current script preprocessors should not be extended to cover .svelte.js files too, that would be a big breaking change for existing preprocessors that currently only expect script blocks from components. We would need a way to tell them (or they would have to rely on the file extension).

.svelte.js files allow you to export composed utilities as functions or classes, so instead of transforming existing calls to achieve something different, for most usecases you can just export from a .svelte.js library and skip all the extra processing.

dominikg avatar Aug 06 '24 14:08 dominikg

Just some thought as a svelte.preprocess API daily consumer that has a couple of custom preprocessors in active production use:

I agree with Rich and Dominik in that I mostly do transformation on markup (while trying not to introduce any non standard semantics) and actively avoid the script part, and not touch CSS at all, as those tend to quickly lead to uncharted territory. Extending this to .svelte.js/ts to me kind of invites people, including myself, to spend time hacking our way through a problem that might be better off resolved via another completely different direction (but perhaps @fcrozatier can provide a practical example otherwise). One exception to this is for some preprocessors, I do check/add ImportDeclaration to script tag.

Also a very quick comment about Vite. As far as I understand it, except for the 2 use cases Dominik mentioned where it's helpful to run svelte compiler without any bundler, there is not really a benefit to use svelte.preprocess over just writing a Vite plugin, yeah? With APIs from svelte/compiler.parse, zimmerframe.walk, and magic-string, a Vite plugin can do pretty much everything a Svelte preprocessor can today. My personal experience working with Vite plugin is honestly much nicer than with bare-bone Svelte preprocessor, especially when it comes to sourcemap and stuff that benefits from hot reloading.

vnphanquang avatar Aug 06 '24 16:08 vnphanquang

So the consensus is that these transforms should rather be Vite plugins.

Going a step further, is there anything useful we can do with a Svelte preprocessor that we can't do with a Vite plugin? Otherwise they could indeed be deprecated to leave one way of doing things.

The preprocessors still have some niceties like the markup, script, style separation, but a simple helper could do the trick. One remaining thing is that files are preprocessed when packaging a lib, but we have to apply Vite plugins manually.

fcrozatier avatar Aug 07 '24 13:08 fcrozatier

vite has library-mode too but thats not a focus. svelte-package is indeed one of the cases we'd have to look into, good call.

dominikg avatar Aug 07 '24 16:08 dominikg