Next.js (3)| 青训营笔记

168 阅读14分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天

资产、元数据和 CSS

我们当前添加的第二个页面没有样式。让我们添加一些CSS来设置页面样式。
接下来.js内置了对CSSSass的支持。 在本课程中,我们将使用 CSS。
本课还将讨论 Next.js 如何处理静态资产(如图像)和页面元数据(如标记)。

您将在本课中学到什么

在本课程中,您将学习:

  • 如何将静态文件(图像等)添加到 Next.js。
  • 如何为每个页面自定义内部的内容。
  • 如何创建一个使用 CSS 模块设置样式的可重用 React 组件。
  • 如何在页面/_app.js中添加全局 CSS
  • 在Next.js中设置样式的一些有用提示。

先决条件

  • 基本的CSS知识。本课程将介绍如何在Next.js应用程序中添加CSS,但不会涵盖CSS基础知识。

资产

接下来.js可以在顶级公共目录下提供静态资产,例如图像。里面的文件可以从应用程序的根目录引用,类似于页面。public
该目录对于 、Google 站点验证和任何其他静态资产也很有用。查看静态文件服务的文档以了解更多信息。publicrobots.txt

下载您的个人资料图片

首先,让我们检索您的个人资料图片。

  • 以格式下载您的个人资料图片(或使用此文件)。.jpg
  • 公共目录中创建一个目录。images
  • 将图片保存在目录中。profile.jpgpublic/images
  • 图像大小可以在 400 像素 x 400 像素左右。
  • 您可以直接在公共目录下删除未使用的 SVG 徽标文件。

未优化的图像

使用常规 HTML,您可以按如下方式添加您的个人资料图片:

<图像 src="/images/profile.jpg" alt="Your Name" /> 

但是,这意味着您必须手动处理:

  • 确保您的图像在不同的屏幕尺寸上具有响应性
  • 使用第三方工具或库优化图像
  • 仅在图像进入视口时加载图像

等等。相反,Next.js 提供了一个开箱即用的组件来为您处理此问题。Image

图像组件和图像优化

next/image 是 HTML 的扩展<图像> 元素,为现代网络而发展。
Next.js 默认情况下还支持图像优化。这允许在浏览器支持时以现代格式(如 WebP)调整大小、优化和提供图像。这样可以避免将大型图像传送到具有较小视口的设备。它还允许Next.js自动采用未来的图像格式,并将其提供给支持这些格式的浏览器。
自动图像优化适用于任何图像源。即使图像由外部数据源(如 CMS)托管,仍可对其进行优化。

使用图像组件

Next.js 不是在构建时优化映像,而是根据用户请求按需优化映像。与静态站点生成器和仅静态解决方案不同,无论是发布 10 个图像还是 10 万个图像,您的构建时间都不会增加。
默认情况下,图像是延迟加载的。这意味着您的页面速度不会因视口外的图像而受到影响。图像在滚动到视口时加载。
图像始终以避免累积布局偏移的方式呈现,这是Google将在搜索排名中使用的核心Web至关重要
下面是一个使用 next/image 显示我们的个人资料图片的示例。和道具应该是所需的渲染大小,纵横比与源图像相同。heightwidth
**注意:**我们稍后将在“抛光布局”中使用此组件,暂时不需要复制它。

import Image from 'next/image'; const YourComponent = () => (   <Image     src="/images/profile.jpg" // Route of the image file     height={144} // Desired size with correct aspect ratio     width={144} // Desired size with correct aspect ratio     alt="Your Name"   /> ); 

要了解有关自动图像优化的更多信息,请查看文档
要了解有关该组件的更多信息,请查看下一个/图像的 API 参考。Image

元数据

如果我们想修改页面的元数据,例如 HTML 标记,该怎么办?<br /><title>是 HTML 标记的一部分,因此让我们深入了解如何在 Next.js 页面中修改标记。在编辑器中打开并找到以下行:pages/index.js

<Head>
  <title>Create Next App</title>
  <link rel="icon" href="/favicon.ico" />
</Head>

请注意,使用Head代替小写。 是一个内置于 Next.js 中的 React 组件。它允许您修改页面的。
您可以从 next/head 模块导入组件。

添加到Headfirst-post.js

我们尚未在路线中添加 a。让我们添加一个。/posts/first-post打开文件并在文件开头添加 from 的导入:pages/posts/first-post.jsHead

import Head from 'next/head'; 

然后,更新导出的组件以包含该组件。现在,我们只添加标签:FirstPostHeadtitle

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

尝试访问 http://localhost:3000/posts/first-post。浏览器选项卡现在应该显示“First Post”。通过使用浏览器的开发人员工具,您应该会看到标记已添加到 。title

第三方 JavaScript

第三方 JavaScript 是指从第三方源添加的任何脚本。通常 包含第三方脚本是为了将较新的功能引入不 需要从头开始编写,例如分析、广告和客户支持小部件。

添加第三方 JavaScript

让我们深入了解如何将第三方脚本添加到 Next.js 页面。
在编辑器中打开并找到以下行:pages/posts/first-post.js

<Head>
  <title>First Post</title>
</Head>

除了元数据之外,通常会添加需要尽快加载和执行的脚本 在页面中。使用常规 HTML

<Head>
  <title>First Post</title>
  <script src="https://connect.facebook.net/en_US/sdk.js" />
</Head>

此脚本包含通常用于引入Facebook社交插件和其他功能的Facebook SDK。虽然这 方法有效,以这种方式包含脚本并不能清楚地了解何时加载 关于在同一页面上获取的其他 JavaScript 代码。如果特定脚本是 呈现阻塞并可能延迟页面内容的加载,这可能会显著影响性能。

使用脚本组件

next/script 是 HTML 的扩展

import Script from 'next/script'; 

现在,更新组件以包含组件:FirstPostScript

export default function FirstPost() {
  return (
    <>
      <Head>
        <title>First Post</title>
      </Head>
      <Script
        src="https://connect.facebook.net/en_US/sdk.js"
        strategy="lazyOnload"
        onLoad={() =>
          console.log(`script loaded correctly, window.FB has been populated`)
        }
      />
      <h1>First Post</h1>
      <h2>
        <Link href="/">← Back to home</Link>
      </h2>
    </>
  );
}

请注意,脚本组件中定义了几个其他属性:

  • strategy控制应加载第三方脚本的时间。值 告诉 Next.js在浏览器空闲期间延迟加载此特定脚本lazyOnload
  • onLoad用于在脚本完成加载后立即运行任何 JavaScript 代码。在此示例中,我们将一条消息记录到控制台,其中提到脚本已正确加载

尝试访问 http://localhost:3000/posts/first-post。由 使用浏览器的开发人员工具,您应该会在面板中看到上述消息。此外,您可以运行以查看脚本是否已填充此全局 变量。Consolewindow.FB
**注意:**Facebook SDK仅用作人为示例,以展示如何添加第三方 以高性能方式编写应用程序的脚本。现在您了解了包含的基础知识 Next.js 中的第三方功能,您可以从之前删除脚本组件 进行中。FirstPost

CSS 样式

现在让我们谈谈CSS样式
如您所见,我们的索引页(http://localhost:3000)已经有一些样式。如果你看一下你的文件结构,你会看到一个文件夹,里面有两个CSS文件:一个全局样式表()和一个CSS模块()。stylesglobals.cssHome.module.css
如果您的项目没有这些文件,您可以在此处下载起始代码:

npx create-next-app nextjs-blog --use-npm --example "https://github.com/vercel/next-learn/tree/master/basics/assets-metadata-css-starter" 

CSS 模块

CSS 模块允许您通过自动创建唯一的类名在组件级别本地限定 CSS 的作用域。这允许您在不同的文件中使用相同的 CSS 类名,而不必担心类名冲突。
除了 CSS 模块之外,您还可以通过多种方式设置 Next.js 应用程序的样式,包括:

在本课中,我们将在Next.js中讨论如何使用CSS模块Sass。让我们潜入!

布局组件

首先,让我们创建一个将在所有页面之间共享的布局组件。

  • 创建名为 的顶级目录。components
  • 在 中,创建一个包含以下内容的文件:componentslayout.js
export default function Layout({ children }) {
  return <div>{children}</div>;
}

然后,打开 ,为组件添加导入,并使其成为最外层的组件:pages/posts/first-post.jsLayout

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="/">← Back to home</Link>
      </h2>
    </Layout>
  );
}

