We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
这是 Next.js 搭建博客的第一章,整个系列会详细介绍如何结合 GitHub 和 Next.js 搭建自己的博客。
如果你想看已经部署博客的地址可以点击查看,代码仓库地址点击查看。
在正式开始之前,使用坚果云画了一份流程图,方便后续的理解。
整个流程都高度依赖 issues 和 labels,所以在正式讲解 Next.js 之前还需要思考怎么把当前仓库的所有 issues 和 labels 爬取下来,这里 GitHub 官方已经给出了相关的 api 文档,只需要参考调用即可。 不过这里额外补充一下,为什么需要把整体 issues 和 labels 拉取下来再进行 Next.js 拉取呢,主要有三个原因:
整体项目会最终采用一个 MonoRepo 的设计,采用的技术是 pnpm + workspace 形式,下面详细讲解下步骤。
pnpm init -y
packages: # 所有在 packages/ 子目录下的 package - "packages/**" # 不包括在 test 文件夹下的 package - "!**/test/**"
cd packages/sideEffect pnpm init -y
这个 sideEffect 文件最终就是我们加载各种副作用的一个文件夹,拉取 issues 的操作也在这里完成。
经过上面一些步骤,目前项目的大概雏形已经有了,下面安装一些必备的依赖项方便后续的操作
pnpm install axios dayjs dotenv fs-extra
之后进入settings/tokens设置个人令牌,在开发环境传递给 GitHub api 接口使用,否则会受到限制每小时只能请求 60 次。
这里贴一下官方的文档地址 issues,下一步就是把当前仓库所有信息拉取下来。
创建一个新的 api/index.ts 文件,我们所有相关的跟 GitHub api 都通过这个完成。
上面在 settings/tokens 创建一个新的 token 保存下来,在 sideEffect 下新建一个.env 文件,将 token 保存成下面键值对形式。
AUTHORIZATION=xxx # GITHUB_REPOSITORY是你的用户名+仓库名组成,根据你自己的仓库调整 GITHUB_REPOSITORY=bosens-China/blog
之后新建一个 utils/request.ts 文件,这个文件就是封装一下 axios 方便使用。
import axios from "axios"; export const instance = axios.create({ baseURL: "https://api.github.com/", timeout: 10000, headers: { Accept: "application/vnd.github+json", Authorization: `Bearer ${process.env.AUTHORIZATION}`, "X-GitHub-Api-Version": "2022-11-28", }, });
之后返回到 api/index.ts 文件
import { instance } from "../utils/request"; const { GITHUB_REPOSITORY } = process.env; export const issues = async (page = 1) => { const { data } = await instance.get<IssuesDaum[]>( `/repos/${GITHUB_REPOSITORY}/issues`, { params: { filter: "created", state: "open", sort: "updated", per_page: 100, page, }, } ); return data; }; export const labels = async (page = 1) => { const { data } = await instance.get<Label[]>( `/repos/${GITHUB_REPOSITORY}/labels`, { params: { per_page: 100, page, }, } ); return data; };
IssuesDaum 和 Label 是详细的类型定义文件这里忽略掉,如果需要相关类型文件可以点击访问。
之后新建 implement.ts 文件,这个文件就是调用 issues 和 labels 接口,然后把信息保存下来。
上面有说到根据 GitHub 的文档可以看到 labels 和 issues 都是返回一个数组,但是我们并不知道有没有拉取完,所以这边的思路就是创建一个新的文件,让他调用自身直到返回空数组为止。
const continued = async <T extends (page?: number) => Promise<unknown[]>>( fn: T, page = 1 ) => { const result = (await fn(page)) as ReturnType<T>; if (Array.isArray(result) && result.length) { const arr = await continued(fn, page + 1); result.push(...arr); } return result; };
最初的时候创建了一个.env 文件,这个文件是保存开发环境的一些信息,不过根据 esm 加载顺序我们必须要保证在调用其他模块的时候 dotenv 信息已经正确加载,所以这边思路如下。
创建一个立即执行函数,把需要执行的代码放里面执行即可,或者使用顶层 await 也可以,下面是完整代码
import dotenv from "dotenv"; import fs from "fs-extra"; import path from "path"; dotenv.config(); const { GITHUB_REPOSITORY } = process.env; (async () => { console.time(`Start crawling the required data...`); const { labels, issues } = await import("./api"); try { const [labelsData, issuesData] = await Promise.all([ continued(labels), continued(issues), ]); // 考虑到后续可能别人直接拷贝这个项目使用,对label一次插入 let other = labelsData.find((f) => f.name === "其他")!; if (!other) { other = { id: 1000000000, node_id: "MDU6TGFiZWwxMzcxNjg2NjEx", url: `https://api.github.com/repos/${GITHUB_REPOSITORY}/labels/其他`, name: "其他", color: "f6ecbf", default: false, description: "未找到分类,暂定的文章分类", }; labelsData.push(other); } const map: Map<string, typeof issuesData> = new Map(); issuesData.forEach((item) => { if (!item.labels.length) { item.labels.push(other); } item.labels.forEach((label) => { const id = `${label.id}`; if (!map.has(id)) { map.set(id, []); } map.get(id)?.push(item); }); }); await fs.writeJson( path.join(__dirname, "./data.json"), { label: labelsData, issuesData: issuesData, labelsMap: [...map], }, { spaces: 2 } ); } catch (e) { console.log(e instanceof Error ? e.message : e); } console.timeEnd(`Start crawling the required data...`); })();
上面的代码都是 TypeScript,不能直接运行,这里安装 tsx
pnpm add tsx
它的作用就是调用 TypeScript 代码,相比 ts-node 它不会进行类型检查,速度很快。
之后在 package.json 下的 scripts 下创建命令,方便快速调用
scripts: { "crawlingResource": "tsx ./src/implement.ts", }
之后执行 pnpm run crawlingResource,就可以看到在 src 下生成了一个 data.json 的文件。
pnpm run crawlingResource
data.json
这里再新建一个 index.ts 文件,方便对 data.json 进行一些封装查询操作。
import data from "./data.json"; // 对数据进行封装,方便调用 // eslint-disable-next-line @typescript-eslint/no-explicit-any export const classification = new Map(data.labelsMap as any) as Map< string, typeof data.issuesData >; const map = new Map<string, (typeof data.label)[number] | undefined>(); export const getLabel = (id: string) => { if (map.has(id)) { return map.get(id); } const result = data.label.find((f) => f.id === +id); map.set(id, result); return result; }; export default data;
到这里就把拉取资源的相关写完了,不过还需要在 package.json 暴露出口,让其他模块安装之后可以进行调用
"main": "./src/index.ts",
最后记得在当前目录创建一个新的.gitignore 文件,将.env 文件忽略。
第一节内容就讲完了,下一节会介绍 Next.js 构建博客之博客搭建,如果有书写错误欢迎指出。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
这是 Next.js 搭建博客的第一章,整个系列会详细介绍如何结合 GitHub 和 Next.js 搭建自己的博客。
如果你想看已经部署博客的地址可以点击查看,代码仓库地址点击查看。
在正式开始之前,使用坚果云画了一份流程图,方便后续的理解。
整个流程都高度依赖 issues 和 labels,所以在正式讲解 Next.js 之前还需要思考怎么把当前仓库的所有 issues 和 labels 爬取下来,这里 GitHub 官方已经给出了相关的 api 文档,只需要参考调用即可。
不过这里额外补充一下,为什么需要把整体 issues 和 labels 拉取下来再进行 Next.js 拉取呢,主要有三个原因:
项目初始化
整体项目会最终采用一个 MonoRepo 的设计,采用的技术是 pnpm + workspace 形式,下面详细讲解下步骤。
cd packages/sideEffect pnpm init -y
这个 sideEffect 文件最终就是我们加载各种副作用的一个文件夹,拉取 issues 的操作也在这里完成。
经过上面一些步骤,目前项目的大概雏形已经有了,下面安装一些必备的依赖项方便后续的操作
之后进入settings/tokens设置个人令牌,在开发环境传递给 GitHub api 接口使用,否则会受到限制每小时只能请求 60 次。
这里贴一下官方的文档地址 issues,下一步就是把当前仓库所有信息拉取下来。
拉取 issues and labels
创建一个新的 api/index.ts 文件,我们所有相关的跟 GitHub api 都通过这个完成。
上面在 settings/tokens 创建一个新的 token 保存下来,在 sideEffect 下新建一个.env 文件,将 token 保存成下面键值对形式。
AUTHORIZATION=xxx # GITHUB_REPOSITORY是你的用户名+仓库名组成,根据你自己的仓库调整 GITHUB_REPOSITORY=bosens-China/blog
之后新建一个 utils/request.ts 文件,这个文件就是封装一下 axios 方便使用。
之后返回到 api/index.ts 文件
之后新建 implement.ts 文件,这个文件就是调用 issues 和 labels 接口,然后把信息保存下来。
上面有说到根据 GitHub 的文档可以看到 labels 和 issues 都是返回一个数组,但是我们并不知道有没有拉取完,所以这边的思路就是创建一个新的文件,让他调用自身直到返回空数组为止。
最初的时候创建了一个.env 文件,这个文件是保存开发环境的一些信息,不过根据 esm 加载顺序我们必须要保证在调用其他模块的时候 dotenv 信息已经正确加载,所以这边思路如下。
创建一个立即执行函数,把需要执行的代码放里面执行即可,或者使用顶层 await 也可以,下面是完整代码
提供资产
上面的代码都是 TypeScript,不能直接运行,这里安装 tsx
它的作用就是调用 TypeScript 代码,相比 ts-node 它不会进行类型检查,速度很快。
之后在 package.json 下的 scripts 下创建命令,方便快速调用
之后执行
pnpm run crawlingResource
,就可以看到在 src 下生成了一个data.json
的文件。这里再新建一个 index.ts 文件,方便对 data.json 进行一些封装查询操作。
到这里就把拉取资源的相关写完了,不过还需要在 package.json 暴露出口,让其他模块安装之后可以进行调用
最后
最后记得在当前目录创建一个新的.gitignore 文件,将.env 文件忽略。
第一节内容就讲完了,下一节会介绍 Next.js 构建博客之博客搭建,如果有书写错误欢迎指出。
The text was updated successfully, but these errors were encountered: