Найти тему
Nuances of programming

Как настроить Next.js на TypeScript, чтобы получить оценку в 100% от Google Lighthouse и Vercel Analytics

Оглавление

Источник: Nuances of Programming

Начнем с создания нового приложения Next.js:

$ yarn create next-app — typescript

В корне проекта Next.js на TypeScript будут созданы файлы next-env.d.ts и tsconfig.json. Файл next-env.d.ts делает так, чтобы типы Next.js были подобраны компилятором TypeScript. Его не нужно удалять или редактировать.

Файл tsconfig.json  —  это пользовательская конфигурация компилятора TypeScript. Если понадобятся дополнительные типы, нужно создать *.d.ts в корне и сослаться на него в массиве include файла tsconfig.json.

Более подробную информацию можно найти в официальной документации.

Добавление файлов favicon

Наведем порядок и добавим подписи к проекту. Например, удалим ненужные компоненты и добавим иконку приложения. favicon.io  —  эффективный инструмент для создания файлов иконок веб-приложений.

public/
├── android-chrome-192x192.png
├── android-chrome-512x512.png
├── apple-touch-icon.png
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon.ico
└── site.webmanifest

Файлы иконок должны быть помещены в общедоступную папку. Также нужно добавить свойства в site.webmanifest, чтобы дополнить его и привести к стандартам прогрессивного веб-приложения.

  • ./public/site.webmanifest:

{
"name": "Next.js 100 - TypeScript",
"app_name": "Next.js 100 - TypeScript",
"short_name": "Next.js 100 - TypeScript",
"description": "Build a PWA to achieve 100% in Google Lighthouse and Next.js Analytics",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/favicon-32x32.png",
"sizes": "32x32",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/favicon-16x16.png",
"sizes": "16x16",
"type": "image/png",
"purpose": "any maskable"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone",
"scope": "/",
"start_url": "/"
}

  • ./pages/_document.tsx:

import { Head, Html, Main, NextScript } from 'next/document'

const Document = () => (
<Html>
<Head>
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<link
href="/favicon-16x16.png"
rel="icon"
type="image/png"
sizes="16x16"
/>
<link
href="/favicon-32x32.png"
rel="icon"
type="image/png"
sizes="32x32"
/>
<link rel="apple-touch-icon" href="/apple-touch-icon.png"></link>

<link rel="manifest" href="/site.webmanifest" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)

export default Document

Когда файлы будут готовы, добавьте метатеги в элемент <head> файла _document.tsx.

manifest.json и site.webmanifest

Согласно w3.org, разработчики могут использовать различные расширения, такие как manifest.json и site.webmanifest. Однако зарегистрированным в системе IANA расширением файла для manifest является .webmanifest. Мы будем использовать site.webmanifest в этом репозитории.

Фото 1. Отчет о производительности от Lighthouse — сборка разработки
Фото 1. Отчет о производительности от Lighthouse — сборка разработки

Производственная сборка  —  это оптимизированная версия приложения. Сгенерированный код в .next компилируется и минифицируется. Обычно производственная версия выкладывается с целью оптимизации производительности.

Фото 2. Отчет о производительности от Lighthouse — производственная сборка
Фото 2. Отчет о производительности от Lighthouse — производственная сборка

Продолжим, чтобы окрасить все оставшиеся показатели отчета в зеленый цвет.

Добавляем метатеги title и description

Исходя из отчета Lighthouse, добавление элементов title и description может улучшить как уровень доступности, так и показатели SEO.

Фото 3. Диагностика от Lighthouse — элемент title
Фото 3. Диагностика от Lighthouse — элемент title
Фото 4. Диагностика от Lighthouse — элемент title и meta description
Фото 4. Диагностика от Lighthouse — элемент title и meta description

В Next.js мы можем разместить метатег description в файле _document.tsx. Однако элемент <title> нужно добавить на каждую страницу.

  • ./pages/_document.tsx:

import { Head, Html, Main, NextScript } from 'next/document'

