Модификаторы событий
Vue компилирует модификаторы шаблонов в вспомогательные функции времени выполнения, такие как
withModifiers(...) и withKeys(...). Эти функции рассчитаны на работу с настоящими объектами Event браузера.
В @omnicajs/vue-remote нативные события отслеживаются на стороне host, затем сериализуются
и передаются через транспорт в удаленный обработчик. То есть на удаленную сторону приходит
не исходный экземпляр DOM-события, а его сериализованный снимок.
Из-за этого стандартного поведения Vue недостаточно для удаленных шаблонов:
- у сериализованного объекта нет методов вроде
preventDefault()иstopPropagation(); - проверки, завязанные на «живую» идентичность события, например
.self, нельзя надежно воспроизвести по обычному снимку; - проверки клавиш, указателя и системных модификаторов могут не получить нужные поля, если сериализатор на стороне host явно их не сохранил;
- если обычная вспомогательная функция Vue запускается на переданном сериализованном объекте, код модификаторов начинает работать некорректно или падает во время выполнения.
Решение состоит в том, чтобы сохранить метаданные модификаторов на этапе сборки и дать стороне host применить зависящую от нативного события часть логики до сериализации. Именно это и делают webpack loader и Vite plugin, описанные ниже.
Что поддерживается
Ссылка на заголовокЕсли rewrite включен, remote templates и render functions сохраняют:
- event option modifiers:
.capture,.once,.passive; - propagation/default modifiers:
.stop,.prevent,.self; - key и pointer guards:
.enter,.left,.right,.ctrl,.alt,.shift,.meta,.exact.
Обычные listeners без модификаторов продолжают использовать исходный transport path.
Что должна увидеть трансформация
Ссылка на заголовокЧтобы модификаторы действительно заработали, трансформация сборщика должна увидеть:
- исходные удаленные SFC, например
Widget.remote.vue; - сгенерированные из этих SFC подмодули Vue, в первую очередь запросы
template,scriptиscriptSetup; - отдельные файлы входа удаленной части, например
main.remote.tsилиpanel.remote.tsx.
Если один из этих этапов пропущен, шаблон может успешно собраться, но поведение модификаторов во время выполнения не вернется.
Настройка webpack
Ссылка на заголовокДля webpack этот loader нужно воспринимать как дополнение к vue-loader, а не как его замену.
Компиляцией SFC по-прежнему занимается vue-loader, а @omnicajs/vue-remote/webpack-loader
отслеживает точки входа удаленной части и переписывает импорты вспомогательных функций в уже сгенерированных модулях.
На практике конфигурация webpack должна делать три вещи:
- пропускать исходный
.vue-файл через remote loader, чтобы можно было определить<script remote>и<script setup remote>; - сохранять стандартный
vue-loaderrule иVueLoaderPlugin; - запускать remote loader для сгенерированных запросов к модулям Vue и для отдельных файлов входа
.remote.ts/.remote.js.
Пример конфигурации:
const { VueLoaderPlugin } = require('vue-loader')
module.exports = { module: { rules: [ { test: /\.vue$/, enforce: 'pre', loader: '@omnicajs/vue-remote/webpack-loader', }, { test: /\.vue$/, loader: 'vue-loader', }, { test: /\.vue$/, resourceQuery: /vue.*type=(?:template|script|scriptSetup)/, loader: '@omnicajs/vue-remote/webpack-loader', }, { test: /\.remote\.(?:[cm]?[jt]sx?)$/, loader: '@omnicajs/vue-remote/webpack-loader', }, ], }, plugins: [ new VueLoaderPlugin(), ],}Что дает такая конфигурация:
Widget.remote.vueопределяется как удаленный SFC по имени файла;- обычный
Widget.vueможно явно пометить через<script remote>или<script setup remote>; - у сгенерированных Vue
template/scriptмодулей переписываются импортыwithModifiers(...)иwithKeys(...); - отдельные файлы входа удаленной части вроде
main.remote.tsпроходят через тот же путь преобразования.
Если в проекте уже есть сложные oneOf-ветки или генераторы правил от фреймворка,
сохраните ту же идею: remote loader должен увидеть и исходный запрос к SFC, и сгенерированные запросы к модулям Vue.
Настройка Vite
Ссылка на заголовокДля Vite подключите remote plugin рядом с @vitejs/plugin-vue:
import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'import { vueRemoteVitePlugin } from '@omnicajs/vue-remote/vite-plugin'
export default defineConfig({ plugins: [ vue(), vueRemoteVitePlugin(), ],})На практике это означает:
vue()остается стандартным компилятором SFC;vueRemoteVitePlugin()должен находиться в том же Vite-конфиге, чтобы видеть и переписывать сгенерированные модули Vue;- для явных файлов входа удаленной части используйте
*.remote.vue, либо отмечайте обычный SFC через<script remote>/<script setup remote>; - для entry-скриптов вне SFC используйте
*.remote.ts,*.remote.js,*.remote.tsxили*.remote.jsx.
Внутренняя логика преобразования общая с webpack loader, поэтому семантика модификаторов в обоих вариантах сборки остается одинаковой.
Замечания по разработке и tooling
Ссылка на заголовок- Remote-native template ref inference настраивается отдельно через
@omnicajs/vue-remote/tooling. - Модификаторы в шаблонах работают и для нативных узлов DOM, и для Vue-компонентов стороны host, описанных через
defineRemoteComponent(...). - В ручных render functions можно использовать те же вспомогательные функции для удаленной стороны из
@omnicajs/vue-remote/remote.
Далее
Ссылка на заголовок- Базовая настройка: Быстрый старт.
- Контракты на стороне host: Компоненты хоста.
- Моделирование UI на стороне remote: Компоненты remote.