最近用 Next.js 和 typeorm 完成了前端小白的第一个全栈项目,本文会记录我在做项目的过程中学习到的一些知识点,和遇到的那些奇奇怪怪的 Bug
博客系统 - 献上预览地址,喜欢的话就留下一篇博客吧
先说一下,项目的开发流程
- 确定需求
- 初始化项目
- 前后端开发
- 部署
确定需求
做博客系统的初衷,是创造一个小空间,让每个人可以发布博客,评论的地方
基于上面的理念,产品需求就出来了
初始化项目
聪明的同学,看了文章标题,就可以推理出,项目使用什么技术了
那当然是 Next.js + Typeorm+ TS
TS 相信大家已经很熟悉了,但是 Next.js 和 Typeorm 又是什么鬼
那就介绍一下
Next.js
Next.js 的定位是 Node.js 全栈框架,优点有很多
- 页面预渲染 SSR SSG
- 前后的同构
- 支持 React
- 支持 Typescript
缺点
- 完全没有提供数据操作的功能,解决办法:搭配 Typeorm 或 Sequelize
- 完全没有提供测试相关的功能,解决办法:搭配 Jest 和 Cypress
想对 Next,js 的渲染方式有更深的了解,可以看看我写的这篇博客 Next.js 的三种渲染方式(BSR、SSG、SSR)
Typeorm
Typeorm 我们可以这样理解 Type + orm
Type 我们可以理解成 Typescript,支持 Typescript 就是我选用这个框架的原因
ORM 是 Object–relational mapping 的简称,这个技术的作用是通过实例对象的语法,完成关系型数据库的操作的技术
从这个例子可以看出,ORM 的写法,明显更方便简洁
SELECT id, first_name, last_name, phone, birth_date, sex
FROM persons
WHERE id = 10
------ 改成 ORM 的写法
p = Person.get(10);
name = p.first_name;
那么下面就开干吧
使用脚手架创建项目
npm init next-app nextjs-blog // next-js-blog 是项目名称
选择 Default starter app
进入 next-js-blog ,运行 yarn dev
看到这个页面,就代表成功了
启动 Typescript
yarn add --dev typescript @types/react @types/node
yarn dev
然后我们将文件名 index.js 改为 index.tsx
将 index.tsx 改为
import React from "react"
import {NextPage} from 'next';
const Index: NextPage = () => {
return (
<div>
首页
</div>
)
}
export default Index;
tsconfig 加强
在 tsconfig.json 里添加
"noImplicitAny": true
禁用隐式的 any,想学会 TS 就加上吧
知识点:Link 快速导航
详情请参考官网介绍
一般我们实现页面跳转都是使用 a 标签,而 Next 则推荐我们使用 标签,难道是有黑魔法吗?我们一起来揭晓吧
先在项目分别使用 a 标签和 Link 标签,实现首页和第一篇文章的互相跳转
pages/index.tsx
import React from "react"
import {NextPage} from 'next';
const Index: NextPage = () => {
return (
<div>
<a href="/posts/first-post">a 点击这里</a>
<Link href="/posts/first-post"><a >link 点击这里</a></Link>
</div>
)
}
export default Index;
pages/posts/first-post.tsx
// 第一篇文章
import React from "react"
import {NextPage} from 'next';
const FirstPost: NextPage = () => {
return (
<div>First Post</div>
)
}
export default FirstPost;
实验开始
首先我们通过 a 标签,进行两个页面之间的跳转,从控制台可以看到,浏览器重新请求了 html css js
那接下来,我们使用 Link 重复上面的操作,神奇的事情发送了,浏览器只发送了两个请求
其中第二个请求时 webpack, 所以实际上只发送了一个请求,就是 first-post.js
我们来揭秘一下黑魔法吧
传统导航
当用户点击 a 标签时,请求 html,通过解析 html,请求 html 中引用到的 css 和 js
Link 快速导航
首次加载,浏览器依次请求 html css js,和传统导航相同
当用户点击 Link 时,解析 Link 标签,通过 AJAX 请求 page2.js,而 page2.js 实际上就是 page2 的 HTML + CSS + JS
请求完 page2.js 之后,浏览器不需要访问 page2,而是通过 page2.js 将 page1 的内容,转换成 page2
优点
- 页面不会刷新,用 AJAX 请求新页面内容
- 不会请求重复的 HTML、CSS、JS
- 自动在页面插入新内容,删除旧内容
- 因为省了很多请求和解析过程,所以速度极快
知识点:同构代码
由于我们项目使用的时 SSR 渲染方式,也就是服务端渲染,所以写的就是同构代码
同构代码指的是同时在客户端和服务端运行的代码
比如,我们在组件里写一句 console.log('执行了')
你会发现 Node 控制台会输出这句话,Chrome 控制台也会输出这句话
注意差异
- 不是所有的代码都会运行,有些需要用户触发
- 不是所有的 API 都能用,比如 window 在 Node 里面就不存在
Next.js API
目前我们写的都是 HTML 页面
那实际开发中我们需要请求 /user /shops 等 API,返回的内容都是 JSON 格式的字符串
我们先来实现一个简单的 API 吧
使用 Next.js API
我们使用路径为 /api/v1/posts 以便和 /posts 区分开来
默认导出函数的类型为 NextApiHandle
该代码只运行在 Node.js 里,不运行在浏览器中
/pages/api/v1/posts.tsx
import {NextApiHandler} from 'next';
const Posts:NextApiHandler = (req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.write(JSON.stringify({name: 'Jacky'}));
res.end();
};
export default Posts;
访问 localhost:3000/api/v1/posts
得到
表示api可以访问了 (图中的效果是因为我装了Chrome 的插件 JSON viewer)
改造 posts
目前的 posts api 还不能返回博客列表,接下来我们就改造一下吧
由于我们现在还没创建数据库,先在根目录下创建 markdown 目录,写入几篇 md 格式的博客
然后我们借助 gray-matter 从 md 文件中解析数据
lib/posts.tsx 这个文件导出 JSON 数据
import path from "path";
import fs, {promises as fsPromise} from "fs";
import matter from "gray-matter";
export const getPosts = async () => {
const fileNames = await fsPromise.readdir(find('markdown'))
return fileNames.map(fileName => {
const id = fileName.replace(/\.md$/, '')
const fullPath = find('markdown', fileName)
const content = fs.readFileSync(fullPath, 'utf-8')
const {title, date} = matter(content).data
return {
id, title, date
}
})
}
搞定了读取数据之后,下面就是完善 Posts API ,当接收到请求时,posts api 会从 lib/posts.tsx 中获取数据,然后返回给前端即可
import {NextApiHandler} from 'next';
import {getPosts} from 'lib/posts';
const Posts: NextApiHandler = async (req, res) => {
const posts = await getPosts();
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.write(JSON.stringify(posts));
res.end();
};
export default Posts;
此时,再次访问 localhost:3000/api/v1/posts
页面,就能得到 markdown 目录里写的文章了
未完待续...
更多博客系统的实现和相关知识,请留意 - Next.js + typerom 实践 - 博客系统(中),还没创作出来(再等等吧)
如果对 Next.js 的三种渲染方式有兴趣,请移步查看 Next.js 的三种渲染方式(BSR、SSG、SSR)
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!