Стартовый шаблон Next.js + MUI5 + TypeScript

Очень часто при старте проекта необходимо выбрать набор инструментов, которые значительно упрощают разработку и, которые можно в дальнейшем использовать и в других проектах.

Вадим Пашаев

Вадим Пашаев

12/12/2021

Стартовый шаблон Next.js + MUI5 + TypeScript

И здесь встает вопрос, а будут ли они работать вместе должным образом.

Итак, какие задачи перед нами стоят:

  • Обеспечить стабильную сборку для быстрого создания новых проектов и прототипирования;
  • Обеспечить статическую типизацию и проверку типов для улучшения качества кода;
  • Перейти на новый Material UI 5, который претерпел очень много полезных изменений по сравнению с 4 версией (который для нашей студии уже стал стандартом, де-факто);

В этой статье мы соберем с вами сборку на Next.js + MUI5 + TypeScript.

Cвязка React+Typescript давно уже стала самой популярная для создания клиентских приложений. Их в своих проектах уже используют следующие бренды: Yandex, Тинькофф, ВК, Avito, Сбербанк, Контур, Netflix, Instagram, Pinterest, AirBNB и другие крупные компании.

Next.js

Next.js — это основанный на React фреймворк, предназначенный для разработки веб-приложений, обладающих функционалом, выходящим за рамки SPA, т.е. так называемых одностраничных приложений. Известно, что основным недостатком одностраничных приложений или SPA являются проблемы с индексацией страниц таких приложений поисковыми роботами, что негативно влияет на SEO.

TypeScript

TypeScript (далее TS) - это надстройка над JavaScript (далее JS), которая добавляет статическую типизацию и еще кучу полезных фишек в нативный JS, старается исправить большинство недочетов и предоставляет нам мощнейшие иструменты для улучшения качества кода. Про все достоинства и недостатки TS подробнее можно почитать в других статьях. Например, здесь.

Наиболее распространенными ошибками, совершаемыми JavaScript-разработчиками, являются ошибки вида, когда вместо ожидаемого значения используется неправильное. Это может быть связано с простыми опечатками, непониманием интерфейса используемой библиотеки, неверными предположениями о поведении кода во время выполнения и т.д. Цель TypeScript - осуществлять проверку типов значений, используемых в программе, написанной на JavaScript. TypeScript - это инструмент, который выполняет свою работу до запуска кода (поэтому его называют статическим) и обеспечивает использование приложением значений правильных типов.

О том, что дает нам TypeScript в React можно подробнее прочитать здесь.

MUI5 (MaterialUI 5)

MUI - это довольно надежная, настраиваемая и доступная библиотека базовых и расширенных компонентов, позволяющая создавать собственную систему дизайна и быстрее разрабатывать приложения на React.

Собираем шаблон

1. Установка Next.js и TypeScript

Для начала сборки нам потребуется создать шаблонный проект на Next.js + Typescript. Next.js поддерживает TypeScript из коробки, поэтому все, что нам нужно сделать на этом этапе, это набрать в консоли:

yarn create next-app --typescript

Где флаг --typescript как раз указывает на создание проекта с надстройкой TypeScript.

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

2. Установка MUI

С установкой MaterialUI-5 все немного сложнее ;)

Для начала в проект устанавливаем следующие пакеты:

yarn add @emotion/cache @emotion/react @emotion/server @emotion/styled @mui/icons-material @mui/material

3. Редактируем файл _app.js

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

  1. Сохранение частей макета при переключении между страницами;
  2. Сохранение состояния при навигации по страницам;
  3. Пользовательская обработка ошибок;
  4. Встраивание дополнительных данных на страницу;
  5. Добавление глобальных CSS-стилей.

Что нужно сделать?

Идем в документацию Next.js и открываем раздел Advanced Features/Custom App. Копируем оттуда весь код и создаем файл _app.js в папке /pages

// import App from 'next/app'

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

