Next.js 시작해보자 2/5 - Assets, Metadata, and 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.js
는 styled-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
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>
}
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.js
를 pages
의 아래에 추가하면 된다.
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} />
}
Polishing Layout
https://nextjs.org/learn/basics/assets-metadata-css/polishing-layout
간단한 CSS Modules
과 React 코드로 간단하게 구현을 해봤는데 data fetching
을 하기 전에 page styling과 코드를 세련되게 해보자 (=polishing layout)
Download Your Profile Picture
- https://github.com/vercel/next-learn-starter/blob/master/basics-final/public/images/profile.jpg 의 프로필 이미지를 다운로드
images
의 디렉토리를public
디렉토리 아래 생성public/images/profile.jpg
파일을 추가
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.js
는 postcss를 사용하여 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