Next.js 시작해보자 2/5 - Assets, Metadata, and CSS

2020-10-10 — Written by jslee
#nextjs#react framework#assets#metadata#css

목록

  • Next.js에서는 CSS, Sass를 지원한다.
  • images, videos를 어떻게 Next.js에 추가하는지
  • 각 페이지의 <head>를 어떻게 customize 하는지
  • CSS Modules을 사용해서 reusable React component를 만드는지
  • global CSS 추가하는 방법
  • 유용한 styling

Assets

https://nextjs.org/learn/basics/assets-metadata-css/assets

이미지와 같은 static assets을 추가하기 위해서는 public에 추가하면 된다. public/vercel.svg를 추가하고 사용하고자 하는 페이지에 아래와 같이 코드를 추가하면 된다.

<img src="/vercel.svg" alt="Vercel Logo" className="logo" />

추가로 public에는 robots.txt, Google Site Verification 을 추가해서 사용할수 있는 폴더이다.

Metadata

https://nextjs.org/learn/basics/assets-metadata-css/metadata

<title>과 같은 HTML tag의 metadata를 수정하고 싶을때는 아래와 같이 사용해보자. <head>가 아닌 <Head>를 사용해야 한다. <Head>Next.js의 head 모듈을 추가해서 사용이 가능하다.

import Head from "next/head"
import Link from "next/link"

export default function FirstPost() {
  return (
    <>
      <Head>
        <title>First Post</title>
      </Head>
      <h1>First Post</h1>
      <Link href="/">
        <a>Back to home</a>
      </Link>
    </>
  )
}

CSS Styling

https://nextjs.org/learn/basics/assets-metadata-css/css-styling

styled-jsx의 library를 사용해서 스타일링을 할 수 있다. CSS-in-JS 라이브러리는 React Component에서 CSS로 작성이 가능하도록 (다른 컴포넌트는 영향을 받지 않는다.)

Next.jsstyled-jsx, CSS-in-JS인 styled-components, emotion, Tailwaind CSS를 사용한다.

Layout Component

https://nextjs.org/learn/basics/assets-metadata-css/layout-component

Layout 컴포넌트를 생성해서 가장 바깥쪽 컴포넌트를 만들수 있다.

// components/layout.js
export default function Layout({ children }) {
  return <div>{children}</div>
}

// pages/posts/first-post.js
import Head from "next/head"
import Link from "next/link"
import Layout from "../../components/layout"

export default function FirstPost() {
  return (
    <Layout>
      <Head>
        <title>First Post</title>
      </Head>
      <h1>First Post</h1>
      <h2>
        <Link href="/">
          <a>Back to home</a>
        </Link>
      </h2>
    </Layout>
  )
}

Adding CSS 이전
Adding CSS 이전

Adding CSS

Layout의 컴포넌트를 구성했다면 CSS Modules을 이용해서 스타일링을 추가할 수 있다.

CSS Modules을 사용하기 위해서는 반드시 파일의 이름이 .module.css

/* layout.mmodules.css */
.container {
  max-width: 36rem;
  padding: 0 1rem;
  margin: 3rem auto 6rem;
  background: black;
}
import styles from "./layout.module.css"

export default function Layout({ children }) {
  return <div className={styles.container}>{children}</div>
}

Adding CSS 이후
Adding CSS 이후

CSS Module은 자동으로 uqniue class names을 생성해준다. 또한 Next.js의 code splitting features은 CSS Module에서도 작동을 한다. (각 페이지에서 최소한의 CSS가 로드되도록, 결과적으로 번들 크기가 작아진다. = 빠르다)

Global Styles

https://nextjs.org/learn/basics/assets-metadata-css/global-styles

CSS Modules은 component-level sytles에 유용하다. 그러나 모든 페이지에서 일부 CSS를 로드하려면 Next.js에서도 지원을 한다. global CSS 파일들을 로드하기 위해서는 _app.jspages의 아래에 추가하면 된다.

export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />
}

App 컴포넌트는 top-level component로 모든 다른 페이지에서 공통적으로 사용. 해당 컴포넌트를 사용해서 페이지 사이를 이동할때 상태 유지가 가능하다.

pages/_app.js를 추가할때는 반드시 서버를 재시작 해야한다.

Adding Global CSS

pages/_app.js를 제외하고 다른곳에서는 global CSS를 어디서도 가져올수 없으니 반드시 pages/_app.js를 사용하자. 이렇게 막아놓은 이유는 전역 CSS가 페이지의 모든 요소에 영향을 주기 때문이다.

styles의 디렉토리를 생성하고 global.css를 그 안에 생성하자.

/* styles/global.css */

html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
    Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  line-height: 1.6;
  font-size: 18px;
}

* {
  box-sizing: border-box;
}

a {
  color: #0070f3;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

img {
  max-width: 100%;
  display: block;
}

마지막으로 ppages/_app.js에 아래와 같이 추가하면 끝

import "../styles/global.css"

export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />
}

adding global css
adding global css

Polishing Layout

https://nextjs.org/learn/basics/assets-metadata-css/polishing-layout

간단한 CSS Modules과 React 코드로 간단하게 구현을 해봤는데 data fetching을 하기 전에 page styling과 코드를 세련되게 해보자 (=polishing layout)

polishing layout 최종 화면
polishing layout 최종 화면

Download Your Profile Picture

Update components/layout.module.css

