Введение
Последние несколько месяцев ни для кого не были легкими. Я надеюсь, что все и их семьи останутся здоровыми.
Чтобы поддержать новую инициативу компании и снизить затраты на привлечение пользователей, нашу команду инженеров попросили придумать решение для улучшения SEO (обычных результатов поиска).
В идеале мы хотим найти решение, которое поддерживает рендеринг на стороне сервера и обеспечивает достойную производительность в Интернете. Наши существующие приложения создаются как одностраничное приложение, которое обрабатывает всю визуализацию страниц на стороне клиента, а First Contentful Paint выполняется слишком долго из-за большого количества JavaScript, отправляемого в браузеры. Мы решили попробовать Next.js, учитывая, что он обеспечивает рендеринг на стороне сервера из коробки, а SSR должен повысить скорость загрузки страницы за счет снижения нагрузки на браузер. Однако путь не так прост. Я хочу поделиться несколькими проблемами и препятствиями, с которыми я столкнулся при создании нашего приложения Next.js.
Нет окна
Как разработчики, ежедневно работающие с Javascript и браузерами, мы обычно принимаем некоторые вещи как должное. Именно в нашем подсознании window
объект всегда рядом, когда он нам нужен. Это не относится к Next.js. window
является частью веб-API браузеров, а не частью ядра JavaScript. Для SSR Next.js выполняет первоначальный рендеринг на стороне сервера в Node.js, где объект window
недоступен.
Для нашего исходного кода, который использует window
или что-то, что исходит от веб-API, мы проверим, существует ли объект, прежде чем вызывать его.
if (typeof window !== 'undefined') { window.addEventListener('NAV_LOADED', () => handleInitNavData()); window.addEventListener('resize', refreshNavHeight); }
Для компонентов, которые мы хотим визуализировать только на стороне клиента, мы можем использовать Динамический импорт. ssr: false
убедитесь, что компонент не обрабатывается на стороне сервера.
import dynamic from 'next/dynamic'; ... const Footer = dynamic(import('../../components/ui/Footer/Footer'), { ssr: false, });
Вынос
Пакеты из node_module
не могут быть обработаны таким образом. К сожалению, нам придется либо изменить способ использования библиотеки, либо заменить ее новой. Одним из примеров первой ситуации является react-media
, нам пришлось зависеть от пользовательского агента из запроса, чтобы предоставить полунадежное значение по умолчанию, чтобы он знал размер экрана по умолчанию.
Где находится переменная среды
Разве это не просто process.env.MY_THING
? Да, но это еще не все. Next.js предоставляет 3 различных типа переменных окружения.
const globalConfig = { env: { ASSET_PATH: isDevelopment ? '' : 'https://cdn.cloudfront.net/', }, publicRuntimeConfig: { SEGMENT_ID, }, serverRuntimeConfig: { CACHE, }, };
env: заменяет значение на времени сборки. process.env.ASSET_PATH
будет заменено на https://cdn.cloudfront.net/
, когда мы попытаемся сделать производственную сборку.
publicRuntimeConfig & serverRuntimeConfig: есть переменные времени выполнения, хороший пример — Next.js.
import getConfig from 'next/config' // Only holds serverRuntimeConfig and publicRuntimeConfig const { serverRuntimeConfig, publicRuntimeConfig } = getConfig() // Will only be available on the server-side console.log(serverRuntimeConfig.mySecret) // Will be available on both server-side and client-side console.log(publicRuntimeConfig.staticFolder) function MyImage() { return ( <div> <img src={`${publicRuntimeConfig.staticFolder}/logo.png`} alt="logo" /> </div> ) } export default MyImage
Вынос
Помните о том, как мы используем эти переменные и назначаем их в правильные места. Переменные времени сборки будут недоступны во время выполнения. Не раскрывайте больше, чем вам нужно, в общедоступной конфигурации времени выполнения. Зная различия между этими тремя, здравый смысл работает лучше всего.
Нет бесплатных файлов cookie
У меня возникла проблема, когда я начал работать с выборкой данных в приложении Next.js. У меня есть этот код, который делает GET
запрос на получение информации о пользователе. Однако запрос не смог аутентифицировать пользователя в getServerSideProps
.
// Fetch user context async function fetchUser(req: IncomingMessage): Promise<UserContext | null> { let userContext: UserContext | null = null; try { // our custom API helper uses fetch internally userContext = await ApiService.get( `${process.env.WEB_HOST}/web-api/user/get`, {}, // params ); } catch (error) { console.error('Unable to load user context', error); } return userContext; } export const getServerSideProps: GetServerSideProps = async ({ req }) { const userCtx = await fetchUser(req); return { props: { userCtx, }, }; }
Вынос
Мы должны вручную передавать файлы cookie в запрос, который отправляется на наши конечные точки.
Для сервера Next.js:
await ApiService.get( `${process.env.WEB_HOST}/web-api/user/get`, {}, // params { // adding cookie to the new request cookie: req.headers.cookie, } );
Другие вещи
- Глобальную таблицу стилей можно добавить только в
_app.js
. Next.js автоматически использует ограниченный CSS (модуль CSS) для компонентов. Next.js — встроенная поддержка CSS assetPrefix
применяется только к сгенерированным ресурсам (JS, CSS, JSON...), он не оказывает никакого влияния на ресурсы (изображения, шрифты...) в папкеpublic
. Next.js - поддержка CDN- Чтобы лучше организовать наш код, мы можем переместить весь наш исходный код под
src/...
. Next.js - каталог Src
Последние мысли
Нам очень нравится Next.js. Он делает большинство вещей прямо из коробки. Мы уже начали перенос страниц с фокусом на SEO в это новое приложение Next.js, и это было здорово. С другой стороны, мы до сих пор не нашли решения для интеграции в нашу инфраструктуру некоторых функций Next.js, таких как Incremental Static Regeneration. Если вы недавно начали изучать Next.js, как и я, я надеюсь, что этот пост сэкономит вам время и сэкономит время на гугление.
Первоначально опубликовано на https://www.andrew-zheng.com 26 августа 2020 г.