@application-kit/vue-ssr
@application-kit/vue-ssr
SSR приложения на Vue.js поверх @libs-for-dev/vue-modular-application: рендер страницы на сервере со снимком Pinia и
повторным проходом на 500, гидрация клиента в одном порядке и кодек снимка. Пакет не знает корневого компонента
продукта, его локалей, фичефлагов и ключей window.*: всё это приходит параметрами.
Установка
yarn add @application-kit/vue-ssr
Peer-зависимости: vue, vue-router, pinia, devalue, @libs-for-dev/vue-modular-application — экземпляр у
приложения один.
Входы
| Вход | Для чего | Тянет |
|---|---|---|
@application-kit/vue-ssr |
изоморфно: гидрация клиента, снимок Pinia, чтение window.*, тип контекста рендера |
devalue (типы vue, pinia) |
@application-kit/vue-ssr/server |
сервер: SSR-энтри для рендерера страницы | vue/server-renderer, vue-router, vue-modular-application |
@application-kit/vue-ssr/testing |
спеки потребителя: снимок сторов через провод страницы | devalue |
Импорт любого входа не имеет побочных эффектов и не требует окружения. Nest пакету не нужен: Nest-провайдером энтри делает потребитель — зависимости context builder'а (порты, реестр модулей, логгер) знает только он.
Сервер
createSsrEntry(options) — энтри с render(url, initialState), страница которого совпадает по форме с
SsrPageInterface пакета @application-kit/nestjs-vite. На каждый запрос — свежее приложение
(VueApplication с memory history), навигация на url, renderToString с контекстом; ошибка приложения переключает
pageType на 500, пишется в лог, и дерево рендерится вторым проходом — уже страницей ошибки.
rootComponent,moduleRegistry— корневой компонент и реестр модулей продукта.buildContext(app, initialState)— контекст рендера (расширениеSsrRenderContextInterface { pageType }). Вызывается до рендера: локаль, provide флагов и всё, что разметка должна увидеть, ставится приложению здесь.describePage(context)—langи значенияwindow.*из того же контекста, которым рендерилась разметка.stateKey— ключwindow.*для снимка Pinia;logger— структурный{ error(error, message) }, подходитPinoLogger.
@Injectable()
export class EntrySsr implements SsrEntryInterface {
private readonly entry: VueSsrEntryInterface<VueSsrInitialState>
public constructor(moduleRegistry: ModuleRegistry<RouteRecordRaw[], MenuItem[]>, logger: ApplicationLogger) {
this.entry = createSsrEntry({
buildContext: (app, { locale }) => {
setLocale(app, locale)
return { locale, pageType: HttpStatus.OK }
},
describePage: (context) => ({ lang: context.locale, state: { ssrLocale: context.locale } }),
logger,
moduleRegistry,
rootComponent: Application,
stateKey: 'ssrState',
})
}
public async render(url: string, initialState: VueSsrInitialState): Promise<SsrPageInterface> {
return this.entry.render(url, initialState)
}
}
Клиент
hydrateSsrApplication(app, { stateKey, beforeMount, container }) — подъём приложения на разметке сервера. Порядок —
контракт: снимок Pinia восстанавливается до первой навигации (гварды маршрутов видят состояние сервера и не
запрашивают его заново), beforeMount — после router.isReady() и до mount (локаль и флаги первого кадра совпадают
с сервером), затем mount(container).
await hydrateSsrApplication(app, {
beforeMount: (application) => {
const locale = readSsrValue('ssrLocale')
if (isSupportedLocale(locale)) {
setLocale(application, locale)
}
},
container: '#app',
stateKey: 'ssrState',
})
restoreSsrState(app, key)— снимок под ключомkeyв Pinia приложения; ключа нет — сторы не трогаются.readSsrValue(key)— строка, которую рендерер положил вwindow[key]; иначеundefined.serializeSsrState(state),parseSsrState(serialized)— кодек снимка на devalue:Date,Map,Set,undefinedи повторные ссылки переживают провод, в отличие от JSON.
Pinia и роутер должны быть установлены в приложение до гидрации (плагином модуля).
Тесты потребителя
roundTripSsrState(state) — снимок сторов через тот же провод, что между энтри: строка на сервере → разбор на
клиенте. Спека гидрации, которая переносит экземпляр стора, а не строку, пропускает состояние, не попавшее в снимок.
pinia.state.value = roundTripSsrState(serverPinia.state.value)
Related Packages
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.1.0 | ^3.5.0 | MIT |
Pre-releases (1)
| Version | Released | License |
|---|---|---|
| 0.0.0-stage |