const Document = () => (
<Html>
<Head>
+ <meta
+ name="description"
+ content="Build a PWA to achieve 100% in Google Lighthouse and Next.js Analytics"
+ />
+
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />

  • ./pages/index.tsx:

import type { NextPage } from 'next'
+ import Head from 'next/head'

const Index: NextPage = () => {
return (
<div>
+ <Head>
+ <title>Next.js 100 - TypeScript</title>
+ </Head>
+
<main>
<h1>Next.js 100 - TypeScript</h1>
</main>

Добавление атрибута lang к элементу HTML

Начиная с версии 10, Next.js поддерживает интернационализированную маршрутизацию. Next.js будет автоматически добавлять атрибут lang в зависимости от языка пользователя.

  • ./next.config.js:

const nextConfig = {
reactStrictMode: true,
+ i18n: {
+ locales: ['en', 'nl'],
+ defaultLocale: 'en',
+ localeDetection: false,
+ },
})

module.exports = nextConfig

Добавим конфигурацию i18n в next.config.js, чтобы указать поддерживаемые языки. Мы увидим, что автоматически определяемый атрибут lang добавлен к элементу HTML.

Фото 5. Отчет о производительности от Lighthouse — все показатели зеленые
Фото 5. Отчет о производительности от Lighthouse — все показатели зеленые

Теперь в отчете от Lighthouse все четыре показателя окрашены в зеленый цвет (100). Тем не менее на кружке PWA все еще видим минус.

Прогрессивное веб-приложение (PWA)

Довольно удобно превратить простое приложение Next.js в прогрессивное веб-приложение, добавив пакет next-pwa:

$ yarn add next-pwa

Импортируйте пакет next-pwa в next.config.js и добавьте конфигурации. Желательно, чтобы service worker не функционировал во время процесса разработки.

  • ./next.config.js:

/** @type {import('next').NextConfig} */
+ const withPWA = require('next-pwa')
+ const runtimeCaching = require('next-pwa/cache')
+
const nextConfig = withPWA({
reactStrictMode: true,
i18n: {
locales: ['en', 'nl'],
defaultLocale: 'en',
localeDetection: false,
},
+ pwa: {
+ disable: process.env.NODE_ENV !== 'production',
+ dest: 'public',
+ runtimeCaching,
+ buildExcludes: [/middleware-manifest.json$/],
+ },
})

module.exports = nextConfig

Для настройки PWA также необходимы метатеги theme-color и referrer.

  • ./pages/_document.tsx:

import { Head, Html, Main, NextScript } from 'next/document'

const Document = () => (
<Html>
<Head>
<meta
name="description"
content="Build a PWA to achieve 100% in Google Lighthouse and Next.js Analytics"
/>
+ <meta name="theme-color" content="#333333" />
+ <meta name="referrer" content={'strict-origin'} />

<link rel="icon" type="image/x-icon" href="/favicon.ico" />

manifest.json и проблема предварительного кэширования

После развертывания в Vercel мы столкнемся с проблемой предварительного кэширования. Поэтому в следующей сборке PWA кэш времени выполнения добавлен, а файл middleware-manifest.json исключен.

После выполнения вышеуказанных манипуляций, магическим образом в кружке PWA в отчете от Lighthouse появляется зеленая галочка!

Фото 6. Отчет о производительности от Lighthouse — все показатели зеленые, включая PWA
Фото 6. Отчет о производительности от Lighthouse — все показатели зеленые, включая PWA

Проверка безопасности

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

Фото 7. Отчет о безопасности с сайта webpagetest.org — оценка безопасности E
Фото 7. Отчет о безопасности с сайта webpagetest.org — оценка безопасности E

По данным webpagetest.org, оценка безопасности находится в группе E. Это означает, что нам предстоит решить ряд проблем.

Фото 8. Диагностика на сайте webpagetest.org —параметр X Content Type Options
Фото 8. Диагностика на сайте webpagetest.org —параметр X Content Type Options
Фото 9. Диагностика на сайте webpagetest.org — параметр X Frame Options
Фото 9. Диагностика на сайте webpagetest.org — параметр X Frame Options
Фото 10. Диагностика на сайте webpagetest.org — параметр X XSS Protection.
Фото 10. Диагностика на сайте webpagetest.org — параметр X XSS Protection.

Добавляем заголовки безопасности

Мы можем исправить эти проблемы, добавив заголовки безопасности в next.config.js:

/** @type {import('next').NextConfig} */
const withPWA = require('next-pwa')
const runtimeCaching = require('next-pwa/cache')

+ const securityHeaders = () => [
+ {
+ key: 'X-Content-Type-Options',
+ value: 'nosniff',
+ },
+ {
+ key: 'X-Frame-Options',
+ value: 'SAMEORIGIN',
+ },
+ {
+ key: 'X-XSS-Protection',
+ value: '1; mode=block',
+ },
+ ]
+
const nextConfig = withPWA({
reactStrictMode: true,
i18n: {
locales: ['en', 'nl'],
defaultLocale: 'en',
localeDetection: false,
},
pwa: {
disable: process.env.NODE_ENV !== 'production',
dest: 'public',
runtimeCaching,
buildExcludes: [/middleware-manifest.json$/],
},
+ async headers() {
+ return [
+ {
+ source: '/:path*',
+ headers: securityHeaders(),
+ },
+ ]
+ },
})

module.exports = nextConfig

Добавляем политику безопасности контента

Для обеспечения политики безопасности контента мы должны добавить vitals.vercel-insights.com для Vercel Analytics:

/** @type {import('next').NextConfig} */
const withPWA = require('next-pwa')
const runtimeCaching = require('next-pwa/cache')

+ const ContentSecurityPolicy = `
+ default-src 'self';
+ script-src 'self';
+ connect-src 'self' vitals.vercel-insights.com;
+ style-src 'self';
+ font-src 'self';
+ `
+
const securityHeaders = () => [
{
key: 'X-Content-Type-Options',
value: 'nosniff',
},
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN',
},
{
key: 'X-XSS-Protection',
value: '1; mode=block',
},
+ {
+ key: 'Content-Security-Policy',
+ value: ContentSecurityPolicy.replace(/\s{2,}/g, ' ').trim(),
+ },
]

Пройдем еще одну проверку на webpagetest.org для получения лучшей оценки.

Фото 11. Отчет о безопасности от webpagetest.org — оценка безопасности A+
Фото 11. Отчет о безопасности от webpagetest.org — оценка безопасности A+

Наконец-то мы получили группу А+ по уровню безопасности.

Vercel Analytics

Google Lighthouse  —  почти стандартный инструмент для проверки основных показателей сайта. Но эта оценка предназначена для одной точки данных. Чтобы оценить веб-показатели с точки зрения реального опыта, нужно воспользоваться Vercel analytics. Этот инструмент позволяет измерять производительность сайта путем сбора метрик при посещении пользователями его страниц.

Фото 12. Включение Vercel Analytics
Фото 12. Включение Vercel Analytics

Настройка Vercel Analytics в Vercel довольно проста, мы просто включаем его на вкладке Analytics целевого проекта.

Фото 13. Отчет о производительности от Vercel Analytics
Фото 13. Отчет о производительности от Vercel Analytics

Поскольку Vercel Analytics собирает показатели производительности по мере посещения пользователями сайта, нужно зайти на страницу несколько раз, прежде чем данные появятся на дашборде.

Вывод

В этой статье мы проследили весь путь создания прогрессивного веб-приложения с Next.js и получения 100-процентного результата от Google Lighthouse, Next.js Analytics и уровня безопасности A+ на webpagetest.org. Надеюсь, этот материал послужит трамплином для ваших потрясающих проектов!

Исходный код можно найти в этом репозитории.

Читайте также:

Читайте нас в Telegram, VK

Перевод статьи Rocky Li: How to Set Up Next.js with TypeScript to Get a 100% Score in Google Lighthouse and Vercel Analytics