Этот пост является частью серии о Next.js и Netlify. Первую часть вы можете прочитать здесь.

Проблема со стандартной стратегией именования файлов Next.js:

Next.js по умолчанию создает случайную строку из 21 символа для каждой сборки с использованием наноида. Это полезно в том смысле, что все ваши активы будут иметь один и тот же префикс в одном развертывании.

Next.js сохраняет значение buildId в файле BUILD_ID в папке /.next, чтобы определить, какие файлы ресурсов следует обслуживать.

Эта стратегия также подразумевает, что каждый актив в каждом развертывании будет иметь свой собственный уникальный URL-адрес, а новые URL-адреса будут создаваться при каждом развертывании. Теперь, поскольку никакое содержимое файла не будет перезаписано каким-либо будущим развертыванием, мы можем предположить, что содержимое файла будет неизменным и может кэшироваться на неопределенный срок с помощью CDN и браузеров. Вы можете сообщить браузерам, что содержимое URL-адреса неизменяемо, используя высокий заголовок HTTP max-age. Браузер даже не будет запрашивать такой актив, если он есть в его кеше. Это также может помочь уменьшить проблемы с недействительностью кеша в браузере, потому что содержимое неизменяемо, вам никогда не нужно аннулировать кеш, браузеры автоматически удаляют наименее используемые ресурсы.

Вы можете прочитать больше о передовых методах кэширования и ошибках, связанных с максимальным возрастом, из этой статьи Джейка Арчибальда.



Но это означает, что при каждом развертывании вы будете изменять каждый файл (включая файлы HTML, поскольку они ссылаются на имена файлов JS). Это может привести к увеличению времени развертывания и переполнению кеша в браузерах пользователя, даже если содержимое файла не изменилось. Таким образом, Netlify не рекомендует использовать кеш с большим максимальным возрастом.



Вы можете повторно использовать то же имя файла и получить лучшие результаты через Edge CDN Netlify. Netlify устанавливает заголовки для актива примерно так:

Эти заголовки сообщают браузеру, что он может кэшировать контент на неопределенный срок, но каждый раз перед его использованием он должен один раз проверить с сервером ссылку etag. Браузер сделает запрос с этим тегом в заголовках запроса. Если содержимое не изменилось, сервер ответит кодом состояния 304. И эти запросы выполняются очень быстро, когда обслуживаются CDN.

Подробнее о кешировании Netlify здесь:



Итак, прежде чем мы примем стратегию по умолчанию, давайте рассмотрим еще несколько стратегий:

Одинаковые имена файлов при сборке / развертывании:

Теперь мы не хотим, чтобы URL-адреса менялись каждый раз. Что, если мы установим для buildId постоянное значение? Это кажется хорошей стратегией, если вы не добавляете нигде еще один уровень кеширования, который нужно сделать недействительным. то есть единственное кеширование выполняется Netlify и встроенным механизмом кеширования вашего браузера. Для каждого ресурса, который запрашивается вашей страницей, браузер будет делать запрос на сервер, чтобы убедиться, что то, что у него в кеше, все еще актуально и применимо. Вы можете добиться этого, установив для buildId постоянное значение. (Через generateBuildId)

Но есть большая проблема, которую нам нужно понять, чтобы понять, как маршрутизатор работает в настоящее время:

Next.js определяет путь к активу маршрута, используя это:

`/_next/static/${buildId}/${route}.js

Что произойдет, если пользователь откроет ваш веб-сайт во вкладке браузера, пока вы запускаете новое развертывание? Если он щелкнет ссылку, Next.js запросит актив, который, поскольку buildId является постоянным, будет из нового развертывания, и попытается использовать его для визуализации нового маршрута. Это может работать или не работать в зависимости от того, что вы изменили в своем новом развертывании. Если к общему пакету добавляется зависимость от поставщика, а ресурс этого нового маршрута требует, это вызовет ошибку, поскольку мы не перезагружаем пакет общего поставщика.

Поэтому, если вы собираетесь создать более одной страницы со ссылками друг на друга с помощью маршрутизации на стороне клиента, не используйте эту стратегию с Next.js. Вы все равно можете используйте эту стратегию с другими фреймворками, которые не имеют такой маршрутизации на стороне клиента при развертывании в Netlify. Или отключите маршрутизацию на стороне клиента и заставьте сервер отвечать на все маршруты.

Хеш содержимого md5 / sha включен в имя файла:

Здесь для каждого созданного объекта был сохранен хэш в имени файла. Любые изменения, которые вы вносите в исходный код, изменяют имя файла ресурса, в который он, наконец, входит. Если, скажем, вы изменяете исходный код файла, который влияет только на один маршрут, и вы убедились, что файл не импортируется в ваш _app.js, тогда и только тогда путь к активу этой страницы будет изменен, а путь к активу других страниц останется прежним. . По сути, каждый хеш будет указывать на одну версию кода и может считаться неизменным. Итак, теперь вы можете использовать долгосрочное кеширование, и браузеру никогда не придется запрашивать один и тот же актив дважды.

Таким образом, теперь вместо использования стратегии Next.js по умолчанию, заключающейся в том, чтобы каждый раз менять все пути и никогда не менять ни одного пути, это дает идеальную золотую середину, когда путь к активу изменяется только тогда, когда изменяется его содержимое.

Способ добиться этого непростой и лишенный благословения разработчиков Next.js, так что ожидайте, что это сломается в будущих версиях Next.js. Но тем не менее с версией 8.0.3 для этого вам необходимо сделать следующее:

  1. Измените функцию имени файла в конфигурации Webpack, чтобы создать ресурсы на стороне клиента с хешем содержимого в имени файла. (Посмотреть здесь".)
  2. Вам нужно будет где-то сохранить эти хэши контента, поэтому создайте плагин Webpack, который создает файл JSON, в котором хранится сопоставление маршрута с хешем контента, то есть путь к активу. (Посмотреть здесь".)
  3. Используйте этот JSON во время сборки для создания тегов <script> в части рендеринга на стороне сервера (т.е. в pages/_document.js в компоненте NextScript) (см. Здесь.)
  4. Когда пользователь щелкает ссылку, ваш клиентский маршрутизатор должен запросить правильный путь к активу, сопоставленный с маршрутом, на который пользователь запрашивает переход. Это включает в себя патч Monkey для PageLoader, чтобы генерировать пути к ресурсам, используя отображение, которое вы строите на шаге 2. Вы сможете это сделать, потому что Next.js в настоящее время не искажает реквизиты. (Посмотреть здесь".)
  5. Вам необходимо убедиться, что вы обслуживаете старые и новые активы с помощью Netlify. то есть сохранять файлы между сборками, а также сохранять файл records.json из Webpack. (Скоро появится в более позднем сообщении в блоге)

Вы можете взглянуть на этот PR, который охватывает все вышеперечисленное.

(Примечание: это то, что я люблю и ненавижу в Javascript прямо сейчас, я могу изменить метод класса вне библиотеки. Это будет невозможно, когда появится предложение о частных полях и методах и библиотеки начнут его использовать. .)

Заключение

Подпишитесь на Github Issues, чтобы быть в курсе решений:

Если вы разрабатываете проверенный и готовый к эксплуатации сервис для своей компании или клиента, у которого вы не хотите оставлять никаких технических долгов, используйте стратегию Next.js по умолчанию.

Если вы создаете свой собственный сайт-портфолио (я 😅), для которого вы можете позволить себе поэкспериментировать и хотите добиться максимальной производительности с Next.js + Netlify, используйте стратегию хеширования контента. Также не забудьте оставить ссылку на это сообщение в блоге в исходном коде, чтобы вы могли ссылаться на него в будущем.

Обновление: 15 мая 2019 г.: существует RFC для Next.js, который не требует от нас реализации решения, представленного в этом блоге. Подпишитесь здесь.

Обновление от 10 августа 2019 г.: вышеупомянутый RFC был удален, поскольку при возврате компонента из обработчика будут проблемы с кешированием.

Что дальше:

Итак, это пара блогов, которые я собираюсь написать на Next.js + Netlify.

  1. "Вступление"
  2. Стратегии именования файлов и кэширования (эта)
  3. … (Скоро будет больше, когда у меня будет время написать их 😅)

Я пишу эти сообщения по мере того, как учусь, строя свой блог. Следуйте за мной, чтобы получать уведомления, когда они будут готовы. Рекомендую (👏) это, если эта статья помогла вам начать работу с Next.js или помогла улучшить настройку Next.js.