Skip to content

Latest commit

 

History

History
209 lines (147 loc) · 19.4 KB

40-page-options.md

File metadata and controls

209 lines (147 loc) · 19.4 KB

Параметры страницы


По умолчанию SvelteKit будет рендерить (или пререндерить) любой компонент сначала на сервере и отправлять его на клиент в формате HTML. Затем он снова отрендерит компонент в браузере, чтобы сделать его интерактивным в процессе, называемом гидратация. По этой причине необходимо убедиться, что компоненты могут работать в обоих местах. Затем SvelteKit инициализирует маршрутизатор, который берет на себя последующую навигацию.

Вы можете управлять каждой из них в отдельности, экспортируя опции из +page.js или +page.server.js, или для групп страниц, используя общий +layout.js или +layout.server.js. Чтобы определить параметр для всего приложения, экспортируйте его из корневого макета. Дочерние макеты и страницы переопределяют значения, установленные в родительских макетах, поэтому, например, вы можете включить пререндеринг для всего приложения и отключить его для страниц, которые должны быть динамически отображены.

Вы можете смешивать и сочетать эти опции в различных областях вашего приложения. Например, вы можете сделать пререндер маркетинговой страницы для максимальной скорости, серверный рендеринг динамических страниц для SEO и доступности и перевести раздел администрирования в SPA, сделав его рендеринг только на клиенте. Это делает SvelteKit очень универсальным.

пререндер

Вполне вероятно, что по крайней мере некоторые маршруты вашего приложения могут быть представлены в виде простого HTML-файла, создаваемого во время сборки. Эти маршруты могут быть пререндерены.

+page.js/+page.server.js/+server.js

export const prerender = true;

В качестве альтернативы, вы можете установить export const prerender = true в вашем корне +layout.js или +layout.server.js и пререндерить все, кроме страниц, которые явно помечены как не пререндерируемые:

+page.js/+page.server.js/+server.js

export const prerender = false;

Маршруты с prerender = true будут исключены из манифестов, используемых для динамического SSR, что сделает ваш сервер (или функции serverless/edge) меньше. В некоторых случаях вы можете захотеть пререндерить маршрут, но также включить его в манифест (например, маршрут типа /blog/[slug], где вы хотите пререндерить ваш самый свежий/популярный контент, но сервер рендерит длинный хвост) - для таких случаев есть третья опция, 'auto':

+page.js/+page.server.js/+server.js

export const prerender = 'auto';

Если все ваше приложение подходит для пререндеринга, вы можете использовать adapter-static, который выведет файлы, пригодные для использования с любым статическим веб-сервером.

Пререндер запускается в корне вашего приложения и генерирует файлы для всех страниц с возможностью пререндера или маршрутов +server.js, которые он находит. Каждая страница сканируется на наличие элементов <a>, указывающих на другие страницы, которые являются кандидатами на пререндеринг — поэтому обычно не нужно указывать, какие страницы должны быть доступны. Если вам необходимо указать, какие страницы должны быть доступны пререндеру, вы можете сделать это с помощью опции entries в конфигурации prerender configuration.

При пререндеринге значение building, импортированного из $app/environment, будет равно true.

Пререндеринг серверных маршрутов

В отличие от других опций страниц, prerender также применяется к файлам +server.js. Эти файлы не зависят от макетов, но наследуют значения по умолчанию от страниц, которые получают данные из них, если таковые имеются. Например, если +page.js содержит такую функцию load...

JavaScript

+page.js

export const prerender = true;

/** @type {import('./$types').PageLoad} */
export async function load({ fetch }) {
	const res = await fetch('/my-server-route.json');
	return await res.json();
}

TypeScript

+page.ts

import type { PageLoad } from './$types';
export const prerender = true;
 
export const load = (async ({ fetch }) => {
	const res = await fetch('/my-server-route.json');
	return await res.json();
}) satisfies PageLoad;

...тогда src/routes/my-server-route.json/+server.js будет рассматриваться как пререндерируемый, если он не содержит собственного export const prerender = false.

Когда не стоит делать пререндер

Основное правило таково: чтобы страница была пререндерируемой, любые два пользователя, обратившиеся к ней напрямую, должны получить от сервера одинаковое содержимое.

Не все страницы подходят для предварительного рендеринга. Любое содержимое, которое отображается с помощью пререндера, будет видно всем пользователям. Конечно, вы можете получить персонализированные данные в onMount на странице с пререндерингом, но это может привести к ухудшению пользовательского опыта, поскольку будет включать пустой начальный контент или индикаторы загрузки.

Обратите внимание, что вы все еще можете пререндерить страницы, которые загружают данные на основе параметров страницы, например, маршрут src/routes/blog/[slug]/+page.svelte.

Обращение к url.searchParams во время пререндеринга запрещено. Если вам необходимо его использовать, убедитесь, что вы делаете это только в браузере (например, в onMount).

Страницы с actions не могут быть пререндерены, поскольку сервер должен быть способен обрабатывать запросы POST.

Пререндер и ssr

Если вы установите опцию ssr в false, каждый запрос будет приводить к одной и той же пустой HTML-оболочке. Поскольку это приведет к ненужной работе, SvelteKit по умолчанию выполняет предпросмотр всех найденных страниц, для которых prerender не установлен в явном виде в false.

Конфликты маршрутов

Поскольку пререндеринг записывает данные в файловую систему, невозможно иметь две конечные точки, в которых каталог и файл будут иметь одинаковое имя. Например, src/routes/foo/+server.js и src/routes/foo/bar/+server.js попытались бы создать foo и foo/bar, что невозможно.