.container {
  max-width: 36rem;
  padding: 0 1rem;
  margin: 3rem auto 6rem;
}

.header {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.headerImage {
  width: 6rem;
  height: 6rem;
}

.headerHomeImage {
  width: 8rem;
  height: 8rem;
}

.backToHome {
  margin: 3rem 0 0;
}

Create styles/utils.module.css

.heading2Xl {
  font-size: 2.5rem;
  line-height: 1.2;
  font-weight: 800;
  letter-spacing: -0.05rem;
  margin: 1rem 0;
}

.headingXl {
  font-size: 2rem;
  line-height: 1.3;
  font-weight: 800;
  letter-spacing: -0.05rem;
  margin: 1rem 0;
}

.headingLg {
  font-size: 1.5rem;
  line-height: 1.4;
  margin: 1rem 0;
}

.headingMd {
  font-size: 1.2rem;
  line-height: 1.5;
}

.borderCircle {
  border-radius: 9999px;
}

.colorInherit {
  color: inherit;
}

.padding1px {
  padding-top: 1px;
}

.list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.listItem {
  margin: 0 0 1.25rem;
}

.lightText {
  color: #999;
}

Update components/layout.js

import Head from "next/head"
import styles from "./layout.module.css"
import utilStyles from "../styles/utils.module.css"
import Link from "next/link"

const name = "Your Name"
export const siteTitle = "Next.js Sample Website"

export default function Layout({ children, home }) {
  return (
    <div className={styles.container}>
      <Head>
        <link rel="icon" href="/favicon.ico" />
        <meta
          name="description"
          content="Learn how to build a personal website using Next.js"
        />
        <meta
          property="og:image"
          content={`https://og-image.now.sh/${encodeURI(
            siteTitle
          )}.png?theme=light&md=0&fontSize=75px&images=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Ffront%2Fassets%2Fdesign%2Fnextjs-black-logo.svg`}
        />
        <meta name="og:title" content={siteTitle} />
        <meta name="twitter:card" content="summary_large_image" />
      </Head>
      <header className={styles.header}>
        {home ? (
          <>
            <img
              src="/images/profile.jpg"
              className={`${styles.headerHomeImage} ${utilStyles.borderCircle}`}
              alt={name}
            />
            <h1 className={utilStyles.heading2Xl}>{name}</h1>
          </>
        ) : (
          <>
            <Link href="/">
              <a>
                <img
                  src="/images/profile.jpg"
                  className={`${styles.headerImage} ${utilStyles.borderCircle}`}
                  alt={name}
                />
              </a>
            </Link>
            <h2 className={utilStyles.headingLg}>
              <Link href="/">
                <a className={utilStyles.colorInherit}>{name}</a>
              </Link>
            </h2>
          </>
        )}
      </header>
      <main>{children}</main>
      {!home && (
        <div className={styles.backToHome}>
          <Link href="/">
            <a>← Back to home</a>
          </Link>
        </div>
      )}
    </div>
  )
}

Update pages/index.js

import Head from "next/head"
import Layout, { siteTitle } from "../components/layout"
import utilStyles from "../styles/utils.module.css"

export default function Home() {
  return (
    <Layout home>
      <Head>
        <title>{siteTitle}</title>
      </Head>
      <section className={utilStyles.headingMd}>
        <p>[Your Self Introduction]</p>
        <p>
          (This is a sample website - you’ll be building a site like this on{" "}
          <a href="https://nextjs.org/learn">our Next.js tutorial</a>.)
        </p>
      </section>
    </Layout>
  )
}

Styling

https://nextjs.org/learn/basics/assets-metadata-css/styling-tips

styling tips!

Using classnames library to toggle classes

classnames을 쉽게 전환 할 수 있는 간단한 라이브러리로 yarn add classnames로 설치가 가능하다.

.success {
  color: green;
}
.error {
  color: red;
}

위를 classnames을 사용하면

import styles from "./alert.module.css"
import cn from "classnames"

export default function Alert({ children, type }) {
  return (
    <div
      className={cn({
        [styles.success]: type === "success",
        [styles.error]: type === "error",
      })}
    >
      {children}
    </div>
  )
}

Customizing PostCSS Config

configuration 없이 바로 사용할수 있는 Next.jspostcss를 사용하여 CSS를 컴파일 합니다. PostCSS conifg를 커스터마ㅇ이즈 하기 위해서는 postcss.config.js를 생성하면 된다. Tailwind CSS와 같은 라이브러리를 사용하는 경우 유용하다.

아래와 같이관련된 패키지를 설치하고

npm install tailwindcss postcss-preset-env postcss-flexbugs-fixes

postcss.config.js를 아래와 같이 작성한다

module.exports = {
  plugins: [
    "tailwindcss",
    "postcss-flexbugs-fixes",
    [
      "postcss-preset-env",
      {
        autoprefixer: {
          flexbox: "no-2009",
        },
        stage: 3,
        features: {
          "custom-properties": false,
        },
      },
    ],
  ],
}

tailwind.config.js에서 purge를 이용해 사용하지 않는 CSS는 제거를 한다.

// tailwind.config.js
module.exports = {
  purge: [
    // Use *.tsx if using TypeScript
    "./pages/**/*.js",
    "./components/**/*.js",
  ],
  // ...
}

Using Sass

Sass도 역시 임포트가 가능하다. CSS Modules을 통해 component-level Sass를 사용할 수 있다.

npm install sass
@doubly