把 nextjs netflix clone 教程学完了
跟着教程,一个半月时间,67个半小时。终于学完了。代码跟着写了一遍,注册登录部分只写了登录。在这里做一些零碎的总结,算是收尾了。
// zustand, 全局状态管理工具。状态变了,使用状态的组件会更新
const {openModal} = useInfoModalStore()
import useSwr from 'swr'
import fetcher from '@/libs/fetcher';
const useBillboard = () => {
// swr,2秒内发送同一个请求,只发一个
// 缓存和请求校验,相同,组件不更新
const { data, error, isLoading } = useSwr('/api/random', fetcher, {
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false,
});
return {
data,
error,
isLoading
}
};
export default useBillboard;
import { PrismaClient } from '@prisma/client'
// prisma
// 数据库orm
// 数据库 schema,数据库表设计
// 数据库迁移
// 相当于在数据库查询语句上做一层抽象,屏蔽到不同数据查询语句sql的差异。
// 还有数据库迁移、初始化等功能
const client = global.prismadb || new PrismaClient()
if(process.env.NODE_ENV !== 'production') global.prismadb = client
export default client
import { authOptions } from "@/pages/api/auth/[...nextauth]";
import { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth";
// 身份验证,以及身份信息获取
const serverAuth = async (req: NextApiRequest, res: NextApiResponse) => {
const session = await getServerSession(req, res, authOptions)
if(!session?.user?.email) {
throw new Error('Not signed in')
}
const currentUser = await prismadb.user.findUnique({
where: {
email: session.user.email,
}
})
if(!currentUser) throw new Error('Not signed in')
return {currentUser}
}
export default serverAuth
// index.tsx
import Navbar from "@/components/Navbar";
import Billboard from '@/components/Billboard';
import MovieList from '@/components/MovieList';
import useInfoModalStore from '@/hooks/useInfoModalStore';
import InfoModal from '@/components/InfoModal';
import { NextPageContext } from "next";
import { getSession } from "next-auth/react";
import useMovieList from "@/hooks/useMovieList";
import useFavorites from "@/hooks/useFavorites";
// 在node环境下运行,浏览器没办法 debug 这部分内容
export async function getServerSideProps(context: NextPageContext) {
const session = await getSession(context)
console.log(session);
// 拦截页面跳转,没有session,跳转到登录页面
if (!session) {
return {
redirect: {
destination: '/auth',
permanent: false,
}
}
}
return {
props: {}
}
}
export default function Home() {
const {data: movies=[]} = useMovieList()
const {data: favorites=[]} = useFavorites()
// 两兄弟组件共用状态放在 zustand 管理起来,逻辑挺清楚的。
// 写起来麻烦些。
// 之前那种父组件向子组件传参,调用组件内方法。
// 子组件向父组件传参,emit 自定义事件也挺麻烦的,并且耦合深,不通用
const { isOpen, closeModal } = useInfoModalStore()
return (
<>
<InfoModal visible={isOpen} onClose={closeModal}/>
<Navbar></Navbar>
<Billboard></Billboard>
<div className="pb-40 pl-[47px] bg-black">
<MovieList title="Trending Now" data={movies}></MovieList>
<MovieList title="My List" data={favorites}></MovieList>
</div>
</>
)
}
本地起 mongodb 以及应用连接 mongodb 花了挺多时间。连接上之后,发现第三方登录还是不行。最后跟着视频教程用 mongodb atlas 。
nextjs 基于react 的全栈框架,包含路由、请求、打包、优化等 nextjs 默认使用 server component,使用服务端渲染
tailwindcss
self-center 交叉轴居中
appearance-none 移除默认样式
flex 子元素 右对齐
子元素设置 ml-auto
nextjs,服务端渲染,服务端直接生成html发给浏览器。 客户端渲染,发html,发js库,发js,浏览器渲染。
// schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
previewFeatures = ["mongoDb"]
}
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
name String
image String?
email String? @unique
emailVerified DateTime?
hashedPassword String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
sessions Session[]
accounts Account[]
favoriteIds String[] @db.ObjectId
}
model Account {
id String @id @default(auto()) @map("_id") @db.ObjectId
userId String @db.ObjectId
type String
provider String
providerAccountId String
refresh_token String? @db.String
access_token String? @db.String
expires_at Int?
token_type String?
scope String?
id_token String? @db.String
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id String @id @default(auto()) @map("_id") @db.ObjectId
sessionToken String @unique
userId String @db.ObjectId
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model VerificationToken {
id String @id @default(auto()) @map("_id") @db.ObjectId
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
model Movie {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
description String
videoUrl String
thumbnailUrl String
genre String
duration String
}
prisma schema
User数据集
唯一 unique
id自动生成
可填/必填
default 默认值
@id 主键
@db.ObjectId 在数据库中使用 ObjectId 类型
Session[] 一个用户可以多个会话记录
Account
账户类型,email Oauth
提供者google
Authorization:Bearer 接口请求,用于身份验证
一个账户与一个用户关联,用户被删除,账户也被删除
唯一约束,账户提供者和账户id的组合是唯一的
Session
expires 存DateTime
类型
DateTime
string
prisma 有实时数据库事件
orm,简单地与数据库对话
迁移系统
nextjs 构建全栈web应用程序的react框架
文件系统的路由器
文件系统的动态路由
按文件路径的API
router.push()
swr
swr 好处,数据与组件解耦。
请求有缓存
2秒内只发一个请求
可以设置轮询时间
zustand
替代redux的全局状态管理工具