【实战】Next.js + 云函数开发一个面试刷题网站

简介: 前段时间开发了一个面试刷题小程序——面试狗,主要使用了 uniapp + unicloud 云开发实现,今天我们来开发一个与之对应的 PC 版面试刷题网站。

前言

前段时间开发了一个面试刷题小程序——面试狗,主要使用了 uniapp + unicloud 云开发实现,详情可以看这篇文章《【实战】使用 uniapp 开发一个面试刷题小程序》 ,今天我们来开发一个与之对应的 PC 版面试刷题网站。

体验地址:https://www.runjs.cool/interview

技术栈选择

  • Next.js —— React 服务端渲染框架
  • Tailwindcss —— CSS 原子类框架
  • 云数据库 —— 和小程序公用一套数据库

项目初始化

首先我们使用 create-next-app 创建一个新的 next 项目

npx create-next-app next-interview
cd next-interview

进入到 next-interview 目录下安装 tailwindcss 相关 npm 包,并且初始化 tailwindcss 配置文件

yarn add --dev tailwindcss postcss autoprefixer @tailwindcss/typography
npx tailwindcss init -p

接下来将 pagesstyles 文件夹重新移动到 src 目录下,这一步是我个人习惯。

修改 tailwindcss.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [require('@tailwindcss/typography')],
}

这样 tailwindcss 只会编译 src 目录下使用到的 css 类,其中是 @tailwindcss/typography 是 tailwind 官方提供的文章插件,小程序中题目和答案使用 markdown 编辑的,所以使用到这个插件可以方便样式设置。

然后修改 styles/globals.css 中 css 为 tailwindcss 的指令

@tailwind base;
@tailwind components;
@tailwind utilities;

修改 index.js 中的代码测试下 tailwindcss 是否配置成功

import Head from 'next/head';

export default function Home() {
  return (
    <div>
      <Head>
        <title>前端面试题库</title>
      </Head>
      <h1 className="text-3xl text-blue-500 flex p-10 justify-center">
        前端面试题库
      </h1>
    </div>
  );
}

修改后,运行 yarn && yarn dev,可以在浏览器中看法如下效果

至此项目初始化成功。

云数据库

之前我们在小程序中设计好了云数据,并且可以在小程序中请求数据,下面这个接口对应数据库中的题目表

export interface Question {
  _id: string;
  category: string; // 分类
  title: string; //标题
  desc: string; // 简介
  options?: string; //选项,选择题
  explanation: string;// 答案解析
  level: number; // 难度等级
  tagId: number; // 标签
}

我们原来的的云函数代码如下,用于请求题目列表

exports.main = async (event, context) => {
  const db = uniCloud.database();
  const page = event.page || 1;
  const res = await db.collection('fe-question').skip((page - 1) * 20)
      .limit(20)
      .get();
  //返回数据给客户端
  return res.data
};

在 uniapp 中可以使用 uniCloud.callFunction 方法直接请求数据,那么在 Next.js 项目中要如何请求数据呢?

云函数 URL 化

设置云函数 HTTP 访问地址

  • 登录 uniCloud 后台 (opens new window),选择服务空间。
  • 单击左侧菜单栏【云函数】,进入云函数页面。
  • 点击需要配置的云函数的【详情】按钮,配置访问路径。

注意:path 应该以 / 开头,例如:/functionName

云函数的调用方式

在云函数中,不同的调用方式在context.SOURCE 中可以获得不同的参数

  • client: 客户端callFunction方式调用
  • http: 云函数 url 化方式调用
  • timing: 定时触发器调用
  • server: 由管理端调用,HBuilderX里上传并运行
  • function: 由其他云函数 callFunction调用
'use strict';
exports.main = async (event, context) => {
  let source = context.SOURCE // 当前云函数 Url 后, 为 http 的方式调用
}

云函数的入参

使用 HTTP 访问云函数时,HTTP 请求会被转化为特殊的结构体,称之为集成请求,结构如下:

{
    path: 'HTTP请求路径,如 /hello',
    httpMethod: 'HTTP请求方法,如 GET',
    headers: {HTTP请求头},
    queryStringParameters: {HTTP请求的Query,键值对形式},
    body: 'HTTP请求体',
    isBase64Encoded: 'true or false,表示body是否为Base64编码'
}

使用GET请求https://${云函数Url化域名}/${functionPath}?a=1&b=2,云函数接收到的event

{
    path: '/',
    httpMethod: 'GET',
    headers: {HTTP请求头},
    queryStringParameters: {a: "1", b: "2"},
    isBase64Encoded: false
}

