Skip to content

Рендеринг на стороне клиента

EffCSS уже работает на стороне клиента без каких-либо усилий с вашей стороны. Однако механизм гидратации стилей, который обычно используется при рендеринге на сервере, также может быть использован для рендеринга на стороне клиента (CSR) с использованием vite-plugin-effcss.

Плагин захватывает сгенерированный EffCSS CSS-код с помощью конвейера Vite SSR и встраивает его в HTML. Это позволяет устранить FOUC и ускорить первый рендеринг за счет гидратации CSS. Работает как в режиме разработки, так и в режиме сборки с нулевыми дополнительными зависимостями (без esbuild, без tsx, без дополнительных загрузчиков).

Zero-config — работает без каких-либо опций. Просто добавьте его в свой массив плагинов.

CSR-ориентированный — для SSR/SSG используйте вызовы serialize() и serializeMeta(). Подробности смотрите в разделе Рендеринг на стороне сервера.

Использование плагина

Во-первых, вам нужно установить плагин в свой проект:

bash
npm install vite-plugin-effcss --save-dev

EffCSS объявлен как peer dependency — убедитесь, что библиотека установлена в вашем проекте:

bash
npm install effcss

Затем добавьте его в конфигурацию Vite:

ts
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import effcss from 'vite-plugin-effcss';

export default defineConfig({
  plugins: [react(), effcss()],
});

Добавьте плейсхолдер в свой HTML (необязательно - по умолчанию добавляется перед </head>).:

html
<head>
  <!-- EFFCSS_INJECT -->
</head>

Вот и все. Плагин захватывает весь сгенерированный CSS-код EffCSS и встраивает его в ваш HTML-код.

Обратите внимание, что плагин не устанавливает prefix, minify и другие параметры EffCSS - они должны быть настроены в вашем собственном исходном коде с помощью configure():

ts
// src/effcss-config.ts
import { configure } from 'effcss';

configure({
  prefix: 'my',
  minify: true,
});

Опции

Плагин поддерживает следующие опции:

OptionTypeDefaultDescription
verbosebooleanfalseПодробное логирование
entrystringЯвная точка входа (например, /src/main.tsx). Автоматически определяется из <script type="module" src="..."> в index.html, если не указана
placeholderstring'<!-- EFFCSS_INJECT -->'HTML-плейсхолдер, который нужно заменить на <style>
injectTo'head' | 'head-prepend' | 'body''head'Резервный вариант инжектирования стилей, если плейсхолдер не найден
injectMetabooleantrueДобавить serializeMeta() в виде <script> с метаданными JSON

Как это работает

                    buildStart()

                 ┌─────────┴─────────┐
                 │                   │
                 ▼                   ▼
           Server exists?      Server null?
           (dev mode)          (build mode)
                 │                   │
                 ▼                   ▼
      write tmp .ts file     createServer() + virtual module
      → ssrLoadModule        → ssrLoadModule('effcss:capture')
                 │                   │
                 └───────┬───────────┘

               mod.css + mod.meta


               transformIndexHtml
               → inject <style> + <script>

Плагин создает модуль захвата, который:

  1. Импортирует EffCSS (для доступа к serialize() / serializeMeta())
  2. Импортирует вашу точку входа — для выполнения и регистрации стилей
  3. Вызывает serialize() — захватывает итоговый CSS + метаданные в виде строк
  4. Встраивает результаты в ваш HTML с помощью transformIndexHtml

Режим разработки — использует существующий ViteDevServer с временным файлом .ts, а затем очищает его.

Режим сборки — создает временный сервер разработки Vite с помощью createServer(), регистрирует виртуальный модуль 'effcss:capture' с хуками resolveId/load, загружает его с помощью ssrLoadModule() и закрывает сервер. Включены пользовательские плагины (React, Vue и т. д.), поэтому импорт JSX, SVG и CSS корректно преобразуется. Плагин исключает себя из вложенного сервера, чтобы предотвратить бесконечную рекурсию.

Технические примечания

  • Vite: ^5.0.0 || ^6.0.0
  • EffCSS: ^5.4.0
  • Runtime: EffCSS остаётся в составе бандла в браузере

Опубликовано под лицензией Apache License 2.0