Стадии и переменные среды в Svelte (SvelteKit)

В процессе разработки приложения Svelte вы, скорее всего, столкнетесь со сценарием, когда вам нужно будет использовать различные значения в зависимости от того, на какой стадии (локальной, staging, production и т.д.) запущено приложение.

Например, допустим, у вас есть следующий файл +page.server.ts, который использует функцию load, которая получает сообщения блога с локального сервера и передает их на маршрутную страницу +page.svelte:

+page.server.ts

import { error, type Load } from '@sveltejs/kit';

export const load: Load = async () => {
    const res = await fetch(`http://localhost:1337/api/blog-posts`);

    const { data } = await res.json();

    if (res.ok) {
        return { posts: data };
    }

    throw error(404, 'Unable to fetch posts');
};
Вход в полноэкранный режим Выход из полноэкранного режима

Итак, вы развернули бэкенд (API) и готовы развернуть фронтенд (приложение Svelte) в продакшене — только вы еще не можете этого сделать, потому что URL, указанный в fetch, указывает на localhost. Нам нужен этот URL для получения данных из нашего развернутого API (давайте представим, что он развернут на https://APP.herokuapp.com/api/blog-posts).

Конечно, мы могли бы заменить URL на наш производственный (https://APP.herokuapp.com/api/blog-posts), развернуть его и менять его обратно на localhost (http://localhost:1337/api/blog-posts) всякий раз, когда мы делаем локальные изменения… но это быстро станет утомительным.

Как мы можем динамически использовать разные URL в зависимости от того, на каком этапе работает приложение?

В более поздних версиях SvelteKit используются следующие сценарии сборки:

"scripts": {
  "dev": "vite dev",
  "build": "vite build",
  //...
}
Вход в полноэкранный режим Выход из полноэкранного режима

(Раньше это было не так, раньше это были svelte-kit dev и svelte-kit build соответственно).

Это означает, что мы можем (продолжайте читать для лучшего решения) использовать переменную окружения Vite MODE, которая автоматически предоставляется нам. По умолчанию, сервер dev (команда dev) работает в режиме development, а команда build работает в режиме production. (Подробнее о режимах вы можете прочитать здесь).

Вы можете получить доступ к переменным окружения через Vite, используя import.meta.env, поэтому если вы хотите сослаться на MODE, вы можете использовать const { MODE } = import.meta.env (или const MODE = import.meta.env.MODE, если вы не любитель деструктуризации, как я).

Вернемся к примеру, поэтому мы можем добавить троичный оператор к MODE, что даст нам:

+page.server.ts

import { error, type Load } from '@sveltejs/kit';

const { MODE } = import.meta.env;
const LOCAL_URL = 'http://localhost:1337/api/blog-posts';
const PROD_URL = 'https://APP.herokuapp.com/api/blog-posts'; // Replace with whatever your deployed URL is

export const load: Load = async () => {
    const res = await fetch(MODE === 'development' ? LOCAL_URL : PROD_URL);

    const { data } = await res.json();

    if (res.ok) {
        return { blogs: data };
    }

    throw error(404, 'Unable to fetch blogs');
};
Войти в полноэкранный режим Выйти из полноэкранного режима

Предполагая, что ваша конечная точка не требует ключа API, вышеуказанное должно попасть в правильную конечную точку и вернуть данные, специфичные для этапа (🥳). Вы можете убедиться в этом, запустив npm run build для запуска приложения в режиме "production".

Как мы можем упростить эту задачу с помощью пользовательских переменных .env?

Vite использует пакет dotenv для загрузки любых дополнительных переменных окружения в ваш envDir (по умолчанию это корневой каталог):

.env (загружается во всех случаях)
.env.local (загружается во всех случаях, игнорируется git’ом)
.env.[mode] (загружается только в указанном режиме)
.env.[mode].local (загружается только в указанном режиме, игнорируется git)

Еще пара моментов, которые следует отметить:

  • Файл env для конкретного режима (например, .env.production) будет иметь более высокий приоритет, чем общий (например, .env).
  • Дополнительные переменные окружения должны иметь префикс VITE_.

Зная это, мы можем создать следующие…

.env.development (файл в корневом каталоге для режима "development")

содержимое:

VITE_API_URL=http://localhost:1337/api/blog-posts
Войти в полноэкранный режим Выход из полноэкранного режима

.env.production (файл в корневом каталоге для режима "production")

содержимое:

VITE_API_URL=https://APP.herokuapp.com/api/blog-posts
Вход в полноэкранный режим Выход из полноэкранного режима

…и мы можем упростить нашу функцию загрузки, удалив троичность и просто используя переменную окружения VITE_API_URL. SvelteKit предоставляет нам $env/static/public, поэтому вместо использования import.meta.env мы можем использовать import { VITE_API_URL } from '$env/static/private';, что дает нам:

+page.server.ts

import { error, type Load } from '@sveltejs/kit';

import { VITE_API_URL } from '$env/static/private';

export const load: Load = async () => {
    const res = await fetch(VITE_API_URL);

    const { data } = await res.json();

    if (res.ok) {
        return { blogs: data };
    }

    throw error(404, 'Unable to fetch blogs');
};
Вход в полноэкранный режим Выйти из полноэкранного режима

Вот и все! 👨💻

Если вам нужна дополнительная информация о вышеописанном или о чем-либо еще (например, о добавлении новых окружений, таких как staging), посмотрите документацию Vite, документацию SvelteKit или официальный дискорд Svelte.

Оцените статью
devanswers.ru
Добавить комментарий