Я использовал AC3 в течение месяца, вот что я узнал

Я использую платформу Apollo уже почти два года. Я использовал его в нескольких коммерческих приложениях, и он стал одним из моих самых любимых фреймворков.
В связи с предстоящим выпуском Apollo Client 3 я подумал, что это отличное время, чтобы протестировать последнюю бета-версию и написать о некоторых захватывающих улучшениях, которые меня больше всего волнуют.
Что нового
Вы, наверное, слышали старую шутливую фразу, приписываемую инженеру Netscape Филу Карлтону: «В компьютерных науках есть только две сложные вещи: инвалидация кеша и именование вещей». Фраза уже устарела, в компьютерных науках есть много сложных вещей, но инвалидация кеша действительно очень сложная задача.
В Apollo Client уже много лет используется мощная нормализованная система кэширования, но в предыдущих версиях практически не было инвалидации кеша (что очень полезно в некоторых сценариях). В отсутствие этого пользователи прибегали к хакерским решениям, таким как сброс всего хранилища или даже прямое управление кешем, что могло привести к любому количеству неожиданных проблем.
Apollo Client 3 имеет множество улучшений кеша, включая, помимо прочего, аннулирование, сборку мусора и вытеснение кеша. В версии 3.0 все результаты кеширования теперь заморожены / неизменяемы, и в нем представлен новый декларативный API для управления политиками типов и объектами полей с инструментами для хирургического манипулирования кешем в памяти.
В этой статье я поделюсь своим опытом с моими любимыми частями:
- Новые API политик типов и полей
- Изменение кеша на месте с помощью cache.modify
- Сбор и удаление мусора с помощью cache.evict / cache.gc
Если вы еще этого не сделали, ознакомьтесь с прекрасной статьей Хью Уилсона Предварительный просмотр кэша Apollo Client 3, чтобы получить отличное введение в улучшения кеша Apollo Client 3.0.
Тип и API политики полей
Вы можете настроить способ чтения и записи отдельных полей в кэше Apollo Client. Для этого вы определяете объект
FieldPolicyдля данного поля. Вы вкладываетеFieldPolicyобъект в любойTypePolicyобъект, соответствующий типу, содержащему поле.
Политики типов могут заменять dataIdFromObject, директиву @connection и cacheRedirects.
Вот пример реализации inMemoryCache с объектами typePolicies, fieldPolicy и сгенерированным possibleTypes:
В бета-документации для Apollo Client 3 появился новый раздел, озаглавленный Настройка поведения кэшированных полей, в котором объясняются некоторые новые функции объекта политики поля:
Функция чтения:
Если вы определяете
readфункцию для поля, кеш вызывает эту функцию всякий раз, когда ваш клиент запрашивает поле. В ответе на запрос поле заполняется значением, возвращаемым функциейread, вместо кэшированного значения поля.
Чтение полезно для управления значениями, когда они считываются из кеша, например, такими вещами, как строки форматирования, даты и т. д. Вы также можете использовать его для реализации виртуальных полей. Это очень мощно, если учесть местное государственное управление.
Эта функция также может быть полезна при разработке схемы. Рассмотрим сценарий, в котором вы хотите добавить новое поле в свой API, которое не будет готово в течение нескольких недель - вы можете реализовать временное виртуальное поле, чтобы разблокировать себя.
Функция слияния:
Если вы определяете функцию
mergeдля поля, кеш вызывает эту функцию всякий раз, когда в поле собирается записать входящее значение (например, ответ от успешной мутации через ваш сервер GraphQL). Когда происходит запись, новое значение поля устанавливается на значение, возвращаемое функциейmerge, вместо исходного входящего значения.
Слияние может принимать входящие данные и манипулировать ими перед объединением с существующими данными. Предположим, вы хотите объединить массивы или ненормализованные объекты. Вы также можете использовать его для обработки логики разбивки на страницы.
Эти новые функции политики полей более декларативны и позволяют централизовать вашу логику. Вы также можете создать многоразовые политики полей, например, вы можете написать многоразовые политики разбивки на страницы.
Рассмотрим этот пример из бета-документации Apollo Client 3:
Если вы можете разделить свою логику и создать ее только один раз, будет намного проще поддерживать сложный граф узлов.
В Apollo Client 2.0 комбинацияFragmentMatcher, HeuristicFragmentMatcher и IntrospectionFragmentMatcher использовалась для определения, какой объект принадлежит какому фрагменту.
В AC3 все они были удалены. Сегодня в AC3 InMemoryCache содержит свойство possibleTypes, которое заменяет всю предыдущую сложность.
const cache = new InMemoryCache({
possibleTypes: {
Character: ["Jedi", "Droid"],
Test: ["PassingTest", "FailingTest", "SkippedTest"],
Snake: ["Viper", "Python"],
},
});
См. possibleTypes документацию для получения дополнительной информации о том, как это работает.
cache.modify
Я играл с этим новым методом в течение нескольких дней, и это, вероятно, моя любимая функция в Apollo Client 3. Он позволяет вам изменять кеш на месте вместо того, чтобы использовать readData для анализа того, что вы хотите изменить, а затем писать его обратно в кеш с writeData.
Поскольку cache.modify также можно использовать для удаления полей, это делает writeData в значительной степени избыточным. previousResult больше не является важным фактором.
Устранение
writeDataявляется одним из этапов выпуска Apollo Client 3.0.
Я всегда находил, что манипулирование кешем с помощью обновлений мутаций немного обременительно. Может быть сложно извлечь данные, которые нужно переписать, но, вдобавок ко всему, может быть сложно решить, где разместить свою логику.
Никогда не казалось правильным размещать мой код кеша внутри контейнеров, например, помещать обновление кеша в контейнер кнопки. Что делать, если мне нужна та же политика обновления кеша в другом месте? Например, если у меня есть кнопка «удалить категорию» на странице сведений, и мне нужна такая же функция удаления категории в списке категорий, это может означать введение повторяющейся логики.
Чтобы избежать дублирования, я раньше начал оборачивать свои useQuery крючки внутри пользовательских крючков. С новым API политик типов и полей код для управления кешем хранится в одном месте 🏆.
Чтобы проиллюстрировать, что я имею в виду, взгляните на эти примеры.
До:
После:
Обратите внимание, что мне не нужно сначала читать категории? cache.evict полностью удаляет элемент из кеша и, используя его в функции обновления мутации, передает изменения, чтобы мои компоненты React отражали изменения.
Вот еще один пример, на этот раз с использованием ссылки для удаления карточки из категории.
В этом примере я обновляю соединение и пересчитываю pageInfo, поэтому исключение здесь нецелесообразно, поэтому использованиеmodify здесь является большим улучшением по сравнению с исходной логикой. В Apollo Client 2.0 вам нужно будет извлечь исходную информацию о странице, прежде чем вы сможете ее изменить. Это намного приятнее.
Вот пример использования cache.evict для удаления поля:
cache.evict(id, 'fieldNameToDelete')
Вы также можете использовать cache.modify для удаления поля, но вызов cache.evict короче и проще.
cache.identify можно использовать для получения ссылки на кеш для данного объекта, например, если у вас есть следующий объект:
Звонок cache.identify(cuckoosCallingBook) вернет Book:031648637x.
Вы можете использовать это вместе с cache.modify, чтобы идентифицировать кэшированные записи, которыми нужно манипулировать.
cache.evict / cache.gc
Существуют сценарии, в которых вам нужен лучший доступ к кешу, например, когда вам нужно очистить кешированные данные, чтобы избежать их повторного чтения другими функциями. AC3 предоставляет возможность удалять данные из кеша в памяти.
Используя метод cache.evict, вы можете удалить любой нормализованный объект из кеша (существуют также методы retain и release для хранения и освобождения объектов кеша).
cache.gc удаляет из нормализованного кэша все недостижимые объекты (сборка мусора). Он недоступен для функции обновления мутации, но вам не нужно часто вызывать эту функцию.
Заключение
Apollo Client 3.0 выглядит великолепно. Кэш всегда был одной из самых сильных сторон Apollo, а версия 3.0 - значительное улучшение.
Он упрощает и решает многие существующие проблемы, особенно недействительность кеша, которая была очень востребованной функцией.
API-интерфейсы политик типов и полей AC3 упрощают написание логики многократно используемого кеша, упрощают изменение кеша, являются более декларативными, эффективными и требуют меньше кода.
Удалять вещи из кеша теперь легко с evict, и есть несколько новых мощных инструментов для управления кешем (modify, identify, gc, read и merge).
Я с нетерпением жду финальной версии Apollo Client 3.0 в конце этого года. Большое спасибо команде Apollo и Халилу Стеммлеру за помощь в написании статьи!
Ресурсы
Журнал изменений Apollo Client 3.0
Бета-документация Apollo Client 3.0