По этой и другим причинам рекомендуется всегда указывать расширение файла — src/routes/foo.json/+server.js и src/routes/foo/bar.json/+server.js приведут к тому, что файлы foo.json и foo/bar.json будут гармонично жить рядом.

Для страниц мы обходим эту проблему, записывая foo/index.html вместо foo.

Обратите внимание, что это отключит маршрутизацию на стороне клиента для любой навигации с этой страницы, независимо от того, активен ли уже маршрутизатор.

Устранение неполадок

Если вы столкнулись с ошибкой типа 'The following routes were marked as prerenderable, but were not prerendered' ("Следующие маршруты были отмечены как пригодные для пререндеринга, но не были пререндерены"), это связано с тем, что данный маршрут (или родительский макет, если это страница) имеет export const prerender = true, но страница на самом деле не была пререндерена, потому что до нее не добрался обходчик пререндера.

Поскольку эти маршруты не могут быть динамически рендерены сервером, это приведет к ошибкам, когда люди попытаются получить доступ к рассматриваемому маршруту. Есть два способа исправить это:

  • Убедитесь, что SvelteKit может найти маршрут по ссылкам из config.kit.prerender.entries. Добавьте ссылки на динамические маршруты (т.е. страницы с [параметрами]) в эту опцию, если они не найдены при просмотре других точек входа, иначе они не пререндерятся, потому что SvelteKit не знает какое значение должны иметь параметры. Страницы, не помеченные как пререндеренные, будут игнорироваться, а их ссылки на другие страницы не будут просмотрены, даже если некоторые из них будут пререндеренными.
  • Замените export const prerender = true на export const prerender = 'auto'. Маршруты с 'auto' могут динамически рендериться сервером

ssr

Обычно SvelteKit сначала отображает вашу страницу на сервере и отправляет этот HTML на клиент, где он гидратируется. Если вы установите ssr в false, вместо этого будет отображаться пустая страница-"оболочка". Это полезно, если ваша страница не может быть отрисована на сервере (например, из-за использования глобальных файлов только для браузера, таких как document), но в большинстве ситуаций это не рекомендуется (см. приложение).

+page.js

export const ssr = false;

Если вы добавите export const ssr = false в корень +layout.js, всё ваше приложение будет отображаться только на клиенте - что по сути означает превращение вашего приложения в SPA.

csr

Обычно SvelteKit гидратирует ваш серверный HTML в интерактивную страницу с клиентским рендерингом (CSR). Некоторые страницы вообще не требуют JavaScript - многие сообщения в блогах и страницы "о себе" попадают в эту категорию. В этих случаях вы можете отключить CSR:

+page.js

export const csr = false;

Если ssr и csr равны false, ничего не будет отображено!

trailingSlash

По умолчанию SvelteKit удаляет косую черту из URL-адресов - если вы посетите сайт /about/, он ответит перенаправлением на /about. Вы можете изменить это поведение с помощью опции trailingSlash, которая может быть одной из 'never' (по умолчанию), 'always' или 'ignore'.

Как и другие параметры страницы, вы можете экспортировать это значение из файла +layout.js или +layout.server.js, и оно будет применяться ко всем дочерним страницам. Вы также можете экспортировать конфигурацию из файлов +server.js.

src/routes/+layout.js

export const trailingSlash = 'always';

Этот параметр также влияет на prerendering. Если trailingSlash имеет значение always, маршрут типа /about приведет к созданию файла about/index.html, в противном случае будет создан about.html, зеркально отражая статические соглашения веб-сервера.

Игнорировать косые черты не рекомендуется - семантика относительных путей отличается в двух случаях (./y из /x - это /y, а из /x/ - это /x/y), и /x и /x/ рассматриваются как отдельные URL, что вредит SEO.

config

Благодаря концепции адаптеров SvelteKit может работать на различных платформах. Каждая из них может иметь специфическую конфигурацию для дальнейшей настройки развертывания - например, на Vercel вы можете выбрать развертывание некоторых частей вашего приложения на границе, а других - в бессерверных средах.

config - это объект с парами ключ-значение на верхнем уровне. После этого конкретная форма зависит от используемого адаптера. Каждый адаптер должен предоставлять интерфейс Config для импорта в целях обеспечения безопасности типов. Для получения дополнительной информации обратитесь к документации вашего адаптера.

JavaScript

ambient.d.ts

declare module 'some-adapter' {
	export interface Config { runtime: string }
}

src/routes/+page.js

/** @type {import('some-adapter').Config} */
export const config = {
	runtime: 'edge'
};

TypeScript

ambient.d.ts

declare module 'some-adapter' {
	export interface Config { runtime: string }
}

src/routes/+page.ts

import type { Config } from 'some-adapter';
 
export const config: Config = {
	runtime: 'edge'
};

Объекты config объединяются на верхнем уровне (но не на более глубоких уровнях). Это означает, что вам не нужно повторять все значения в +page.js, если вы хотите переопределить только некоторые значения в верхнем +layout.js. Например, эта конфигурация макета...

src/routes/+layout.js

export const config = {
	runtime: 'edge',
	regions: 'all',
	foo: {
		bar: true
	}
}

...отменяется этой конфигурацией страницы...

src/routes/+page.js

export const config = {
	regions: ['us1', 'us2'],
	foo: {
		baz: true
	}
}

...что приводит к значению конфигурации { runtime: 'edge', regions: ['us1', 'us2'], foo: { baz: true } } для этой страницы.

Дальнейшее чтение