开发 todos 网站的栽坑记录
docker nginx 静态页面
使用 nextjs,先做的静态页面,用的最简单版腾讯云,启动docker ngnix 静态网页部署,过程是直接上传本地打包文件直接到服务器,
docker run -d -p 80:80
-v /home/docker-nginx/nginx.conf:/etc/nginx/nginx.conf
-v /home/docker-nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
-v /home/lighthouse/out:/usr/share/nginx/html
--name mynginx
一一解释, -p 80:80 本地docker 80 外面监听80,后面的是外面的
-d 命令行关闭,后台运行
/home/docker-nginx/nginx.conf:/etc/nginx/nginx.conf 把外面的配置地址复制到里面,
用了这么多nginx ,是因为 nginx 有一个server 还有http , 这还没配置log,就是把里面的log给同步到外面,
配置这么多可以写Dockerfile
/home/lighthouse/out:/usr/share/nginx/html
这是把外面的静态文件扔到里面
/usr/share/nginx/html 这位置 nginx server 字段 location / root配置
http {
gzip on; #要开 gzip压缩
}
server {
listen 80;
# listen 443 ssl;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html; #指向静态文件位置
index index.html index.htm;
try_files $uri $uri.html $uri/ /index.html;
add_header Access-Control-Allow-Origin *;
add_header Cache-Control no-cache;
}
location = /50x.html {
root /usr/share/nginx/html;
}
# 可选:配置 HTTPS
# listen 443 ssl;
# ssl_certificate /path/to/your/ssl/certificate.crt;
# ssl_certificate_key /path/to/your/ssl/private.key;
}
try_files $uri $uri.html $uri/ /index.html; 这里 try_files,SPA刷新路径失效就是 try_files 没有配置正确导致的
Cache-Control no-cache; 的意思是说每次使用缓存前,都需要请求,没有过期才能用。 Cache-Control 参数里面也有一点协商缓存的意思,Cache-Control 不止是强缓存
配置ssl需要证书,申请证书需要域名 申请后保持电话畅通,否则给你驳回还得重新申请 工信部将给你发送校验短信,请收到短信后24小时内按照短信提示登录工信部网站进行短信核验,超时未核验备案订单会被退回。短信24小时内最多重发3次,验证码有效期为24小时并且期间试错次数为5次。
nginx 解析域名和反向代理
server {
listen 80;
server_name todos.asia www.todos.asia;
location / {
proxy_pass http://ip:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name b.com www.todos.asia;
location / {
proxy_pass http://ip:4000;
}
}
server_name 填写你购买的域名,有二级域名加空格
proxy_pass 就是访问80端口给代理到你自己的服务器3000端口来,这样的话,你的服务器可以有多个域名,然后代理到不同的端口
https 要监听443端口,默认是80
有了端口,防火墙也要把端口打开
本地的数据库和 node 版本
不要搞本地的,因为本地系统都特别旧,经常要你升级, node版本太低,你要安装各种C++的东西,烦的要死,数据库经常起不来,版本不对,为此都折腾了好几天。所以再也不搞本地的服务,都进docker
nextjs /app SSR
使用的是新版本,本来想学习下nextjs,官方给了一个todolist,我也就直接把官方给的拿来了。 里面有服务端渲染,服务端渲染最适合做本身就固定好的内容,个性化的内容不适合,需要用户登陆的请求统统不适合。
nextjs SSR 默认所有的页面都是服务端渲染, 服务端渲染只会渲染一次,不用使用useState 等。开始写惯了真的不习惯,老是不知道怎么写。RSC组件可以包含静态组件,静态组件不能包RSC组件,但是可以使用一些特殊的系法,让一些静态组件也能包含RSC组件。
SSR 部署的时候一直是node server.js 这样的命令行在跑。
SSR 页面不能被CDN,CDN只能缓存静态的页面
RSC form 使用 useForm 请求可以做到无js请求,基本就是直接操作数据库。
useForm 这个设置一个动态默认值也听麻烦的。比如用户id 需要请求才能得到,设置value,又提醒需要受控组件,action又是非受控组件,反正能运行但是一直warning 很烦人
踩坑: 直接看官方的视频,拿别人的例子来开发。
tailwind
学习了tailwind 的用法,同时也踩坑了一些复杂的写法比如 checked:before: 代表即是checked还是伪代码部分,如果需要一些动态的样式,不要拆开横,要把整个作为一个新变量 text-[#a9af99] text-[isRed: 'red':'green'],这种写法就是错误的。 flex 设置成flex-row 或者flex-col的时候 items 和 justify 是反着的。 使用一些tailwind框架UI 的时候,修改他们的样式,尤其是深层的样式, 通过这个好像是[.*_&]:text-white 选中所有的子属性,修改样式, 感觉覆盖样式还是很麻烦的
tailwind 框架 UI不好修改的时候,还不如自己写样式
数据库的速度
开始用的velcel默认的免费的数据库本地访问特别慢,跟代理没代理没关系,速度就是慢。然后用腾讯云自己的数据库一下快了
网站和接口一定要部署在一个地域,后来我网站部署到vercel的默认美国区域,访问的中国数据库,2s 的返回速度。尽管我又该回了vercel数据,在中国访问依然很慢,我不清楚其他国家慢还是vervel免费的数据库本身就不好用。
登录系统 next-auth jwt
使用next-auth ,建议直接看youtube 教学,先写好UI,数据,因为要做数据库,需要把用户名称存到库里,然后prisma 就出现了问题,各种魔改,总算保存在了库里,这个只能访问用户名各种基本信息,连jwt那个token都没有跟我生成,我还自己根据返回的json token 生成 一个jwt token,我发现依然需要借口,又写了一个接口,我还以为不需要接口了。 jwt就是编码带在请求头里发过去,那边解码解析。 cookie 或者localstorge是存储,不需要带 cookie 请求。
使用nextjs ssr 在腾讯云部署
官网的docker 部署版本过时了,我用的一个博客分享的
FROM node:18-alpine as base
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk add --no-cache g++ make py3-pip libc6-compat
WORKDIR /app
COPY package*.json ./
EXPOSE 3000
FROM base as builder
WORKDIR /app
COPY . .
RUN npm run build
FROM base as production
WORKDIR /app
ENV NODE_ENV=production
RUN npm ci
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
USER nextjs
COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/public ./public
CMD npm start
运行到 RUN apk add --no-cache g++ make py3-pip libc6-compat 一直过不去,我还在傻等着,后来才知道需要修改镜像,又添加了上面一行RUN sed -i
域名解析到腾讯云
本来使用 nginx 做了配置,启动一直访问不到,原来还需要域名备案,备案过程中电话要畅通,不然给你驳回,重新提交,他们会给你打电话,还有提交域名的时候,域名先不要解析,会让你删除解析记录再次提交
prisma
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
accounts Account[]
sessions Session[]
todos Todo[]
@@map(name: "users")
}
@@map(name: "users") 不写的话 ,select * from user 查询不出来,这是我推断出来的,文档也没怎么看
model Todo {
id String @id @default(cuid())
content String
createdAt DateTime @default(now()) @map(name: "created_at")
finished Boolean @default(false)
user User? @relation(fields: [userId], references: [id])
userId String
@@map(name: "todos")
}
user User? @relation(fields: [userId], references: [id]) 代码表示了Todo 数据模型中的 userId 字段与 User 数据模型中的 id 字段之间的关联关系。 也就是说,通过这个关系定义,Prisma 将会根据 userId 字段的数值来关联到 User 数据模型中相应的 id 字段,建立起这两个数据模型之间的连接。
const res = await prisma.todo.create({
data: {
content: data.todo,
finished: false,
user: {
connect: {
id: data.id
}
}
},
});
因为是关联表,创建的时候就要指定 id,写法可以是这样的
const todos = [{
content: '',
finished: false,
userId:1
},{
content: '',
finished: false,
userId:1
}]
const res = await prisma.todo.createMany({
data: todos,
});
也可以这样批量创建
数据库一直自己删库
每天我创建了库,24小时后必定删库,开始第一天还以为遭到了入侵,朋友让我改密码。 后来每次我都发现库成了空。在部署的时候我终于想起了修改密码,但是密码修改名称修改,我什么都连不上了。 我试了很多次只修改密码不修改名称,开始以为密码太长,或者用了英文,各种瞎尝试,我发现只有密码是123456 的时候能连接成功。根据一些错误提示,通过搜索github有人说是因为外面有个数据库,里面有个数据库, 你连接的是外面的,我把外面的数据库全部卸载了,但是我修改密码还是连接不成功,于是我就在docker里面修改密码才成功,外面的那个配置密码是不对的。