Пара нюансов в вопросе Webpack vs Vite
На первый взгляд может показаться что одно можно легко заменить на другое, ну или как минимум не трогать код проекта, но это не так. Я столкнулся с двумя моментами, но скорее всего их больше.
1. Обработка ошибок загрузки (не существующих) чанков
Если ваша сборка подразумевает что имена чанков между сборками могут отличаться, в хэш части, то хорошей практикой будет добавить обработку ошибки загрузки не существующих файлов. Webpack, в данном случае, возвращает специализированные ошибки:
Vite же, для js вернёт обычную ошибку, сообщение в которой может варьироваться в зависимости от браузера, а для css — заготовленную ошибку Unable to preload CSS.
Про обработку таких ошибок расскажу как нибудь в другой раз.
2. Ручное именование чанков
Иногда возникает потребность в более детальной настройке того, что и как попадёт в конкретный чанк. Для этого, в webpack, есть так называемые магические комментарии https://webpack.js.org/api/module-methods/#magic-comments. В данный момент нас интересует webpackChunkName, который позволяет указать название чанка (то, как будет именоваться js файл).
Естественно, подобные комментарии не работают в Vite. Но, мы не первые, кто столкнулся с этим вопросом, поэтому уже есть плагин https://www.npmjs.com/package/vite-plugin-webpackchunkname. Лично пока не пробовал, могут быть нюансы.
#development #frontend #javascript #webpack #vite
На первый взгляд может показаться что одно можно легко заменить на другое, ну или как минимум не трогать код проекта, но это не так. Я столкнулся с двумя моментами, но скорее всего их больше.
1. Обработка ошибок загрузки (не существующих) чанков
Если ваша сборка подразумевает что имена чанков между сборками могут отличаться, в хэш части, то хорошей практикой будет добавить обработку ошибки загрузки не существующих файлов. Webpack, в данном случае, возвращает специализированные ошибки:
Для JS: error.name = ChunkLoadError
Для CSS: error.code = CSS_CHUNK_LOAD_FAILED
Vite же, для js вернёт обычную ошибку, сообщение в которой может варьироваться в зависимости от браузера, а для css — заготовленную ошибку Unable to preload CSS.
Про обработку таких ошибок расскажу как нибудь в другой раз.
2. Ручное именование чанков
Иногда возникает потребность в более детальной настройке того, что и как попадёт в конкретный чанк. Для этого, в webpack, есть так называемые магические комментарии https://webpack.js.org/api/module-methods/#magic-comments. В данный момент нас интересует webpackChunkName, который позволяет указать название чанка (то, как будет именоваться js файл).
Естественно, подобные комментарии не работают в Vite. Но, мы не первые, кто столкнулся с этим вопросом, поэтому уже есть плагин https://www.npmjs.com/package/vite-plugin-webpackchunkname. Лично пока не пробовал, могут быть нюансы.
#development #frontend #javascript #webpack #vite
webpack
Module Methods | webpack
webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.
Экспериментальная оптимизация Webpack
Как сократить время локального запуска проекта, например, с 16 до 1 секунды? Если вы используете Webpack 5.17+, можно отложить сборку конкретного кода (чанка) до момента пока он не понадобится:
В итоге, чем лучше код разделён на чанки, тем меньше времени придётся ждать.
#development #frontend #webpack #optimisation #javascript
https://webpack.js.org/configuration/experiments/#experimentslazycompilation
Как сократить время локального запуска проекта, например, с 16 до 1 секунды? Если вы используете Webpack 5.17+, можно отложить сборку конкретного кода (чанка) до момента пока он не понадобится:
experiments: {
// true должно быть только при локальном запуске
lazyCompilation: true,
},
В итоге, чем лучше код разделён на чанки, тем меньше времени придётся ждать.
#development #frontend #webpack #optimisation #javascript
https://webpack.js.org/configuration/experiments/#experimentslazycompilation
webpack
Experiments | webpack
webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.
Как в Webstorm найти не используемый код?
Заходим в меню Code > Analyze Code > Run Inspection By Name, в появившемся поле вводим “unused” и из списка подсказок выбираем Unused global symbol. Ну а далее настраиваем параметры и нажимаем ОК.
#development #frontend #javascript #webstorm
Заходим в меню Code > Analyze Code > Run Inspection By Name, в появившемся поле вводим “unused” и из списка подсказок выбираем Unused global symbol. Ну а далее настраиваем параметры и нажимаем ОК.
#development #frontend #javascript #webstorm
Про код-стайл, зачем он нужен и как должен выглядеть
Код-стайл (он же code style, coding standards, coding convention или programming style) — некоторый набор правил и соглашений для написания кода, над которым работает более одного разработчика.
Зачем нужны эти правила?
Первое, и самое важное — убрать разногласия между разработчиками, т.к. каждый привык писать по своему и считает что именно его вариант самый верный.
Второе — предотвратить появление распространённых ошибок в коде. Например then() написали, а catch() забыли и в итоге у нас ошибка на проде.
Третье — упростить чтение кодовой базы.
В каком виде эти правила и соглашения должны быть реализованы?
Самый эффективный способ — настроить автоматические инструменты для максимального количества правил. При этом, что бы все стилистические правила (табы vs пробелы, длинна строки и т.п.) применялись автоматически, например на pre-commit hook! Почему именно так? Да всё просто, всё что делается автоматом, не должно мешать во время написания кода. Важно отметить, что автоматическое применение стилей не должно происходить до момента пока код не дописан, т.к. есть правила которые удаляют не используемый код.
Из этого вытекает что наборов правил должно быть как минимум два:
первый — для этапа написания кода, что бы “по живому” показывать ошибки и предупреждения,
второй — для автоматического форматирования кода.
Скорее всего, останутся соглашения, которые невозможно реализовать через инструменты. Самое важное, что можно и нужно с ними сделать, помимо записи в общедоступном месте, постараться максимально сократить их количество, а те что остались — подробно описать.
Самые популярные инструменты, на данный момент:
https://eslint.org
https://prettier.io
#codestyle #eslint #prettier #frontend #development #javascript
Код-стайл (он же code style, coding standards, coding convention или programming style) — некоторый набор правил и соглашений для написания кода, над которым работает более одного разработчика.
Зачем нужны эти правила?
Первое, и самое важное — убрать разногласия между разработчиками, т.к. каждый привык писать по своему и считает что именно его вариант самый верный.
Второе — предотвратить появление распространённых ошибок в коде. Например then() написали, а catch() забыли и в итоге у нас ошибка на проде.
Третье — упростить чтение кодовой базы.
В каком виде эти правила и соглашения должны быть реализованы?
Самый эффективный способ — настроить автоматические инструменты для максимального количества правил. При этом, что бы все стилистические правила (табы vs пробелы, длинна строки и т.п.) применялись автоматически, например на pre-commit hook! Почему именно так? Да всё просто, всё что делается автоматом, не должно мешать во время написания кода. Важно отметить, что автоматическое применение стилей не должно происходить до момента пока код не дописан, т.к. есть правила которые удаляют не используемый код.
Из этого вытекает что наборов правил должно быть как минимум два:
первый — для этапа написания кода, что бы “по живому” показывать ошибки и предупреждения,
второй — для автоматического форматирования кода.
Скорее всего, останутся соглашения, которые невозможно реализовать через инструменты. Самое важное, что можно и нужно с ними сделать, помимо записи в общедоступном месте, постараться максимально сократить их количество, а те что остались — подробно описать.
Самые популярные инструменты, на данный момент:
https://eslint.org
https://prettier.io
#codestyle #eslint #prettier #frontend #development #javascript
eslint.org
Find and fix problems in your JavaScript code - ESLint - Pluggable JavaScript Linter
A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code quality with ease.
Про чанки
Начать нужно с того, что весь (frontend) код который мы пишем, в конечном итоге загружается пользователями. Помимо самой загрузки, браузеру нужно этот код прочитать, проанализировать и выполнить. На всё это, как ни странно, нужно время, и чем больше этого кода, тем больше времени будут занимать все эти процессы.
Стоит сделать важное замечание: даже если нужно выполнить какую-то небольшую часть кода, загрузить и проанализировать браузер его должен полностью.
Предположим у нас есть веб-приложение с 10 страницами, из которых пользователи используют обычно 2-3, а к остальным обращаются редко, а то и вообще никогда. Будет странно загружать весь код (для всех страниц) одним куском (файлом).
Для решения этого вопроса и придумали разделение кода на небольшие кусочки (или чанки). В результате браузер загружает, анализирует и выполняет только тот код, который действительно нужен.
Разделение кода — не (совсем) автоматический процесс и требует осознанного подхода. Обычно, в отдельный чанк выносится та часть кода (со всеми её зависимостями), которая была использована через динамический импорт:
Но то, как именно код будет разделён, в конечном счёте зависит от настроек инструментов сборки, которые вы используете.
Как именно делить код, вопрос индивидуальный и зависит от конкретной задачи. Однако можно выделить пару универсальных советов. Во-первых, старайтесь выносить каждую страницу в отдельный чанк. Во-вторых, выносите функционал который не доступен на странице по умолчанию, без дополнительных действий пользователя.
Кстати, если вы пишите приложение с использованием React, то встроенная функция lazy и компонент Suspense должны быть вам хорошо знакомы.
#frontend #development #codesplitting #javascript #react
Начать нужно с того, что весь (frontend) код который мы пишем, в конечном итоге загружается пользователями. Помимо самой загрузки, браузеру нужно этот код прочитать, проанализировать и выполнить. На всё это, как ни странно, нужно время, и чем больше этого кода, тем больше времени будут занимать все эти процессы.
Стоит сделать важное замечание: даже если нужно выполнить какую-то небольшую часть кода, загрузить и проанализировать браузер его должен полностью.
Предположим у нас есть веб-приложение с 10 страницами, из которых пользователи используют обычно 2-3, а к остальным обращаются редко, а то и вообще никогда. Будет странно загружать весь код (для всех страниц) одним куском (файлом).
Для решения этого вопроса и придумали разделение кода на небольшие кусочки (или чанки). В результате браузер загружает, анализирует и выполняет только тот код, который действительно нужен.
Разделение кода — не (совсем) автоматический процесс и требует осознанного подхода. Обычно, в отдельный чанк выносится та часть кода (со всеми её зависимостями), которая была использована через динамический импорт:
import('./something')
Но то, как именно код будет разделён, в конечном счёте зависит от настроек инструментов сборки, которые вы используете.
Как именно делить код, вопрос индивидуальный и зависит от конкретной задачи. Однако можно выделить пару универсальных советов. Во-первых, старайтесь выносить каждую страницу в отдельный чанк. Во-вторых, выносите функционал который не доступен на странице по умолчанию, без дополнительных действий пользователя.
Кстати, если вы пишите приложение с использованием React, то встроенная функция lazy и компонент Suspense должны быть вам хорошо знакомы.
#frontend #development #codesplitting #javascript #react
Паттерн switch(true)
Интересный паттерн который однако встречается достаточно редко. Настолько, что его полноценная поддержка в typescript появилась только в версии 5.3 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html#switch-true-narrowing
Если в коде видим большое количество else if условий, например:
Возможно, это то самое место, где можно и нужно применить switch(true):
Конечно это субъективно, но на мой взгляд, так выглядит понятнее и самое главное логичнее.
Кстати, в SolidJS есть компоненты которые используют этот паттерн:
#javascript #typescript #frontend #development #patterns #react #solidjs
Интересный паттерн который однако встречается достаточно редко. Настолько, что его полноценная поддержка в typescript появилась только в версии 5.3 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html#switch-true-narrowing
Если в коде видим большое количество else if условий, например:
if (/* condition #1 */) {
// code #1
} else if (/* condition #2 */) {
// code #2
} else if (/* condition #3 */) {
// code #3
} else {
// code #4
}
Возможно, это то самое место, где можно и нужно применить switch(true):
switch(true) {
case /* condition #1 */:
// code #1
break;
case /* condition #2 */:
// code #2
break;
case /* condition #3 */:
// code #3
break;
default:
// code #4
}
Конечно это субъективно, но на мой взгляд, так выглядит понятнее и самое главное логичнее.
Кстати, в SolidJS есть компоненты которые используют этот паттерн:
<Switch fallback={<div>Not Found</div>}>
<Match when={state.route === "home"}>
<Home />
</Match>
<Match when={state.route === "settings"}>
<Settings />
</Match>
</Switch>
#javascript #typescript #frontend #development #patterns #react #solidjs
www.typescriptlang.org
Documentation - TypeScript 5.3
TypeScript 5.3 Release Notes
Типичная ошибка использования .sort()
Даже опытные разработчики могут не увидеть ошибку в следующем коде:
А она заключается в том, что метод sort не создаёт нового массива, а изменяет текущий. И это не очевидное поведение может привезти к появлению ошибок. Решается это довольно просто:
Видимо это всех настолько “утомило”, что в спецификацию добавили метод toSorted.
Ещё одним “решением” для предотвращения появления этой ошибки в typescript является использование ReadonlyArray. Но, к сожалению, про него практически ни кто не знает.
#frontend #development #javascript #typescript
Даже опытные разработчики могут не увидеть ошибку в следующем коде:
function sortItems<T>(items: T[]): T[] {
return items.sort(/* some sort function */);
}
А она заключается в том, что метод sort не создаёт нового массива, а изменяет текущий. И это не очевидное поведение может привезти к появлению ошибок. Решается это довольно просто:
function sortItems<T>(items: T[]): T[] {
return [...items].sort(/* some sort function */);
}
Видимо это всех настолько “утомило”, что в спецификацию добавили метод toSorted.
Ещё одним “решением” для предотвращения появления этой ошибки в typescript является использование ReadonlyArray. Но, к сожалению, про него практически ни кто не знает.
#frontend #development #javascript #typescript
Пример улучшения функции сортировки
Сортировка — довольно распространённый вид операции с данными в JavaScript / TypeScript. Например, в одном из рабочих проектов .sort встречается 97 раз в 65 файлах. При этом важно, чтобы этот код был максимально читаемым и компактным.
Обратите внимание, что некоторые примеры, для упрощения восприятия, будут без типизации. В конце будет ссылка на рабочий TypeScript код целиком.
Рассмотрим следующий пример:
На первый взгляд, код как код, и вроде бы даже всё предельно понятно. Но давайте попробуем его улучшить. Для начала, вынесем две общие функции.
Для сортировки по алфавиту:
Для сортировки по полю с перечислением (в нашем примере это type) в заданном порядке в виде массива (почему именно массив, объясню в конце):
Для объединения нескольких функций сортировки в один метод .sort() напишем ещё одну вспомогательную функцию:
Осталось переписать наш пример используя эти функции:
В итоге мы получили:
Несколько общих функций, которые можно повторно использовать в остальных частях нашего приложения, и тем самым сократили кодовую базу, а также улучшили читаемость.
Более удобную, с точки зрения поддержки, настройку сортировки по типу, т.к. в случае изменения списка FeatureType не нужно будет обновлять индексы.
Код полностью: https://gist.github.com/SanichKotikov/c8c3dac1f0de4b722b13c4af49b29c61
#frontend #development #javascript #typescript #sort
Сортировка — довольно распространённый вид операции с данными в JavaScript / TypeScript. Например, в одном из рабочих проектов .sort встречается 97 раз в 65 файлах. При этом важно, чтобы этот код был максимально читаемым и компактным.
Обратите внимание, что некоторые примеры, для упрощения восприятия, будут без типизации. В конце будет ссылка на рабочий TypeScript код целиком.
Рассмотрим следующий пример:
const MAP_TYPE_TO_ORDER: Record<FeatureType, number> = {
[FeatureType.Default]: 0,
[FeatureType.Local]: 1,
[FeatureType.Unknown]: 2,
};
function sortFeaturesByTypeAndTitle(features: Feature[]): Feature[] {
return [...features].sort((a, b) => {
const numA = MAP_TYPE_TO_ORDER[a.type];
const numB = MAP_TYPE_TO_ORDER[b.type];
if (numA !== numB) {
return numA - numB;
}
return a.title.localeCompare(b.title);
});
}
На первый взгляд, код как код, и вроде бы даже всё предельно понятно. Но давайте попробуем его улучшить. Для начала, вынесем две общие функции.
Для сортировки по алфавиту:
function inAbcOrderBy(prop) {
return (a, b) => a[prop].localeCompare(b[prop]);
}
Для сортировки по полю с перечислением (в нашем примере это type) в заданном порядке в виде массива (почему именно массив, объясню в конце):
function inCustomOrderBy(prop, order) {
return (a, b) => order.indexOf(a[prop]) - order.indexOf(b[prop]);
}
Для объединения нескольких функций сортировки в один метод .sort() напишем ещё одну вспомогательную функцию:
function inPriority(...sorters) {
return (a, b) => {
for (let i = 0; i < sorters.length; i++) {
const result = sorters[i](a, b);
if (result !== 0) return result;
}
return 0;
};
}
Осталось переписать наш пример используя эти функции:
const TYPE_ORDER = [
FeatureType.Default,
FeatureType.Local,
FeatureType.Unknown,
];
function sortFeaturesByTypeAndTitle(features: Feature[]): Feature[] {
return [...features].sort(
inPriority(
inCustomOrderBy('type', TYPE_ORDER),
inAbcOrderBy('title')
)
);
}
В итоге мы получили:
Несколько общих функций, которые можно повторно использовать в остальных частях нашего приложения, и тем самым сократили кодовую базу, а также улучшили читаемость.
Более удобную, с точки зрения поддержки, настройку сортировки по типу, т.к. в случае изменения списка FeatureType не нужно будет обновлять индексы.
Код полностью: https://gist.github.com/SanichKotikov/c8c3dac1f0de4b722b13c4af49b29c61
#frontend #development #javascript #typescript #sort
Gist
sort-example.ts
GitHub Gist: instantly share code, notes, and snippets.
https://kettanaito.com/blog/dont-sleep-on-abort-controller
Хорошая обзорная статья про AbortController. Обычно его используют только для отмены запросов fetch, но на самом деле, при желании, отменять можно всё что угодно.
Самым вкусным, на мой взгляд, является отмена пачки подписок на события одной командой:
#frontend #development #javascript #react
Хорошая обзорная статья про AbortController. Обычно его используют только для отмены запросов fetch, но на самом деле, при желании, отменять можно всё что угодно.
Самым вкусным, на мой взгляд, является отмена пачки подписок на события одной командой:
useEffect(() => {
const controller = new AbortController();
const options = { signal: controller.signal };
el.addEventListener('pointerdown', handler, options);
el.addEventListener('pointerup', handler, options);
el.addEventListener('pointercancel', handler, options);
el.addEventListener('pointerleave', handler, options);
el.addEventListener('click', handler, options);
return () => {
controller.abort();
};
}, []);
#frontend #development #javascript #react
kettanaito.com
Don't Sleep on AbortController
Learn how to make anything abortable in JavaScript.
👍3
В продолжении темы оптимизации
В прошлом посте я рассказывал про оптимизацию средствами CSS, на примере конкретного свойства. Пришло время поговорить и про JS.
Возьмём всё тот же код с использованием SolidJS: https://github.com/SanichKotikov/solid-emoji-demo
Примечание: В этот раз все цифры будут указаны с учётом 4х кратного замедления, т.к. они ближе к цифрам в реальных условиях. Плюс, замеры производились на production сборке.
В качестве отправной точки возьмём код, в котором стили объявлены через свойство style из JS:
Выносим всю стилизацию, кроме contain-intrinsic-height, из JS в CSS файл, и сразу получаем следующий результат:
Выполнение JS кода, а также recalculate style, сократились примерно в двое. Кстати, если использовать emotion/css, то это практически ни как не повлияет на изначальные цифры. Делаем очевидный вывод — стилизация через JS (в рантайме) имеет свои накладные расходы.
Интересно, что если унести и contain-intrinsic-height в CSS, само собой с каким-то усреднённым значением, то это может замедлить Layout до ~24 ms.
Как ещё можно сократить время выполнения JS в таком, казалось бы, простом коде? Избавимся от “конструкций” библиотеки (в нашем случае SolidJS), там где это возможно.
Во-первых, избавимся от отдельного компонента EmojiButton, т.к. в нём нет ни какого практического смысла. Запомните, чем больше в проекте компонентов, тем он медленнее, в том числе и на этапе сборки.
Во-вторых, заменим For на обычный .map, т.к. список emoji статический, и в этом компоненте тут нет какого-то особого смысла. Попутно можно удалить и createMemo, по той же причине. Кстати, компонент Index медленнее чем For.
В итоге, получаем ещё немного прироста в выполнении JS:
П.С. Изменения можно посмотреть в том же репозитории, ветки css и js.
#development #performance #solidjs #javascript
В прошлом посте я рассказывал про оптимизацию средствами CSS, на примере конкретного свойства. Пришло время поговорить и про JS.
Возьмём всё тот же код с использованием SolidJS: https://github.com/SanichKotikov/solid-emoji-demo
Примечание: В этот раз все цифры будут указаны с учётом 4х кратного замедления, т.к. они ближе к цифрам в реальных условиях. Плюс, замеры производились на production сборке.
В качестве отправной точки возьмём код, в котором стили объявлены через свойство style из JS:
Script ~54 ms
Recalculate: ~7 ms
Layout: ~19 ms
PrePaint: ~2 ms
Paint: ~7 ms
Выносим всю стилизацию, кроме contain-intrinsic-height, из JS в CSS файл, и сразу получаем следующий результат:
Script ~24 ms
Recalculate: ~3 ms
Layout: ~19 ms
PrePaint: ~1.3 ms
Paint: ~6.3 ms
Выполнение JS кода, а также recalculate style, сократились примерно в двое. Кстати, если использовать emotion/css, то это практически ни как не повлияет на изначальные цифры. Делаем очевидный вывод — стилизация через JS (в рантайме) имеет свои накладные расходы.
Интересно, что если унести и contain-intrinsic-height в CSS, само собой с каким-то усреднённым значением, то это может замедлить Layout до ~24 ms.
Как ещё можно сократить время выполнения JS в таком, казалось бы, простом коде? Избавимся от “конструкций” библиотеки (в нашем случае SolidJS), там где это возможно.
Во-первых, избавимся от отдельного компонента EmojiButton, т.к. в нём нет ни какого практического смысла. Запомните, чем больше в проекте компонентов, тем он медленнее, в том числе и на этапе сборки.
Во-вторых, заменим For на обычный .map, т.к. список emoji статический, и в этом компоненте тут нет какого-то особого смысла. Попутно можно удалить и createMemo, по той же причине. Кстати, компонент Index медленнее чем For.
В итоге, получаем ещё немного прироста в выполнении JS:
Script ~19 ms
П.С. Изменения можно посмотреть в том же репозитории, ветки css и js.
#development #performance #solidjs #javascript
GitHub
GitHub - SanichKotikov/solid-emoji-demo
Contribute to SanichKotikov/solid-emoji-demo development by creating an account on GitHub.
Children в SolidJS и порядок выполнения
Недавно столкнулся с не совсем очевидным моментом, связанным с props.children в SolidJS. Для понимания проблемы возьмём вот такой код:
Примечание: Опустим момент, что компонент Wrapper не реактивный, сейчас нас это не интересует.
Вопреки ожиданиям, компоненты выполнятся в следующем порядке: App > Wrapper > Content > Provider. В результате чего, контекст из Provider будет недоступен в компоненте Content. Чтобы понять, что пошло не так, давайте посмотрим во что превращается JSX при сборке проекта:
Параметр children превратился в getter функцию, которая будет выполнена при любой попытке чтения! Например, при передаче в качестве аргумента в функцию:
Очевидным решением проблемы, в данном случае, будет замена интерфейса параметра children компонента Wrapper, с JSX на функцию, вызов которой вернёт этот самый JSX:
#development #frontend #solidjs #javascript #jsx
Недавно столкнулся с не совсем очевидным моментом, связанным с props.children в SolidJS. Для понимания проблемы возьмём вот такой код:
function Wrapper(props) {
return props.when
? props.wrap(props.children, props.when)
: props.children;
}
function App() {
return (
<Wrapper
when={true}
wrap={(content) => (
<Provider>{content}</Provider>
)}
>
<Content />
</Wrapper>
);
}
Примечание: Опустим момент, что компонент Wrapper не реактивный, сейчас нас это не интересует.
Вопреки ожиданиям, компоненты выполнятся в следующем порядке: App > Wrapper > Content > Provider. В результате чего, контекст из Provider будет недоступен в компоненте Content. Чтобы понять, что пошло не так, давайте посмотрим во что превращается JSX при сборке проекта:
function App() {
return _$jsx(Wrapper, {
when: true,
wrap: content => _$jsx(Provider, {
children: content
}),
get children() {
return _$jsx(Content, {});
}
});
}
Параметр children превратился в getter функцию, которая будет выполнена при любой попытке чтения! Например, при передаче в качестве аргумента в функцию:
props.wrap(props.children, props.when)
Очевидным решением проблемы, в данном случае, будет замена интерфейса параметра children компонента Wrapper, с JSX на функцию, вызов которой вернёт этот самый JSX:
function App() {
return (
<Wrapper
when={true}
wrap={(content) => (
<Provider>{content()}</Provider>
)}
>
{() => <Content />}
</Wrapper>
);
}
#development #frontend #solidjs #javascript #jsx
🔥2