# Next.js 入门学习教程

# 准备工作

  • [✓] 一台 MacBook
  • [✓] 编辑器:VSCode
  • [✓] 终端:iterm2+zsh
  • [✓] 环境:Nodejs、科学上网

Next.js 是一个基于 Node.js 的框架,所以首先需要安装 Node.js。你可以从 Node.js 官方网站 (opens new window) 下载并安装最新版本。

# 创建项目

项目文件夹名 my-nextjs-app

npx create-next-app my-nextjs-app

为了更容易理解Next.js,你可以所有选项都选 No 所有选项都选NO

进入my-nextjs-app

cd my-nextjs-app

运行开发模式

npm run dev

打开浏览器,访问 http://localhost:3000 (opens new window),你将看到一个基本的 Next.js 应用程序正在运行。

# 基础概念

# 页面 & 路由

pages文件夹的意义是我们所有页面的存放地点, 当我们访问根目录(/)时,会自动找到/index.js,同理访问(/new),则会找到/pages/new.js

/pages/index.js 内容比较多,为了方便理解,我们先不去修改它。

我们新建一个list.js在pages文件夹下

// pages/list.js

import Link from 'next/link';

const projects = [
  { id: 1, title: '点我跳转' },
];

const List = () => {
  return (
    <div>
      <h1>Project List</h1>
      <div>页面跳转传参: /detail/[id]</div>
      <ul>
        {projects.map((project) => (
          <li key={project.id}>
            <Link target="_blank" href={`/detail/${project.id}`}>
              {project.title}
            </Link>
          </li>
        ))}
      </ul>
      <div>页面跳转传参: /detail?id=[id]</div>
      <ul>
        {projects.map((project) => (
          <li key={project.id}>
            <Link target="_blank" href={`/detail?id=${project.id}`}>
              {project.title}
            </Link>
          </li>
        ))}
      </ul>
      <div>页面跳转传参: /detail/[id]/view</div>
      <ul>
        {projects.map((project) => (
          <li key={project.id}>
            <Link target="_blank" href={`/detail/${project.id}/view`}>
              {project.title}
            </Link>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default List;

为了页面清爽一点 找到 _app.js 我们先把样式引入注释掉

// import '@/styles/globals.css'

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

现在我们 访问 http://localhost:3000/list (opens new window) ,可以看到我们刚刚创建的页面。

可以看到我们列举了3种页面传参的方式,下面我们演示如何接收参数

# 接收方式1

在pages文件夹下创建detail文件夹,在detail文件夹下创建一个文件名为 [id].js 的文件

//目录结构
pages/
├── detail/
│   └── [id].js
// pages/detail/[id].js

import { useRouter } from 'next/router';

const Detail = () => {
  const router = useRouter();
  const { id } = router.query; // 从路由参数中获取项目的ID

  return (
    <div>
      <h1>Project Details</h1>
      <p>Project ID: {id}</p>
    </div>
  );
};

export default Detail;

访问 http://localhost:3000/detail/1 (opens new window) 即可看到页面已经呈现,参数也被接收

# 接收方式2

在pages文件夹下创建一个文件名为 detail.js 的文件

//目录结构
pages/
├── detail.js
// pages/detail.js

import { useRouter } from 'next/router';

const Detail = () => {
  const router = useRouter();
  const { id } = router.query; // 从路由参数中获取项目的ID

  return (
    <div>
      <h1>Project Details</h1>
      <p>Project ID: {id}</p>
    </div>
  );
};

export default Detail;

访问 http://localhost:3000/detail?id=1 (opens new window) 即可看到页面已经呈现,参数也被接收

# 接收方式3

在pages文件夹下创建detail文件夹,在detail文件夹下创建一个文件名为 [id].js 的文件

//目录结构
pages/
├── detail/
│   └── [id]/
│       └── view.js
// pages/detail/[id]/view.js

import { useRouter } from 'next/router';

const Detail = () => {
  const router = useRouter();
  const { id } = router.query; // 从路由参数中获取项目的ID

  return (
    <div>
      <h1>Project Details</h1>
      <p>Project ID: {id}</p>
    </div>
  );
};

export default Detail;

访问 http://localhost:3000/detail/1/view (opens new window) 即可看到页面已经呈现,参数也被接收

# 数据获取

其中两个重要的函数 getServerSidePropsgetStaticProps 来获取数据并在服务器端预取数据,以便在渲染页面时使用。

# getServerSideProps:

用于在每次请求页面时获取数据。 在服务器端运行,因此可以执行任何服务器端代码,例如调用数据库、访问外部 API 等。 每次请求页面时都会运行 getServerSideProps 函数,因此数据是实时获取的。 返回的数据将作为页面组件的 props,在服务器端渲染时使用。 适用于需要根据每个请求动态获取数据的场景,例如个性化页面、需要实时数据更新的页面等。

# getStaticProps:

用于在构建时(而不是每次请求)获取数据。 在构建时运行,因此它不能包含任何服务器端代码。 可以访问远程数据源或文件系统,并将数据预先获取到静态页面中。 返回的数据将作为页面组件的 props,在静态页面渲染时使用。 适用于静态数据或不经常更改的数据,例如博客文章、产品列表等。

下面我以getServerSideProps为例,做一个天气页面,创建文件 /pages/weather.js

//目录结构
pages/
├── weather.js
// pages/weather.js

function WeatherPage({ weatherData }) {
  // 使用从 getServerSideProps 获取的天气数据渲染页面
  return (
    <div>
      <h1>{weatherData.cityInfo.city}</h1>
      <p>当前温度:{weatherData.data.wendu}</p>
      <p>天气状况:{weatherData.data.forecast[0].type}</p>
    </div>
  );
}

//在getServerSideProps里请求的接口地址是不会被别人看到的
export async function getServerSideProps() {
  // 在这里执行异步操作,从天气API获取数据
  const response = await fetch('http://t.weather.sojson.com/api/weather/city/101010100');
  const data = await response.json();

  // 返回获取的天气数据作为 props
  return {
    props: {
      weatherData: data,
    },
  };
}

export default WeatherPage; 

访问 http://localhost:3000/weather (opens new window) 即可看到页面已经出现实时天气 你可以在getServerSideProps里做任何数据处理,比如查询SQL,请求外部API等。

# 部署

# 部署在Vercel

# 项目在本地

我们需要在本地安装 vercel,建议是全局安装:

npm install -g vercel

之后执行如下命令保证你本地登录了 vercel 账号:

vercel login

之后进入你的项目根路径,执行 vercel 即可:

vercel

# 项目在Github

打开 https://vercel.com/dashboard 点击 Add New... 点击 Project ,Import 你的项目即可;

# 部署在自己的服务器

首先我们在package.json里增加一行prod





 



"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "prod": "next build && next start",
    "lint": "next lint"
  },

我们以宝塔面板为例

  • 打开宝塔面板 -> 网站 -> Node项目 -> 添加Node项目
  • 启动选项:prod
  • 项目端口:3000

如果你想换一个端口,那么你需要将上面的prod 改成 例如 next build && next start -p 3001 即可,绑定域名可以更方便的访问

# 结语

Next.js的学习当然没有这么简单,例如还有中间件 管理样式 插件和库 自定义组件 docker部署 持续集成,以及我们在在最初创建项目时,所有选择的No,改成Yes,会有什么样的变化呢?

更全面的教学文档,请查看Next.js官方提供的文档 https://nextjs.org/docs (opens new window)