Dev News от Максима Соснова
Привет! Меня зовут Максим Соснов и по утрам я читаю всякие разные дайджесты про фронтенд, разработку и управление разработкой. Самые интересные, по моему мнению, ссылки из этих дайджестов я кидаю в этот канал с небольшим описанием. Контакт: @crazymax101
Більше- Підписники
- Перегляди допису
- ER - коефіцієнт залучення
Триває завантаження даних...
Триває завантаження даних...
Всем привет! Меня зовут Кирилл и я работаю фронтенд-разработчиком. Я расскажу о том, как мы перевели несколько тысяч файлов, написанных на JavaScript, с легаси кода, который использовал goog.module ,...
<link rel="preload">
. Но это подходит только для данных, о загрузке которых мы уверены еще на уровне первоначального рендера страницы. Но иногда мы получаем эту уверенность по другому тригеру. Например, наше приложение предоставляет большой список и при клике на какую-то кнопку нужно загрузить и отобразить дополнительную информацию о конкретном элементе списка. Вместо того, чтобы загружать данные только по клику, мы можем их предзагружать если пользователь водит мышкой по компоненту больше скольки-то милисекунд. Это может привести к излишней загрузке в некоторых кейсах, но если мы, например, знаем на основе нашей аналитики, что 90% пользователей, которые держат мышку на элементе дольше 300мс кликают на кнопку загрузки - то можно облегчить жизнь 90% пользователей.
Последний рассмотренный паттерн - Code Splitting. Не весь код приложения нужен пользователю прямо сейчас. Вместо этого можно загружать верстку или логику только тогда, когда она реально понадобилась.
https://martinfowler.com/articles/data-fetch-spa.html#ChoosingTheRightPattern
#development #martinFowler #SPA #javascriptFive patterns to help Single Page Applications fetch data from remote sources
Unit testing HTML templates
query { __typename @a @b @c @d @e ... # imagine 1k+ more of these }И чтобы собрать ответ с ошибкой сервер потратит в 2000 раз больше памяти, чем занимает сам запрос Также автор дважды подмечает N+1 проблему, которую можно решать через паттерн Dataloader. Проблема с GraphQL не только в том, что N+1 актуальна для загрузки данных, но она актуальна и для авторизации. В целом, конечно, ничего нового в этой статье нет - GraphQL очень удобен для запроса данных, но не очень удобен для безопасного и производительного резолва этих данных. Кроме того, для большинства решений и дебага, backend-разработчику проще работать с REST, чем с GraphQL. Под статьей также есть интересные комментарии. Повторюсь, что в целом в статье нет ничего нового - кто интересовался, давно знал о всех этих проблемах. Но не так часто выходят хорошие статьи на этот счет. Обычно все обсуждение минусов происходит в комментариях под статьями или в телеграм каналах. https://bessey.dev/blog/2024/05/24/why-im-over-graphql/ #development #graphql #recommended
GraphQL is an incredible piece of technology that has captured a lot of mindshare since I first started slinging it in production in 2018. You won’t have to ...
gap
и почему оно лучше всех предыдущих решений.
Половина статьи посвящена тому, как делались отступы между элементами до gap
и какие проблемы у них были. Например, были сложности с учетом RTL-лэйаутов.
Вторая половина статьи посвящена тому, как gap
решает все этим проблемы. Рекомендую к прочтению
https://ishadeed.com/article/the-gap/
#development #css #gap #recommendedAn exploration of the pain points that CSS gap solves.
describe
+ it
и через test('name', t => {})
descibe
+ it
import { formatFileSize } from "../formatter.js";
import { describe, it } from "node:test";
import assert from "node:assert";
describe("formatFileSize function", () => {
it('should return "1.00 GB" for sizeBytes = 1073741824', () => {
assert.strictEqual(formatFileSize(1073741824), "1.00 GB");
});
});
test
import { formatFileSize } from '../formatter.js';
import { test } from 'node:test';
import assert from 'node:assert';
test('formatFileSize function', (t) => {
t.test('should return "1.00 GB" for sizeBytes = 1073741824', () => {
assert.strictEqual(formatFileSize(1073741824), '1.00 GB');
});
});
Также поддерживается скип тестов и также это можно сделать двумя способами - через .skip
у теста, либо же через проброс skip: true
в опциях теста
import { describe, it } from 'node:test';
import assert from 'node:assert';
import { formatFileSize } from '../formatter.js';
describe('formatFileSize function', () => {
it.skip("should return '0B' for sizeBytes = 0", () => {
assert.strictEqual(formatFileSize(0), '0B');
});
it("should return '1.00 MB' for sizeBytes = 1048576", { skip: true }, () => {
assert.strictEqual(formatFileSize(1048576), '1.00 MB');
});
});
Доступна фильтрация по имени теста. Как в старые добрые времена, можно в имена тестов добавлять типа тэги (#tag
или @tag
) и запускать только тесты с этим тэгом через фильтрацию имени
node --test --test-name-pattern @large
API мокирования в целом похоже на другие подобные API из существующих решений. Судя по статье, пока нет такого же удобного способа на проверку вызовов мока, как в jest - приходится ручками разбирать вызовы мока
import { describe, it, mock } from 'node:test';
import assert from 'node:assert';
import fs from 'node:fs';
// Mocking fs.readFile() method
mock.method(fs.promises, 'readFile', async () => 'Hello World');
describe('Mocking fs.readFile in Node.js', () => {
it('should successfully read the content of a text file', async () => {
assert.strictEqual(fs.promises.readFile.mock.calls.length, 0);
assert.strictEqual(
await fs.promises.readFile('text-content.txt'),
'Hello World'
);
assert.strictEqual(fs.promises.readFile.mock.calls.length, 1);
// Reset the globally tracked mocks.
mock.reset();
});
});
В версии 20.4 добавлена возможность мокирования таймеров
import { describe, it, mock } from 'node:test';
import assert from 'node:assert/strict';
describe('Mocking setTimeout in Node.js', () => {
it('should successfully mock setTimeout', () => {
const fn = mock.fn();
mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(fn, 20);
mock.timers.tick(10);
mock.timers.tick(10);
assert.strictEqual(fn.mock.callCount(), 1);
});
});
Настройка мокирования таймеров достаточно гранулярная: можно настроить отдельно setTimeout
, а можно Date
. Из статьи правда непонятно до конца, насколько это API хорошо работает в реальных приложениях, где промис-чейны могут быть весьма нетривиальны.
Далее в статье описываются хуки (before
), генерация репортов, сбор code coverage.
Из интересного, показывается пример тестирования сервера на fastify
.
Рекомендую к прочтению для ознакомления с API тест-ранера nodejs
https://betterstack.com/community/guides/testing/nodejs-test-runner/
#development #javascript #nodejs #testing #nodejsTestRunnerMaster Node.js testing with this comprehensive guide to its built-in test runner. Learn to write effective tests and manage your application's test suite
performance
. Собственно это API и называется хуками.
Статья объясняет про особенности работы этих хуков (например, про наличие буферов у каждого обсервера).
https://pavel-romanov.com/nodejs-performance-hooks-mastering-the-mental-model
#development #javascript #performance #nodejsMaster Node.js performance hooks: clocks, performance timeline, performance entries, performance observer, and buffers for precise measurement
<h1 id="heading">hello world</h1>;
Он будет скомпилирован в
// output: newer "automatic runtime" transform
import { jsx as _jsx } from "react/runtime";
_jsx("h1", { id: "heading", children: "hello world" });
Но мы же видим, что компонент статичный и его можно скомпилировать сразу в html
const html = '<h1 id="heading">hello world</h1>';
Что мы получаем от такого преобразования: браузеру намного проще работать с обычными строками, чем с вызовами функций и объектами.
Автор развивает мысль дальше и рассказывает, что мы можем предкомпилировать в html статичную верстку и даже верстку с атрибутами и динамичными частями. Но не можем предкомпилировать кастомные компоненты т.к. каждый фреймворк работает с ними по-своему и было бы неверно как-то оптимизировать эту часть. Для такой верстки предкомпилировать не получится и останется тот же вызов JSX, который есть и без оптимизации
В целом это очень старый подход. Первые web-фреймворки примерно так и работали. Также, многие современные фреймворки поддерживают такую оптимизацию (svelte, vue, preact, solid).
Также автор статьи работает в Deno и эта оптимизация там завезена в Deno и может быть включена через конфиг
// deno.json
{
"compilerOptions": {
- "jsx": "react-jsx",
+ "jsx": "precompile",
}
}
Особый лоск этой оптимизации в том, что она работает с любым фреймворком и при этом нет шанса замедлить работу приложения. В худшем случае, если вся верстка состоит из неоптимизируемого JSX, то код останется тем же, что и был
https://marvinh.dev/blog/speeding-up-javascript-ecosystem-part-9/
#development #javascript #performanceWith a JSX transform that is optimized for rendering HTML as quickly as possible on the server, we can make rendering 7-20x faster and cut GC times in half. This JSX transform is generic and not tied to a particular framework.
На вашому тарифі доступна аналітика тільки для 5 каналів. Щоб отримати більше — оберіть інший тариф.