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 language i.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 :c
Element 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}") Send
Becomes:
<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-preprocess
doesn'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
@keyframes
inside: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
:local
in 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
.