添加 CSS

现在,让我们向组件添加一些样式。为此,我们将使用 CSS 模块,它允许您在 React 组件中导入 CSS 文件。Layout
创建一个包含以下内容的调用文件:components/layout.module.css

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

**重要:**要使用 CSS 模块,CSS 文件名必须以 结尾。.module.css
要在 中使用此类,您需要:containercomponents/layout.js

  • 导入 CSS 文件并为其指定名称,例如styles
  • 用作styles.containerclassName

打开其内容并将其替换为以下内容:components/layout.js

import styles from './layout.module.css';

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

如果转到“现在 http://localhost:3000/posts/first-post”,您应该看到文本现在位于居中的容器中:
image.png

自动生成唯一的类名

现在,如果你看一下浏览器开发工具中的 HTML,你会注意到组件呈现的类名如下所示:divLayoutlayout_container__...
image.png
这就是CSS模块的作用:它自动生成唯一的类名。只要使用 CSS 模块,就不必担心类名冲突。
此外,Next.js的代码拆分功能也适用于CSS模块。它确保为每个页面加载最少量的 CSS。这会导致捆绑包大小更小。
CSS 模块在构建时从 JavaScript 捆绑包中提取,并生成由 Next.js 自动加载的文件。.css

全局样式

CSS 模块对于组件级样式很有用。但是,如果您希望每个页面都加载一些CSS,Next.js也支持此功能。
若要将全局 CSS 加载到应用程序,请创建一个包含以下内容的调用文件:pages/_app.js

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

的默认导出是一个顶级 React 组件,它包装了应用程序中的所有页面。您可以使用此组件在页面之间导航时保持状态,或者像我们在这里所做的那样添加全局样式。详细了解_app.js文件。_app.js

重新启动开发服务器

**重要:**添加页面/_app.js时,需要重新启动开发服务器。按下停止服务器并运行:Ctrl + c

npm run dev 

添加全局 CSS

在Next.js中,您可以通过从页面/_app.js导入全局 CSS 文件来添加全局 CSS 文件。您不能在其他任何位置导入全局 CSS。
全局 CSS 无法导入外部的原因是全局 CSS 会影响所有pages/_app.js元素在页面上。
如果要从主页导航到页面,则主页中的全局样式会无意中受到影响。/posts/first-post/posts/first-post
您可以将全局 CSS 文件放置在任何位置并使用任何名称。因此,让我们执行以下操作:

  • 创建顶级目录和文件。stylesglobal.css
  • 在 中添加以下 CSS。此代码重置某些样式并更改标记的颜色:styles/global.cssa

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; }
最后,将 CSS 文件导入到您之前创建的文件中:pages/_app.js
// pages/_app.js import '../styles/global.css'; export default function App({ Component, pageProps }) { return <Component {...pageProps} />; }
现在,如果您访问 http://localhost:3000/posts/first-post,您将看到样式已应用。导入的任何样式都将全局应用于应用程序的所有页面。_app.js
image.png
如果不起作用:请确保在更新时重新启动开发服务器。pages/_app.js

美化布局

到目前为止,我们只添加了最少的 React 和 CSS 代码来说明 CSS 模块等概念。在我们继续下一课关于数据获取之前,让我们完善我们的页面样式和代码。

更新components/layout.module.css

首先,打开并用以下更精美的样式替换其内容,用于布局和个人资料图片:components/layout.module.css

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

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

.backToHome {
  margin: 3rem 0 0;
}

创造styles/utils.module.css

其次,让我们创建一组可以在多个组件中重用的 CSS 实用程序类(用于文本样式)。
添加一个调用的新 CSS 文件,其中包含以下内容: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: #666;
}