使用POST 请求https://${spaceId}.service.tcloudbase.com/${functionPath},云函数接收到的 event.body 为请求发送的数据

{
    path: '/',
    httpMethod: 'POST',
    headers: {
        ...
        "content-type": 'application/json'
    },
    isBase64Encoded: false,
    body: '{"a":1,"b":2}', // 注意此处可能是base64,需要根据isBase64Encoded判断
}

所以我想要一个云函数,在小程序和 web 端同时调用,可以在外层加一个判断,这里以 post 为例,以下是获取题目列表的接口代码

exports.main = async (event, context) => {
  const db = uniCloud.database();

  let source = context.SOURCE;
  let data = event;
  if ("http" === source) {
    // data=event.queryStringParameters  //get 方式获取参数
    data = JSON.parse(event.body); // post 方式获取参数
  }

  const page = data.page || 1;
  const res = await db.collection('fe-question').skip((page - 1) * 20)
      .limit(20)
      .get();
  //返回数据给客户端
  return res.data
};

将以上代码重新部署,就可以通过 http 的方式访问了。

服务端渲染

为了能够让搜索引擎收录内容,我们选择服务端渲染,在 Next.js 中,可以再导出一个函数getServerSideProps ,这个函数名称是 Next.js 固定的,不可以写错哦。

import fetch from 'node-fetch';

function Page({ data }) {
  // 渲染数据
  return data.map((item)=><div key={item.id}>...</div>)
}

// 每次页面刷新都会执行这个方法
export async function getServerSideProps() {
  // 从云函数请求数据
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  // 将返回的结果通过 props 传递给组件
  return { props: { data } }
}

export default Page

注意:getServerSideProps函数是在 Nodejs 环境下执行的,若部署的 node 版本低于 17,则需要先安装node-fetch

到此,你已经了解了整个开发流程,接下来就数据渲染,跟 react 开发没有异同了,关于 Next.js 的更多用法可以参考 Next 官方文档,也可以参考 React 必学 SSR 框架——Next.js 这篇文章。

部署

Vercel 是一个开箱即用的网站托管平台,Next.js 是 vercel 公司的明星项目, 只需要将代码上传 GitHub,登录 vercel.com ,并且使用 GitHub 登录即可, 点导入,几分钟后便可部署成功!

存在问题

当我在部署成功后,发现部署成功后发现接口很慢,每次请求需要 2s 以上

没优化之前的速度

但是我本地开发的时候却很快,基本都在 200ms 以内,这是什么原因呢?

本地请求速度

其实 vercel 部署的时候会把 getServerSideProps 中方法部署为 serverless 云函数。

而默认是部署区域在美国华盛顿特区,而 uniCloud 的云函数则是部署在上海的,也就我一个请求在发出,在上海和美国盛顿特来了个往返。

当然我们可以在 Vercel 中设置 serverless 的 Region 为香港,这样稍微可以快点。

小结

本文通过一个实现一个面试刷题网站,讲述了 Next.js 和云开发部署的全过程,至此,你也成为了一名全栈工程师。

优点

  • Vercel 完美的结合和 GitHub,部署极快
  • Vercel 可以自动分配 Https 证书,我们可以添加自定义绑定域名,并且域名可以免备案
  • 云开发选择阿里云,云数据库和云函数都免费

缺点

Next.js ssr 渲染方式需要在 2 个 Region 之间的请求数据,相对来说请求速度较慢。

最后

最后为了权衡访问速度和 SEO,最终我放弃使用 ssr 的渲染方式,直接使用客户端渲染,别忘了 Next.js 不但支持 ssr 还支持 csr。
我的这个网站也开源了,包含一些前端常用工具,还可以在线刷面试题。

如果对你有帮助,可以随手点个赞,这对我真的很重要。

以上就是本文全部内容,希望这篇文章对大家有所帮助,也可以参考我往期的文章或者在评论区交流你的想法和心得,欢迎一起探索前端。

相关文章
|
7月前
|
人工智能 自然语言处理 JavaScript
通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
通义灵码基于自然语言需求,快速生成完整Vue组件。例如,用Vue 2和JavaScript实现贪吃蛇游戏:包含键盘控制、得分系统、游戏结束判定与Canvas动态渲染。AI生成的代码符合规范,支持响应式数据与事件监听,还能进阶优化(如增加启停按钮、速度随分数提升)。传统需1小时的工作量,使用通义灵码仅10分钟完成,大幅提升开发效率。操作简单:安装插件、输入需求、运行项目即可实现功能。
389 4
 通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
