Comments 13
У меня тоже получилось сделать функциональные компоненты как в Реакте. А затем роутинг и реактивность, уместить на 1 экран кода.
Особо нет времени смотреть на код. Просмотрел только бегло. Сразу возникли вопросы.
1) я вижу, что в примере роуты у Вас через #. Значит ли это, что вы сразу полностью грузите все приложение со всеми страницами? Или это только для примера в codepen?
2) разве в вашем фреймворке (то, от чего я призываю отказаться) можно вставлять теги как есть? Или только через вашу абстракцию?
3) если все-таки нормальные теги (элементы) вставлять можно, то как вы намерены обрабатывать случаи, когда эти элементы исчезают из DOM? Допустим, элемент уничтожен каким-либо способом. Как в таком случае отследить этот момент и очистить обработчик, чтобы ссылка на этот элемент в обработчике не препятствовала работе сборщика мусора?
Роуты в этом примере реализованы на чистом JavaScript, также этот пример одностраничный с использованием внешней зависимости. Но вы можете организовать любую подгрузку страниц на ваш выбор.
Это не фреймворк, а библиотека, которая имеет всего 2 функции, которые делают
document.createElement
и обновление созданного элемента более простым и декларативным. "Теги" или элементы дерева DOM создаются программно. Есть 3 способа их создания: JSX, fuctional style, hyper style. Вместе с элементами DOM, также добавляются метаданные, чтобы можно было их обновить с помощью функцииupdate()
, поэтому элементы можно создавать только функцией создания библиотеки.Чтобы отследить удаление элемента из DOM - существует пропса
mount
, в которой можно установить событие наunmount
. Более подробный обзор жизненного цикла есть в мануале.
1) а есть реализованный пример нескольких страниц, чтобы можно было увидеть, как там подгружаются скрипты и стили при переходе по ссылкам? Что-то у меня подозрение, что если сделать все по-уму, там будет далеко не один экран..
2) ну.. я бы не сказал, что это прям вот декларативно ) Кроме того, с таким подходом очень резко ограничивается область применения Fusor. Опять же непонятно, чем же это лучше тех же веб-компонентов, если фактически update вызывается императивно.
Есть простой пример роутинга с одноуровневыми переходами и более сложный с многоуровневыми компонентами.
Если
update
декларируется в пропсе - то декларативно, можно и императивно, либо как в примере в пропсеmount
- что тоже декларативно если сделать хэлпер функцию. Кстати не многие осознают что например в Реакт, апдейт также вызывается императивно через -setState()
.
Напоминает вайб turbolinks.
Вообще, кажется много телодвижений лишние и решаются просто грамотным использованием веб технологий. Тот же FOUC(при внутреннем переходе) решается кешированием стилей. Зачем нужен роутер в такой схеме — не очень понятно. Динамические урл он не поддерживает, стейт между переходами, вроде как, тоже не нужно хранить (у нас же сайт, а не приложение). В общем, не раскрыли тему.
Кстати, интересно что конкретно не получилось сделать с vite. Потому что вообще говоря он для такого должен хорошо подойти.
В целом, желание сделать без фреймворков похвально. Но, ИМХО, гораздо интереснее научиться делать кроссфреймворкные решения. Чтобы был компонент Button и его можно было использовать в react, vue, svelte, или в даже vanilla. И при этом, чтобы было не важно, а на каком фреймворке он написан(или вообще без фреймворка). Кажется это действительно дистилирует подход к вебу и фреймворки станут просто библиотеками.
Кстати, интересно что конкретно не получилось сделать с vite.
Честно говоря, уже не помню сути... Помню, что там внутренний сервер, который поднимается при разработке, работает совсем не так, как должен работать реальный сервер после деплоя (или как я изначально ожидал).
Вроде еще были проблемы при предобработке html - файлов... Ну а может дело во врожденной кривизне рук )
Насчет необходимости роутера.. Здесь вопрос, конечно, спорный. Я его сделал для возможности разработки именно приложений, в которых есть какое-либо сохраняемое состояние. Динамические роуты - здесь вопрос добавления нескольких регулярок и небольшой доработки. Я не стал с этим заморачиваться по причине отсутствия необходимости.
Ну и js выполняется не мгновенно. До того момента как JS отработает и отрисуются наши веб-компоненты пройдет некоторое время. Поэтому могут быть мигания. Когда же в окне компоненты уже зарегистрированы - такой проблемы нет.
Про проблему с vite, если вспомните, будет интересно почитать поподробнее.
Ну и js выполняется не мгновенно. До того момента как JS отработает и отрисуются наши веб-компоненты пройдет некоторое время. Поэтому могут быть мигания.
А Вы эти мигания на практике наблюдали? Потому что вообще говоря, если делать правильно, их быть не должно.
Насчет необходимости роутера.. Здесь вопрос, конечно, спорный. Я его сделал для возможности разработки именно приложений, в которых есть какое-либо сохраняемое состояние.
Хм. Не могу придумать подходящий кейс. Обычно на сайтах всё кросстраничное состояние персистентно (либо на сервере, либо в условном localStorage). Можете привести пример состояния, на которое Вы делали расчёт.
Динамические роуты - здесь вопрос добавления нескольких регулярок и небольшой доработки.
Тут аккуратнее. Там ещё вопросы приоритетов есть. Вообще, хороший роут матчер — это штука весьма нетривиальная.
Плюс, не очень понятно, как это всё интегрировать с деплоем. То есть сейчас, у Вас initial page load делается в режиме html, няп. И можно просто закинуть весь фронт на cdn и оно просто будет работать. А если появляются динамические роуты, то нужно либо делать какой-то стаб для initial page load (что вредит времени загрузки), либо дублировать роутер в виде конфига для cdn...
Ну и динамические роуты сейчас нужны плюс-минус постоянно. Даже для сайтов. Поэтому важный момент.
P.S. на всякий случай: рассматривали для Ваших задач какой-нибудь Astro, или solid-start?
Ну и динамические роуты сейчас нужны плюс-минус постоянно. Даже для сайтов. Поэтому важный момент.
Логично. Добавил пример. https://grigorenkosergey.github.io/native-SPA/pages/dynamic/12 Правда, реализовал на коленках, может что-то еще упустил.
Может потом внесу UPD в статью.
По приоритетам.. Если высчитывать совпадение с от наиболее специфичного к наименее специфичному, то особых проблем быть не должно.
А Вы эти мигания на практике наблюдали? Потому что вообще говоря, если делать правильно, их быть не должно.
На MDN постоянно вижу, когда перехожу по страницам. Несмотря на то, что там стили и js полностью берутся из кеша.
Хм. Не могу придумать подходящий кейс.
Ну.. Мне тоже сходу в голову не приходит ) Но я уже говорил об этом, что
"React со своим роутером нанес непоправимый урон моей психике". Потом проведу чуть более полное исследование этого вопроса.
P.S. на всякий случай: рассматривали для Ваших задач какой-нибудь Astro, или solid-start?
Нет. Посмотрю как-нибудь.
Да и забывать о FOUC (Flash Of Unstyled Content) не стоит. Когда страница грузится в первый раз - это не так раздражает, когда это постоянно происходит при перемещениях по страницам одного сайта. Реализовать роутинг в этом случае кажется более простым решением.
Как избежать мелькания нестилизованного контента
До появления Declarative Shadow DOM одним из распространенных методов предотвращения FOUC было применение правила стиля display:none
к пользовательским элементам, которые еще не были загружены, поскольку у них не был прикреплен и заполнен их теневой корень. Таким образом, контент не отображается до тех пор, пока он не будет «готов»:
<style>
x-foo:not(:defined) > * {
display: none;
}
</style>
C декларативным теневой DOM
<style>
x-foo:not(:defined) > template[shadowrootmode] ~ * {
display: none;
}
</style>
На практике ещё если не использовать серверный рендеринг, надо ждать, когда компоненты загрузятся и надо ещё первое отображение обрабатывать, пока роутинг не появится
template.html лучше js файлом сделать.
При рендеринге туда методы можно будет добавлять для обновления частей компонента и работать без сборщика будет.

Вам не нужен вебпак, Gulp подходит лучше всего для этой задачи. Он и в настройке проще. А со сборкой js отлично справляется esbuild, для стилей sass и тд.
Вообще идея очень интересная, поддерживаю ваше начинание! Считаю велосипеды - это двигатель прогресса. Я тоже устал от Реакта, но пошел немного другим путем. Сделал лоадер для jsx, который позволяет работать с jsx/tsx в node.js, что позволяет получить SSR по умолчанию и без костылей. Своего рода шаблонизатор с jsx синтаксисом и полной поддержкой js внутри. Может выполняться как на сервере, так и на клиенте. Оформил в npm пакет и опубликовал. Готовлю документацию полноценную
Веб. К черту фреймворки! Пишем свой starter-kit с роутером и сторами