Skip to main content

编译器和 API

svelte/compiler

通常,你不会直接与 Svelte 编译器交互,而是使用打包器插件将其集成到你的构建系统中。 Svelte 团队最推荐和投资的打包器插件是 vite-plugin-svelteSvelteKit 框架提供了利用 vite-plugin-svelte用于打包 Svelte 组件库的工具 构建应用的设置。 Svelte Society 维护着一个 其他打包器插件 列表,用于附加工具,例如 Rollup 和 Webpack。

Typically, you won't interact with the Svelte compiler directly, but will instead integrate it into your build system using a bundler plugin. The bundler plugin that the Svelte team most recommends and invests in is vite-plugin-svelte. The SvelteKit framework provides a setup leveraging vite-plugin-svelte to build applications as well as a tool for packaging Svelte component libraries. Svelte Society maintains a list of other bundler plugins for additional tools like Rollup and Webpack.

尽管如此,了解如何使用编译器还是很有用的,因为打包器插件通常会向你公开编译器选项。

Nonetheless, it's useful to understand how to use the compiler, since bundler plugins generally expose compiler options to you.

compile

导出片段: svelte/compiler#compile

这就是奇迹发生的地方。 svelte.compile 获取你的组件源代码,并将其转换为导出类的 JavaScript 模块。

This is where the magic happens. svelte.compile takes your component source code, and turns it into a JavaScript module that exports a class.

ts
import { compile } from 'svelte/compiler';
const result = compile(source, {
// options
});

有关所有可用选项,请参阅 CompileOptions

Refer to CompileOptions for all the available options.

返回的 result 对象包含组件的代码以及有用的元数据。

The returned result object contains the code for your component, along with useful bits of metadata.

ts
const { js, css, ast, warnings, vars, stats } = compile(source);

有关编译结果的完整说明,请参阅 CompileResult

Refer to CompileResult for a full description of the compile result.

parse

导出片段: svelte/compiler#parse

parse 函数解析组件,仅返回其抽象语法树。 与使用 generate: false 选项进行编译不同,除了解析组件之外,这不会对组件执行任何验证或其他分析。 请注意,返回的 AST 不被视为公共 API,因此任何时间点都可能发生重大更改。

The parse function parses a component, returning only its abstract syntax tree. Unlike compiling with the generate: false option, this will not perform any validation or other analysis of the component beyond parsing it. Note that the returned AST is not considered public API, so breaking changes could occur at any point in time.

ts
import { parse } from 'svelte/compiler';
const ast = parse(source, { filename: 'App.svelte' });

preprocess

导出片段: svelte/compiler#preprocess

许多 官方和社区维护的预处理插件 可让你将 Svelte 与 TypeScript、PostCSS、SCSS 和 Less 等工具一起使用。

A number of official and community-maintained preprocessing plugins are available to allow you to use Svelte with tools like TypeScript, PostCSS, SCSS, and Less.

你可以使用 svelte.preprocess API 编写自己的预处理器。

You can write your own preprocessor using the svelte.preprocess API.

preprocess 函数为任意转换组件源代码提供了方便的钩子。 例如,它可用于将 <style lang="sass"> 块转换为普通 CSS。

The preprocess function provides convenient hooks for arbitrarily transforming component source code. For example, it can be used to convert a <style lang="sass"> block into vanilla CSS.

第一个参数是组件源代码。 第二个是预处理器数组(或者单个预处理器,如果只有一个),其中预处理器是一个对象,其中包含必需的 name 以及 markupscriptstyle 函数,其中每个函数都是可选的。

The first argument is the component source code. The second is an array of preprocessors (or a single preprocessor, if you only have one), where a preprocessor is an object with a name which is required, and markup, script and style functions, each of which is optional.

markup 函数接收整个组件源文本,以及组件的 filename(如果在第三个参数中指定)。

The markup function receives the entire component source text, along with the component's filename if it was specified in the third argument.

scriptstyle 函数分别接收 <script><style> 元素的内容 (content) 以及整个组件源文本 (markup)。 除了 filename 之外,它们还获取元素属性的对象。

The script and style functions receive the contents of <script> and <style> elements respectively (content) as well as the entire component source text (markup). In addition to filename, they get an object of the element's attributes.

每个 markupscriptstyle 函数必须返回一个带有 code 属性的对象(或解析为对象的 Promise),表示转换后的源代码。 他们可以选择返回一个 dependencies 数组(表示要监视更改的文件)和一个 map 对象(将转换映射回原始代码的源映射)。 scriptstyle 预处理器可以选择返回表示脚本/样式标记上更新的属性的属性记录。

Each markup, script or style function must return an object (or a Promise that resolves to an object) with a code property, representing the transformed source code. Optionally they can return an array of dependencies which represents files to watch for changes, and a map object which is a sourcemap mapping back the transformation to the original code. script and style preprocessors can optionally return a record of attributes which represent the updated attributes on the script/style tag.

预处理器函数应尽可能返回 map 对象,否则调试会变得更加困难,因为堆栈跟踪无法正确链接到原始代码。

ts
import { preprocess } from 'svelte/compiler';
import MagicString from 'magic-string';
const { code } = await preprocess(
source,
{
markup: ({ content, filename }) => {
const pos = content.indexOf('foo');
if (pos < 0) {
return { code: content };
}
const s = new MagicString(content, { filename });
s.overwrite(pos, pos + 3, 'bar', { storeName: true });
return {
code: s.toString(),
map: s.generateMap()
};
}
},
{
filename: 'App.svelte'
}
);

