svelte-preprocess can be used in two ways: auto-preprocessing and with stand-alone processors.
The examples below are going to be using a hypothetical rollup.config.js, but svelte-preprocess can be used in multiple scenarios, see "Usage".
In auto preprocessing mode, svelte-preprocess automatically uses the respective preprocessor for your code based on a tag's src, lang or type attribute. It also handles the <template> tag for markup, external files and global styling.
import svelte from 'rollup-plugin-svelte'
import { sveltePreprocess } from 'svelte-preprocess'
export default {
plugins: [
svelte({
preprocess: sveltePreprocess({ ... })
})
]
}As svelte-preprocess is just a Svelte preprocessor like any other, it's also possible to use it alongside other preprocessors:
import svelte from 'rollup-plugin-svelte'
import { sveltePreprocess } from 'svelte-preprocess'
export default {
plugins: [
svelte({
preprocess: [
sveltePreprocess({ ... }),
mdsvex({ ... })
]
})
]
}The following options can be passed to the preprocessor. None are required:
| Option | Default | Description |
|---|---|---|
markupTagName |
"template" |
string that sets the name of the tag svelte-preprocess looks for markup in custom languages.i.e markup makes it possible to write your markup between <markup lang="..."></markup> tag. |
aliases |
null |
A list of tuples [alias: string, language: string] that correlates an alias to a languagei.e ['cst', 'customLanguage'] means<... src="./file.cst"><... lang="cst">are treated as customLanguage. |
sourceMap |
false |
If true, svelte-preprocess generates sourcemap for every language that supports it. |
Alongside the options above, you can also configure options of specific preprocessors:
import svelte from 'rollup-plugin-svelte';
import { sveltePreprocess } from 'svelte-preprocess';
export default {
plugins: [
svelte({
preprocess: sveltePreprocess({
globalStyle: { ... },
replace: { ... },
typescript: { ... },
scss: { ... },
sass: { ... },
less: { ... },
stylus: { ... },
babel: { ... },
postcss: { ... },
coffeescript: { ... },
pug: { ... },
}),
}),
],
};See the section below for options for each preprocessor.
It's also possible to create custom preprocessors, taking advantage of the automatic language detection of svelte-preprocess:
import svelte from 'rollup-plugin-svelte';
import { sveltePreprocess } from 'svelte-preprocess';
export default {
plugins: [
svelte({
preprocess: sveltePreprocess({
aliases: [
['potato', 'potatoLanguage'],
['pot', 'potatoLanguage'],
],
/** Add a custom language preprocessor */
potatoLanguage({ content, filename, attributes }) {
const { code, map } = require('potato-language').render(content);
return { code, map };
},
}),
}),
],
};Now svelte-preprocess will use the potatoLanguage preprocessor whenever it finds a tag with lang="potato" or src="./index.pot".
These methods receive the same arguments and act exactly like a common svelte preprocessor, but the concept of markup/style/script is abstracted as they are executed whenever svelte-preprocess find the aforementioned attributes.
We've seen that we can easily create custom preprocessors within svelte-preprocess, but wait, there's more! Using the same mechanism, it's possible to override the default preprocessor for a language!
Let's use TypeScript as an example. The tsc compiler is fast enough at the beginning, but as a project grows, it can really become cumbersome. esbuild is a JavaScript bundler written in Go and can transpile TypeScript much faster than our good and old tsc.
To integrate esbuild with svelte-preprocess we can override the default TypeScript preprocessor as follows:
import svelte from 'rollup-plugin-svelte';
import { sveltePreprocess } from 'svelte-preprocess';
import { transformSync } from 'esbuild';
export default {
plugins: [
svelte({
preprocess: sveltePreprocess({
typescript({ content }) {
const { code, map } = transformSync(content, {
loader: 'ts',
});
return { code, map };
},
}),
}),
],
};In case you want to manually configure your preprocessing step while taking advantage of svelte-preprocess features, such as language detection and external file support, the following preprocessors are available: Pug, CoffeeScript, TypeScript, Less, SCSS, Sass, Stylus, PostCSS, Babel, globalStyle, and replace.
Every processor accepts an options object which is passed to its respective underlying tool. See the section below for options for each preprocessor.
import { scss, postcss } from 'svelte-preprocess';
svelte.preprocess(input, [
scss(),
postcss({
plugins: [
require('autoprefixer')({
browsers: 'last 2 versions',
}),
],
}),
]);Stand-alone markup preprocessors such as Pug are executed over the whole markup and not only inside a custom tag.
The preprocessors are language-aware, which means you can enqueue multiple ones and you won't have SCSS and Stylus conflicting over the same content.
The auto preprocessing mode is the recommended way of using svelte-preprocess as it's the least verbose and most straightforward way of supporting multiple language preprocessors.
svelte-preprocess was built in a way that the underlying transpilers and compilers are only required/imported if a portion of your component matches its language. With that said, the auto-preprocessing mode is roughly equivalent to using all the stand-alone preprocessors in the following order:
import svelte from 'rollup-plugin-svelte';
import {
pug,
coffeescript,
typescript,
less,
scss,
sass,
stylus,
postcss,
globalStyle,
babel,
replace,
} from 'svelte-preprocess';
export default {
plugins: [
svelte({
preprocess: [
replace({ ... }),
pug({ ... }),
coffeescript({ ... }),
typescript({ ... }),
less({ ... }),
scss({ ... }),
sass({ ... }),
stylus({ ... }),
babel({ ... }),
postcss({ ... }),
globalStyle({ ... }),
],
}),
],
};Besides the options of each preprocessor, svelte-preprocess also supports these custom options:
| Option | Default | Description |
|---|---|---|
prependData |
'' |
string will be prepended to every component part that runs through the preprocessor. |
The Babel preprocessor accepts an options object which is passed onto the babel runtime. You can check the Babel API reference for specific options.
Svelte expects your JavaScript to be in at least ES6 format, so make sure to set your Babel configuration accordingly.
If you are using TypeScript through @babel/plugin-transform-typescript, set onlyRemoveTypeImports to true so that all value imports are preserved.
Note: If you want to transpile your app to be supported in older browsers, you must run babel from the context of your bundler.
The CoffeeScript processor accepts no extra options and only transpiles CoffeeScript code down to esm compliant JavaScript code.
You can check the Less API reference for Less specific options.
Note: svelte-preprocess automatically configures inclusion paths for your root directory, node_modules and for the current file's directory.
The PostCSS preprocessor accepts four options:
| Option | Default | Description |
|---|---|---|
plugins |
undefined |
a list of postcss plugins. |
parser |
undefined |
the name of the module to be used as the parser. |
syntax |
undefined |
the syntax to be used. |
configFilePath |
undefined |
the path of the directory containing the PostCSS configuration. |
In auto-preprocessing mode, you can set postcss: true if postcss-load-config is installed and svelte-preprocess will look for a PostCSS config file in your project.
When a lang="sugarss" is found, sugarss is automatically loaded and extra indentation is removed.
You can check the PostCSS API reference for PostCSS specific options.
You can check the Pug API reference for information about its options. The only overridden property is doctype, which is set to HTML.
Apart from those, the Pug preprocessor accepts:
| Option | Default | Description |
|---|---|---|
markupTagName |
template |
the tag name used to look for the optional markup wrapper. If none is found, pug is executed over the whole file. |
configFilePath |
undefined |
the path of the directory containing the Pug configuration. |
Template blocks:
Some of Svelte's template syntax is invalid in Pug. svelte-preprocess provides some pug mixins to represent svelte's {#...}{/...} and {@...} blocks: +if(), +else(), +elseif(), +each(), +key(), +await(), +then(), +catch(), +html(), +const(), +debug(), +snippet(), +render().
ul
+if('posts && posts.length > 1')
+each('posts as post')
li
a(rel="prefetch" href="blog/{post.slug}") {post.title}
+else()
span No posts :cElement attributes:
Pug encodes everything inside an element attribute to html entities, so attr="{foo && bar}" becomes attr="foo && bar". To prevent this from happening, instead of using the = operator use != which won't encode your attribute value:
button(disabled!="{foo && bar}")This is also necessary to pass callbacks:
button(on:click!="{(e) => doTheThing(e)}")It is not possible to use template literals for attribute values. You can't write attr=`Hello ${value ? 'Foo' : 'Bar'}`, instead write attr="Hello {value ? 'Foo' : 'Bar'}".
Spreading props:
To spread props into a pug element, wrap the {...object} expression with quotes ".
This:
button.big(type="button" disabled "{...slide.props}") SendBecomes:
<button class="big" type="button" disabled {...slide.props}> Send </button>Svelte Element directives:
Syntax to use Svelte Element directives with Pug
input(bind:value="{foo}")
input(on:input="{bar}")The scss/sass preprocessor accepts the options listed in the Sass LegacyStringOptions API reference with some exceptions: the file and data properties are not supported. Instead, use the prependData property if you want to prepend some content to your scss content.
Note: svelte-preprocess (version 5.0.0 and later) always uses Sass's legacy renderSync API.
Note: svelte-preprocess automatically configures inclusion paths for your root directory, node_modules and for the current file's directory.
Note: when a lang="sass" is found, indentedSyntax is automatically set to true.
Note: sass, with indented syntax, and scss are not interchangeable so make sure to configure the correct one that fits your needs.
You can check the Stylus API reference for specific Stylus options. The filename property is overridden.
Note: svelte-preprocess automatically configures inclusion paths for your root directory, node_modules and for the current file's directory.
Since version 5, Svelte supports TypeScript natively with a few exceptions: You can only use type-only syntax, i.e. syntax that is just removed from the resulting JS output, and doesn't require code. Non-type-only features are decorators for example. If you need those features, you need to still use a TypeScript preprocessor like this one, else you can omit it.
| Option | Default | Description |
|---|---|---|
tsconfigDirectory |
undefined |
optional string that specifies from where to load the tsconfig from.i.e './configs' |
tsconfigFile |
undefined |
optional string pointing torwards a tsconfig file.i.e './tsconfig.app.json' |
compilerOptions |
undefined |
optional compiler options configuration. These will be merged with options from the tsconfig file if found. |
You can check the compilerOptions reference for specific TypeScript options.
-
Since
v4,svelte-preprocessdoesn't type-check your component, its only concern is to transpile it into valid JavaScript for the compiler. If you want to have your components type-checked, you can use svelte-check. -
Using TypeScript features that are not type-only (i.e. are transpiled to different JS code) inside a component's markup is currently not supported. See #525 for development updates to this.
The globalStyle preprocessor extends the functionalities of Svelte's :global pseudo-selector.
First, install postcss by running npm install --save-dev postcss. Then use the rules below.
global attribute:
Add a global attribute to your style tag and instead of scoping the CSS, all of its content will be interpreted as global style.
<style global>
div {
color: red;
}
</style>:global rule:
Use a :global rule to only expose parts of the stylesheet:
<style lang="scss">
.scoped-style {
}
:global {
@import 'global-stylesheet.scss';
.global-style {
.global-child-style {
}
}
}
</style>Works best with nesting-enabled CSS preprocessors, but regular CSS selectors like div :global .global1 .global2 are also supported.
Usage notes
- If you're using it as a standalone processor, it works best if added to the end of the processors array._
- Wrapping
@keyframesinside:global {}blocks is not supported. Use the-global-name prefix for global keyframes._ - If you need to have some styles be scoped inside a global style tag, use
:localin the same way you'd use:global._
The replace preprocessor replaces a set of string patterns in your components markup defined by an array of [RegExp, ReplaceFn | string] tuples, the same arguments received by the String.prototype.replace method.
For example, to add a process.env.{prop} value resolution and a custom @if/@endif if-block shorthand, one could do:
import svelte from 'rollup-plugin-svelte'
import { replace } from 'svelte-preprocess'
export default {
plugins: [
svelte({
preprocess: [replace([
[
/process\.env\.(\w+)/g,
(_:, prop) => JSON.stringify(process.env[prop]),
],
// Example of supporting a blade-like syntax:
[/@if\s*\((.*?)\)$/gim, '{#if $1}'],
[/@elseif\s*\((.*?)\)$/gim, '{:else if $1}'],
[/@else$/gim, '{:else}'],
[/@endif$/gim, '{/if}'],
[/@each\s*\((.*?)\)$/gim, '{#each $1}'],
[/@endeach$/gim, '{/each}'],
[/@await\s*\((.*?)\)$/gim, '{#await $1}'],
[/@then\s*(?:\((.*?)\))?$/gim, '{:then $1}'],
[/@catch\s*(?:\((.*?)\))?$/gim, '{:catch $1}'],
[/@endawait$/gim, '{/await}'],
[/@debug\s*\((.*?)\)$/gim, '{@debug $1}'],
[/@html\s*\((.*?)\)$/gim, '{@html $1}'],
])]
})
]
}Allowing to write your component like:
@if(process.env.NODE_ENV !== 'development')
<h1>Production environment!</h1>
@endif
And the result, with a NODE_ENV = 'production' would be:
{#if 'production' !== 'development'}
<h1>Production environment!</h1>
{/if}Note: a string can be used instead of a
RegExp, but only a single occurence of it will change, as per the default behavior ofString.prototype.replace.