|
5月前
|
缓存 Java API
Java 面试实操指南与最新技术结合的实战攻略
本指南涵盖Java 17+新特性、Spring Boot 3微服务、响应式编程、容器化部署与数据缓存实操,结合代码案例解析高频面试技术点,助你掌握最新Java技术栈,提升实战能力,轻松应对Java中高级岗位面试。
464 0
|
3月前
|
JavaScript 前端开发 安全
【逆向】Python 调用 JS 代码实战:使用 pyexecjs 与 Node.js 无缝衔接
本文介绍了如何使用 Python 的轻量级库 `pyexecjs` 调用 JavaScript 代码,并结合 Node.js 实现完整的执行流程。内容涵盖环境搭建、基本使用、常见问题解决方案及爬虫逆向分析中的实战技巧,帮助开发者在 Python 中高效处理 JS 逻辑。
|
5月前
|
JavaScript 前端开发 算法
流量分发代码实战|学会用JS控制用户访问路径
流量分发工具(Traffic Distributor),又称跳转器或负载均衡器,可通过JavaScript按预设规则将用户随机引导至不同网站,适用于SEO优化、广告投放、A/B测试等场景。本文分享一段不到百行的JS代码,实现智能、隐蔽的流量控制,并附完整示例与算法解析。
154 1
|
6月前
|
NoSQL Java 微服务
2025 年最新 Java 面试从基础到微服务实战指南全解析
《Java面试实战指南:高并发与微服务架构解析》 本文针对Java开发者提供2025版面试技术要点,涵盖高并发电商系统设计、微服务架构实现及性能优化方案。核心内容包括:1)基于Spring Cloud和云原生技术的系统架构设计;2)JWT认证、Seata分布式事务等核心模块代码实现;3)数据库查询优化与高并发处理方案,响应时间从500ms优化至80ms;4)微服务调用可靠性保障方案。文章通过实战案例展现Java最新技术栈(Java 17/Spring Boot 3.2)的应用.
479 9
|
6月前
|
缓存 算法 NoSQL
校招 Java 面试高频常见知识点深度解析与实战案例详细分享
《2025校招Java面试核心指南》总结了Java技术栈的最新考点,涵盖基础语法、并发编程和云原生技术三大维度: 现代Java特性:重点解析Java 17密封类、Record类型及响应式Stream API,通过电商案例演示函数式数据处理 并发革命:对比传统线程池与Java 21虚拟线程,详解Reactor模式在秒杀系统中的应用及背压机制 云原生实践:提供Spring Boot容器化部署方案,分析Spring WebFlux响应式编程和Redis Cluster缓存策略。
158 0
|
6月前
|
缓存 NoSQL Java
校招 Java 面试常见知识点及实战案例全解析
本文全面解析了Java校招面试中的常见知识点,涵盖Java新特性(如Lambda表达式、、Optional类)、集合框架高级应用(线程安全集合、Map性能优化)、多线程与并发编程(线程池配置)、JVM性能调优(内存溢出排查、垃圾回收器选择)、Spring与微服务实战(Spring Boot自动配置)、数据库与ORM框架(MyBatis高级用法、索引优化)、分布式系统(分布式事务、缓存应用)、性能优化(接口优化、高并发限流)、单元测试与代码质量(JUnit 5、Mockito、JaCoCo)以及项目实战案例(电商秒杀系统、社交消息推送)。资源地址: [https://pan.quark.cn/s
195 4
|
9月前
|
监控 JavaScript 前端开发
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
MutationObserver 是一个非常强大的 API,提供了一种高效、灵活的方式来监听和响应 DOM 变化。它解决了传统 DOM 事件监听器的诸多局限性,通过异步、批量的方式处理 DOM 变化,大大提高了性能和效率。在实际开发中,合理使用 MutationObserver 可以帮助我们更好地控制 DOM 操作,提高代码的健壮性和可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
|
11月前
|
缓存 架构师 Java
Maven实战进阶(01)面试官:Maven怎么解决依赖冲突?| 有几种解决方式
本文介绍了Maven的核心功能和依赖管理技巧。Maven是基于项目对象模型(POM)的构建工具,具备跨平台、标准化、自动化等特性。其三大核心功能为依赖管理、仓库管理和项目构建。依赖管理通过pom.xml文件引入第三方组件并自动下载;仓库管理涉及中央仓库、私服和本地仓库;项目构建则通过生命周期管理编译、测试、打包等流程。文章还详细讲解了依赖冲突的解决方法,包括默认规则、手工排除和版本指定等策略。
|
11月前
|
人工智能 JavaScript 前端开发
一段 JavaScript 代码,集成网站AI语音助手
根据本教程,只需通过白屏化的界面操作,即可快速构建一个专属的AI智能体。