如果返回 dependencies 数组,它将包含在结果对象中。 vite-plugin-svelterollup-plugin-svelte 之类的包使用它来监视其他文件的更改,例如,如果你的 <style> 标签具有 @import,则可以使用此功能。

If a dependencies array is returned, it will be included in the result object. This is used by packages like vite-plugin-svelte and rollup-plugin-svelte to watch additional files for changes, in the case where your <style> tag has an @import (for example).

preprocess-sass.js
ts
import { preprocess } from 'svelte/compiler';
import MagicString from 'magic-string';
import sass from 'sass';
import { dirname } from 'path';
const { code } = await preprocess(
source,
{
name: 'my-fancy-preprocessor',
markup: ({ content, filename }) => {
// Return code as is when no foo string present
const pos = content.indexOf('foo');
if (pos < 0) {
return;
}
// Replace foo with bar using MagicString which provides
// a source map along with the changed code
const s = new MagicString(content, { filename });
s.overwrite(pos, pos + 3, 'bar', { storeName: true });
Property 'css' does not exist on type 'unknown'.
Property 'stats' does not exist on type 'unknown'.
2339
2339
Property 'css' does not exist on type 'unknown'.
Property 'stats' does not exist on type 'unknown'.
return {
code: s.toString(),
map: s.generateMap({ hires: true, file: filename })
};
Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is not assignable to type 'string'.2345Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is not assignable to type 'string'.
},
style: async ({ content, attributes, filename }) => {
// only process <style lang="sass">
if (attributes.lang !== 'sass') return;
const { css, stats } = await new Promise((resolve, reject) =>
sass.render(
{
file: filename,
data: content,
includePaths: [dirname(filename)]
},
(err, result) => {
if (err) reject(err);
else resolve(result);
}
)
);
// remove lang attribute from style tag
delete attributes.lang;
return {
code: css.toString(),
dependencies: stats.includedFiles,
attributes
};
}
},
{
filename: 'App.svelte'
}
);

多个预处理器可以一起使用。 第一个的输出成为第二个的输入。 在一个预处理器中,markup 首先运行,然后是 scriptstyle

Multiple preprocessors can be used together. The output of the first becomes the input to the second. Within one preprocessor, markup runs first, then script and style.

在 Svelte 3 中,所有 markup 函数首先运行,然后是所有 script,最后是所有 style 预处理器。 这个顺序在 Svelte 4 中发生了变化。

multiple-preprocessor.js
ts
import { preprocess } from 'svelte/compiler';
const { code } = await preprocess(source, [
{
name: 'first preprocessor',
markup: () => {
console.log('this runs first');
},
script: () => {
console.log('this runs second');
},
style: () => {
console.log('this runs third');
}
},
{
name: 'second preprocessor',
markup: () => {
console.log('this runs fourth');
},
script: () => {
console.log('this runs fifth');
},
style: () => {
console.log('this runs sixth');
}
}
], {
filename: 'App.svelte'
});
multiple-preprocessor.ts
ts
import { preprocess } from 'svelte/compiler';
const { code } = await preprocess(
source,
[
{
name: 'first preprocessor',
markup: () => {
console.log('this runs first');
},
script: () => {
console.log('this runs second');
},
style: () => {
console.log('this runs third');
},
},
{
name: 'second preprocessor',
markup: () => {
console.log('this runs fourth');
},
script: () => {
console.log('this runs fifth');
},
style: () => {
console.log('this runs sixth');
},
},
],
{
filename: 'App.svelte',
},
);

walk

导出片段: svelte/compiler#walk

walk 函数提供了一种使用编译器自己的内置 estree-walker 实例来遍历解析器生成的抽象语法树的方法。

The walk function provides a way to walk the abstract syntax trees generated by the parser, using the compiler's own built-in instance of estree-walker.

walker 需要一个抽象语法树来行走,以及一个具有两个可选方法的对象: enterleave。 对于每个节点,都会调用 enter(如果存在)。 然后,除非在 enter 期间调用 this.skip(),否则将遍历每个子节点,然后在该节点上调用 leave

The walker takes an abstract syntax tree to walk and an object with two optional methods: enter and leave. For each node, enter is called (if present). Then, unless this.skip() is called during enter, each of the children are traversed, and then leave is called on the node.

compiler-walk.js
ts
import { walk } from 'svelte/compiler';
walk(ast, {
enter(node, parent, prop, index) {
do_something(node);
if (should_skip_children(node)) {
this.skip();
}
},
leave(node, parent, prop, index) {
do_something_else(node);
}
});
compiler-walk.ts
ts
import { walk } from 'svelte/compiler';
walk(ast, {
enter(node, parent, prop, index) {
do_something(node);
if (should_skip_children(node)) {
this.skip();
}
},
leave(node, parent, prop, index) {
do_something_else(node);
},
});

VERSION

导出片段: svelte/compiler#VERSION

当前版本,在 package.json 中设置。

The current version, as set in package.json.

ts
import { VERSION } from 'svelte/compiler';
console.log(`running svelte version ${VERSION}`);

类型(Types)

类型: svelte/compiler

上一页 svelte/action