使用 Next.js、Prisma 2 和 Docker 创建全栈博客应用 - 第一部分:设置 Repo 并配置后端
目录:
第一部分-设置 Repo 并配置后端
这篇文章将介绍如何使用 Docker 创建一个全栈 JavaScript 应用程序,其中使用 Next.js 实现服务器端渲染,并使用 Prisma 2 支持的 GraphQL 服务器,所有这些都由 Docker-Compose 进行编排。
为什么选择 Docker?
Docker 通过将技术栈的不同部分分离到单独的 Docker 容器中,彻底改变了 Web 开发。使用 Docker 开发代码,可以确保代码在开发环境和生产环境中的运行效果完全相同。
它是如何组织的?
我们在前端容器中运行 Next.js,在后端容器中运行连接到 Prisma 的 GraphQL Yoga,并在第三个容器中运行 Prisma Studio UI。我们从第四个容器中的 MySQL 数据库中读取数据,并将其提供给 Prisma UI 和后端服务器。
我们正在建造什么?
我们正在基于 Prisma 2 CLI 附带的示例博客项目构建一个博客 Web 应用。以下是我们可以从后端执行的操作:
查询:
- 阅读所有已发布的博客文章
- 阅读所有博客文章草稿
- 读取所有用户
突变:
- 创建用户
- 创建博客草稿
- 发布博客
- 删除博客
显然,在实际应用程序中,您永远不会允许任何人查看所有用户或未发布的博客文章 - 但在这里这样做是为了我们可以直接从我们的 Next.js 网站查看创建和修改的所有帖子和用户。
代码在哪儿?
目录:
第一部分 - 设置 Repo 并配置后端(本文)
- 创建基础 repo
- 创建 Next.js 前端
- 创建样板 Prisma 2 后端
- 将我们的 Web 应用程序 Docker 化
a. 创建 docker-compose 文件
b. 为每个容器添加 Dockerfile
- 配置后端
a. 将数据库从 SQLite 切换到 MySQL
b. 删除未使用的后端样板代码
c. 更新 Prisma Nexus 中的后端查询
- 验证我们的 Docker-Compose 集群正常运行
第二部分-配置前端
- 添加 GraphQL 片段、查询和解析器
- 添加 GraphQL-Codegen 用于生成 React 组件
- 添加 Apollo 并为 Next.js 创建 HOC
- 将 React-Apollo 添加到项目根目录
- 安装 Antd 以获得漂亮的网站布局
第三部分-构建 UI
- 创建主布局
- 创建用户布局组件
- 创建注册用户组件
- 创建 Feed 布局组件
- 创建新的草稿组件
- 创建发布草稿按钮组件
- 创建删除帖子按钮组件
下面我们将介绍该大纲的第一部分 - 请务必跳到最后观看介绍整个过程的视频。
第一部分-设置 Repo 并配置后端
1. 创建基础仓库
首先,让我们创建一个项目,并使用 nvm 设置正确的 Node 版本。如果您尚未安装 nvm,它是一个允许您在不同版本的 Node 和 npm 之间切换的工具。您可以在这里查看。
mkdir blog-prisma2
cd blog-prisma2/
nvm use 10.15.3
npm
现在我们可以使用 和来初始化项目git
。正如你可能从之前的博客文章中了解到的那样,我非常坚持良好的分支实践,所以现在让我们创建一个暂存分支和一个功能分支。
npm init -y
git init
git checkout -b staging
git checkout -b base
现在,我们在项目根目录中创建一个文件.gitignore
,并添加所有我们不想提交到仓库中的文件名和文件夹。在运行任何npm install
命令之前执行此操作非常重要,因为文件数量node_modules
非常庞大,我们不想提交它们。
logs
*.log
npm-debug.log*
pids
*.pid
*.seed
build/Release
**/node_modules
.DS_Store
.next/
现在运行以下命令进行首次提交。您可以随意使用 Git Kraken 或您喜欢的 git 工具:
git add .gitignore
git commit -am 'added gitignore'
2. 创建 Next.js 前端
现在让我们创建一个文件夹,并在其中创建一个新的 npm 项目。然后我们可以添加 React、next.js、next.js 的 CSS 加载器以及所有 TypeScript 依赖项。
mkdir frontend
cd frontend
npm init -y
npm install --save next react react-dom @zeit/next-css
npm install --save-dev @types/node @types/react @types/react-dom typescript
现在我们可以告诉 TypeScript 使用文件来实际运行tsconfig.json
。Make frontend/tsconfig.json
:
{
"compilerOptions": {
"allowJs": true,
"alwaysStrict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"jsx": "preserve",
"lib": ["dom", "es2017"],
"module": "esnext",
"moduleResolution": "node",
"noEmit": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"target": "esnext"
},
"exclude": ["node_modules"],
"include": ["**/*.ts", "**/*.tsx"]
}
在本教程的最后,我们将使用antd
它来设置所有的样式,所以让我们继续添加 CSS 支持,这样我们就可以在那时使用样式表了。创建一个 next-config 文件并向其中添加 css 插件:
制作frontend/next.config.js
:
const withCSS = require('@zeit/next-css')
module.exports = withCSS({})
现在我们可以创建一个frontend/next-env.d.ts
文件,其中包含我们项目中使用的 next.js 类型的引用:
/// <reference types="next" />
/// <reference types="next/types/global" />
现在我们有了这些基础文件,就可以开始创建 React 组件了。首先整理一下,创建frontend/components
和frontend/pages
文件夹。然后创建frontend/pages/index.tsx
:
import * as React from 'react'
import { NextPage } from 'next'
const IndexPage: NextPage = () => {
return <h1>Index Page</h1>
}
export default IndexPage
Next.js 遵循的惯例是,pages 目录中的 React 组件是网站的路由。index 页面代表/
路由,而在上面我们的 React 组件中,我们只是创建了一个显示 h1 标题的页面。
现在我们需要将 next.js 脚本添加到frontend/package.json
文件中,以便我们可以轻松启动和停止前端服务器:
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"type-check": "tsc"
},
Next.js 8.1.1 原生支持 TypeScript,而这正是我们项目所需的。请快速检查一下文件中的版本frontend/package.json
是否已更新。截至 2019 年 7 月初,执行npm install
Next.js 编译将返回 8.1.0 版本,因此我需要手动将版本号修改package.json
为:
"next": "^8.1.1-canary.61",
npm install
如果需要更新它,请确保在编辑文件后运行package.json
以获取最新版本。
接下来,运行 启动服务器npm run dev
。前往http://localhost:3000
并确认索引页已打开:
一旦您确信它正在运行,请按 ctrl+c 停止前端服务器。
3. 创建 Prisma 2 样板后端
现在我们必须创建后端。返回目录blog-prisma2
并初始化 Prisma 2。
npm install -g prisma2
prisma2 init backend
// Select SQLite
// Select Photon and Lift
// Select Typescript
// Select GraphQL Boilerplate
这个过程将创建一个名为 backend 的文件夹,它将使用 Prisma 2 将博客后端克隆到该文件夹中。我们可以直接启动它并从那里移动,但我们将立即启动将其集成到 docker 中的过程,这样我们就不必再处理 SQLite 了,而是从一开始就将我们的后端连接到 MySQL 数据库。
4. Docker化我们的Web应用程序
a.创建一个 docker-compose 文件。
现在我们要将我们的应用程序docker化。docker-compose.yml
在项目根目录中创建。
version: '3.7'
services:
mysql:
container_name: mysql
ports:
- '3306:3306'
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: prisma
MYSQL_ROOT_PASSWORD: prisma
volumes:
- mysql:/var/lib/mysql
prisma:
links:
- mysql
depends_on:
- mysql
container_name: prisma
ports:
- '5555:5555'
build:
context: backend/prisma
dockerfile: Dockerfile
volumes:
- /app/prisma
backend:
links:
- mysql
depends_on:
- mysql
container_name: backend
ports:
- '4000:4000'
build:
context: backend
dockerfile: Dockerfile
volumes:
- ./backend:/app
- /app/node_modules
- /app/prisma
frontend:
container_name: frontend
ports:
- '3000:3000'
build:
context: frontend
dockerfile: Dockerfile
volumes:
- ./frontend:/app
- /app/node_modules
- /app/.next
volumes: #define our mysql volume used above
mysql:
让我们看一下这个文件。它分为 4 个服务:mysql、prisma、backend 和 frontend。我们已经创建了前端服务器,并在 docker 容器外进行了测试,现在我们将把它迁移进去。prisma 容器用于 Prisma Studio UI,backend 是我们的后端服务器,mysql 是我们的数据库。以下是每个服务中的关键字段及其作用:
-
container_name
这就是我们所说的容器——为了简单起见,它与服务名称相匹配。 -
image
如果我们正在从 docker hub 下载图像,我们会将其放在这里。 -
build
如果我们不从 docker hub 下载,我们将构建我们的图像,并且这个块提供有关哪个文件夹是构建的工作目录以及我们的名称Dockerfile
是什么(我们将在下面创建)的说明。 -
environment
任何环境变量都在这里。 -
restart
确保容器死亡时我们重新启动它。 -
links
并depends_on
在两个容器之间建立连接,并指定特定容器在启动之前应等待不同的容器。 -
volumes
指定容器应创建哪种类型的卷。带冒号的卷:
表示我们正在创建计算机上某个文件夹与容器中某个路径之间的链接。不带冒号的卷表示它将在构建步骤中保存该文件夹,以便我们在容器运行时使用它。这一点很重要,node_modules
例如,我们希望确保 Docker 容器在npm install
构建阶段保留该文件夹,因为该文件夹是运行应用程序所必需的。
现在让我们在基础文件(不是前端或后端)中添加一些脚本,使我们的工作更轻松package.json
:
"start": "docker-compose up",
"build": "docker-compose build",
"stop": "docker-compose down",
"clean": "docker system prune -af",
"clean:volumes": "docker volume prune -f",
"seed": "docker exec -it prisma npm run seed",
b.为每个容器添加 Dockerfile。
现在我们需要创建Dockerfile
前端、后端和 Prisma 容器。这些文件包含启动服务器所需的步骤。添加以下三个 Dockerfile:
frontend/Dockerfile
:
FROM node:10.16.0
RUN mkdir /app
WORKDIR /app
COPY package*.json ./
RUN npm install
CMD [ "npm", "run", "dev" ]
backend/Dockerfile
:
FROM node:10.16.0
RUN npm install -g --unsafe-perm prisma2
RUN mkdir /app
WORKDIR /app
COPY package*.json ./
COPY prisma ./prisma/
RUN npm install
RUN prisma2 generate
CMD [ "npm", "start" ]
backend/prisma/Dockerfile
:
FROM node:10.16.0
RUN npm install -g --unsafe-perm prisma2
RUN mkdir /app
WORKDIR /app
COPY ./ ./prisma/
CMD [ "prisma2", "dev"]
它们都以一个FROM
块开头,这个块就是我们要拉取的镜像。在我们的例子中,我们使用的是 Node.js 的官方版本。然后,我们创建一个app
文件夹,将package.json
和复制package-lock.json
到其中,这样我们就可以运行npm install
来获取所有的包。
我们将该prisma
文件夹复制到后端服务器,以便生成基于我们prisma.project
文件构建的 Prisma 依赖项。这里巧妙之处在于,当我们修改架构时,生成的依赖项也会随之更改以匹配它。Prisma 容器需要 Prisma 文件夹才能针对我们的数据库执行迁移,以创建与架构匹配所需的所有不同表。
我们的前端Dockerfile
更简单,因为它只需要安装所有包依赖项,而不需要了解prisma
文件夹。
配置后端
a. 将数据库从 SQLite 切换到 MySQL
我们有 docker-compose 文件,但你会注意到,我们在这个文件中使用了 MySQL,而在 Prisma 设置步骤中我们指定了 SQLite。让我们通过更新backend/prisma/project.prisma
文件来解决这个问题。使用以下命令更新数据源 db 块:
datasource db {
provider = "mysql"
url = "mysql://root:prisma@mysql:3306/prisma"
}
请注意,我们为其提供了一个连接字符串,其中包含我们在文件中指定的密码和数据库名称docker-compose.yml
。
b. 删除未使用的后端样板代码
现在我们可以删除我们项目不会使用的以下文件。
backend/src/permissions/*
backend/src/resolvers/*
backend/src/utils.ts
backend/README.md`
c. 更新 Prisma Nexus 中的后端查询
在 backend/src/index.ts 文件中,添加用户查询:
t.list.field('users', {
type: 'User',
resolve: (parent, args, ctx) => {
return ctx.photon.users.findMany({})
},
})
在同一个文件中,向feed
名为 的查询添加一个布尔值输入published
,我们可以在其中指定是否需要已发布的帖子。确保在文件顶部的booleanArg
导入语句中添加:@prisma/nexus
import {
idArg,
makeSchema,
objectType,
stringArg,
booleanArg,
} from '@prisma/nexus'
// Lines of code omitted for brevity...
//
//
t.list.field('feed', {
type: 'Post',
args: {
published: booleanArg(),
},
resolve: (parent, { published }, ctx) => {
return ctx.photon.posts.findMany({
where: { published },
})
},
})
6. 验证 Docker-Compose 集群是否正常工作
我们用它npm run build
来构建镜像,然后npm start
启动项目。我们可以npm run stop
使用 clean 命令停止项目,并清理卷、镜像和容器。
接下来,如果我们使用 npm 安装新的依赖包,需要停止项目并重新构建,以确保 Docker 镜像是最新的。如有疑问,npm stop
后面跟着npm run clean
应该可以解决问题。
现在我们需要构建镜像以确保它们能够正常工作。在项目根目录中输入:
npm run build
现在我们已经构建了镜像,让我们开始吧npm start
。首先转到http://localhost:3000
。我们应该看到我们的 Next.js 应用程序:
现在让我们转到http://localhost:4000
,我们应该看到我们的后端 GraphQL 游乐场:
最后,让我们转到http://localhost:5555
,我们应该看到 Prisma Studio 应用程序:
太棒了!我们已经创建了一个初始的 docker-compose 环境,其中运行着 3 个 Web 服务器和一个数据库服务器,只需一个命令即可启动。现在,让我们将工作保存到 git 中,然后简化所有操作,以便我们有一个良好的基础。
git add .
git commit -am 'added base projects'
现在我们已经完成了后端所需的所有更改。在本文的第二部分,我们将讨论前端。
第一部分的视频系列:
架构概述
我们正在构建什么
使用 Git 和 NPM 设置我们的项目
创建 Next.js 前端
创建 Prisma 2 后端
创建我们的 Docker Compose
创建我们的 Dockerfiles
将 Prisma 2 连接到 MySQL
向我们的后端添加新的查询
启动我们的Docker环境
还有更多精彩内容!
点击此处提供您的邮箱地址,我们会在发布新内容时通知您。我们尊重您的邮箱隐私,绝不会向您发送垃圾邮件,您也可以随时取消订阅。
最初发表于Code Mochi。
继续阅读 https://dev.to/codemochi/create-a-fullstack-blog-app-with-next-js-prisma-2-and-docker-part-i-setup-the-repo-and-configure-the-backend-39eb