您可以在整个应用程序中重用这些实用程序类,甚至可以在文件中使用实用程序类。实用程序类是指编写CSS选择器而不是方法的方法(例如全局样式,CSS模块,Sass等)。详细了解实用工具优先的 CSS。global.css

更新components/layout.js

第三,打开并用以下代码替换其内容,更改为实际名称:components/layout.jsYour Name

import Head from 'next/head';
import Image from 'next/image';
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.vercel.app/${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 ? (
          <>
            <Image
              priority
              src="/images/profile.jpg"
              className={utilStyles.borderCircle}
              height={144}
              width={144}
              alt=""
            />
            <h1 className={utilStyles.heading2Xl}>{name}</h1>
          </>
        ) : (
          <>
            <Link href="/">
              <Image
                priority
                src="/images/profile.jpg"
                className={utilStyles.borderCircle}
                height={108}
                width={108}
                alt=""
              />
            </Link>
            <h2 className={utilStyles.headingLg}>
              <Link href="/" className={utilStyles.colorInherit}>
                {name}
              </Link>
            </h2>
          </>
        )}
      </header>
      <main>{children}</main>
      {!home && (
        <div className={styles.backToHome}>
          <Link href="/">← Back to home</Link>
        </div>
      )}
    </div>
  );
}

以下是新增功能:

  • 元标记(如),用于描述页面内容og:image
  • 布尔道具,将调整标题和图像的大小home
  • 底部的“返回主页”链接,如果是homefalse
  • 添加了带有 的图像,这些图像预加载了优先级属性next/image

更新pages/index.js

最后,让我们更新主页。
打开其内容并将其替换为: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>
  );
}

然后用你的自我介绍代替。以下是作者个人资料的示例:[Your Self Introduction]
image.png
就是这样!我们现在有了完善的布局代码,我们准备继续我们的数据获取课程。
在结束本课程之前,让我们在下一页讨论一些与Next.js的CSS支持相关的有用技术。

Styling Tips

以下是一些可能会有所帮助的样式提示。
您可以通读以下部分。无需更改我们的应用程序!

使用库切换类clsx

CLSX 是一个简单的库,可让您轻松切换类名。您可以使用 或 进行安装。npm install clsxyarn add clsx
请查看其文档以获取更多详细信息,但以下是基本用法:

  • 假设您要创建一个接受 的组件,该组件可以是 或 。Alerttype'success''error'
  • 如果是 ,则希望文本颜色为绿色。如果是 ,则希望文本颜色为红色。'success''error'

你可以先写一个CSS模块(例如),像这样:alert.module.css

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

并像这样使用:clsx

import styles from './alert.module.css';
import { clsx } from 'clsx';

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

自定义 PostCSS 配置

开箱即用,无需配置,Next.js 使用 PostCSS 编译 CSS
要自定义PostCSS配置,您可以创建一个名为postcss.config.js的顶级文件。如果您使用的是 Tailwind CSS 等库,这将非常有用。
以下是添加 Tailwind CSS 的步骤。首先,安装软件包:

npm install -D tailwindcss autoprefixer postcss 

然后,创建一个 postcss.config.js

// postcss.config.js
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

我们还建议通过指定以下选项来配置内容源:contenttailwind.config.js

// tailwind.config.js
module.exports = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
    // For the best performance and to avoid false positives,
    // be as specific as possible with your content configuration.
  ],
};

要了解有关自定义 PostCSS 配置的更多信息,请查看 PostCSS 的文档
要轻松开始使用 Tailwind CSS,请查看我们的示例

使用Sass

开箱即用的 Next.js 允许您同时使用 和 扩展导入 Sass。您可以通过 CSS 模块和 or 扩展使用组件级 Sass。.scss.sass.module.scss.module.sass
在使用 Next.js 的内置 Sass 支持之前,请务必安装 sass

npm install -D sass 

本课就讲到这里!

要了解有关Next.js内置CSS支持和CSS模块的更多信息,请查看CSS文档
2023.2.16 4:07 记录