// Only uncomment this method if you have blocking data requirements for
// every single page in your application. This disables the ability to
// perform automatic static optimization, causing every page in your app to
// be server-side rendered.
//
// MyApp.getInitialProps = async (appContext) => {
//   // calls page's `getInitialProps` and fills `appProps.pageProps`
//   const appProps = await App.getInitialProps(appContext);
//
//   return { ...appProps }
// }

export default MyApp

После этого необходимо добавить несколько изменений в файл _app.js

import Head from 'next/head'
import type { AppProps } from 'next/app'
import { ThemeProvider } from '@mui/material/styles'
import { CssBaseline } from '@mui/material'
import { CacheProvider, EmotionCache } from '@emotion/react'
import theme from '../styles/theme'
import createEmotionCache from '../utils/createEmotionCache'

const clientSideEmotionCache = createEmotionCache()

interface MyAppProps extends AppProps {
  emotionCache?: EmotionCache
}

export default function MyApp({ Component, emotionCache = clientSideEmotionCache, pageProps }: MyAppProps) {
  return (
    <CacheProvider value={emotionCache}>
      <Head>
        <title>Change title in _app.tsx</title>
        <meta name="viewport" content='initial-scale=1, width=device-width' />
      </Head>
      <ThemeProvider theme={theme}>
        <CssBaseline />
        <Component {...pageProps} />
      </ThemeProvider>
    </CacheProvider>
  )
}

4. Добавляем файл _document.js

Файл _document.js в Next.js обычно используется для дополнения тегов <html> и <body> вашего приложения. Это необходимо, потому, что страницы Next.js пропускают определение разметки окружающего документа.

Создаем в папке /pages файл _document.js. И вписываем сюда следующий код.

import React from 'react'
import Document, { Html, Head, NextScript, Main } from "next/document"
import createEmotionServer from "@emotion/server/create-instance"
import theme from '../styles/theme'
import createEmotionCache from "../utils/createEmotionCache"

export default class MyDocument extends Document {
  render() {
    return (
      <Html lang="ru">
        <Head>
          <meta name="theme-color" content={theme.palette.primary.main} />
          <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
          <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

MyDocument.getInitialProps = async (ctx) => {
  const originalRenderPage = ctx.renderPage

  const cache = createEmotionCache()

  const { extractCriticalToChunks } = createEmotionServer(cache)

  ctx.renderPage = () => originalRenderPage({
    enhanceApp: (App: any) => function EnhanceApp(props) {
      return <App emotionCache={cache} {...props} />
    }
  })

  const initialProps = await Document.getInitialProps(ctx)

  const emotionStyles = extractCriticalToChunks(initialProps.html)
  const emotionStyleTags = emotionStyles.styles.map(style => (
    <style
      data-emotion={`${style.key} ${style.ids.join(' ')}`}
      key={style.key}
      dangerouslySetInnerHTML={{ __html: style.css }}
    />
  ))

  return {
    ...initialProps,
    styles: [...React.Children.toArray(initialProps.styles), ...emotionStyleTags]
  }
}

5. Пишем первую страницу на MaterialUI 5

import { Link, Typography } from '@mui/material'
import { NextPage } from 'next'
import NextLink from 'next/link'
import Layout from '../components/Layout'

const HomePage: NextPage = () => {
  return (
    <Layout title="Главная | Next.js + TypeScript Example">
      <Typography component="h1" variant='h1'>Привет, Next.js 👋</Typography>
      <Typography>
        <NextLink href="/about" passHref>
          <Link>О нас</Link>
        </NextLink>
      </Typography>
    </Layout>
  )
}

export default HomePage

Все на этом туториал завершен. Код можно найти на Github

Подписаться на рассылку

Получите лучший маркетинговый контент недели

Подписаться на рассылку

Получите лучший маркетинговый контент недели

Оценка проекта

Хотите быструю оценку Вашего проекта?

Заполните эту форму для получения бесплатной оценки вашей идеи или задачи.

Есть интересная идея?

И вы очень хотите ее реализовать, пишите нам и получите подробное коммерческое предложение и быструю реализацию