如何托管前台和后台?
在本教程中,我们将全面介绍如何托管应用程序的前台和后台。
为此,我们将在 Back4app 上托管一个全栈应用程序。我们将首先开发后台,然后开发前台,最后连接这两个组件。
Contents
目标
本文结束时,您将能够
- 解释前台和后台的区别
- 使用Back4app 的 BaaS 解决方案构建后端
- 在Back4app 容器上部署前端应用程序
- 将前台应用程序与后台应用程序连接起来
前台和后台有什么区别?
后端和前端指的是构建现代网络和移动应用程序时的关注点分离。了解它们之间区别的最简单方法就是将冰山形象化。
前端(或客户端)是用户可以看到并与之交互的一切。前端有多种形式,如移动应用程序、网络应用程序、网络界面或其他任何类型的客户端。
该应用部分负责用户界面/用户体验、设计、动画、图形和其他媒体类型。客户端占项目工作的 20%,且不重复。
另一方面,后台(或服务器端)是用户看不到的一切。它是前端和数据库之间的桥梁。
它负责业务逻辑、后台任务、数据存储、扩展、第三方集成等。虽然用户不能直接与之交互,但它仍然对应用程序的质量有很大影响。
它约占项目工作的 80%,通常包括用户管理、身份验证、加密等重复性任务。
在本教程中,您将免费学习如何在 Back4app 上部署前台和后台!继续阅读,了解如何部署后端和前端。
项目介绍
我准备了一个全栈应用程序来演示如何在 Back4app 上部署前端和后端。
该应用程序是一个简单的标记符博客。管理员可以添加、编辑和删除文章,而用户则可以阅读文章。
最终项目将是这样的
如上所述,应用程序由两部分组成:前台和后台。如果我们将应用程序的架构可视化,它将看起来像这样:
我们将把后端部署到Back4app,把前端应用部署到Back4app Containers。最后,我们将通过Parse SDK 连接这两个组件。
我建议你先学习这个应用程序,然后通过部署你的全栈应用程序来测试你的知识。
继续阅读,了解如何托管后台和前台。
如何托管后台?
在本节中,我们将处理应用程序的后台部分。
目标
- 创建 Back4app 应用程序
- 定义数据库类
- 设置数据库 ACL/CLP
- 填充数据库
- 启用管理应用程序
创建 Back4app 应用程序
您需要注册一个免费的 Back4app 帐户,以便了解更多信息。如果您尚未注册,请免费注册!
要使用 Back4app,您首先需要创建一个应用程序。在 Back4app 上进行身份验证后,您将被重定向到应用程序视图。点击 “创建新应用程序 “按钮。
接下来,选择 “后台即服务”,因为我们要部署一个后台。
为应用程序命名,选择 “NoSQL “数据库,然后点击 “创建”。
平台需要一点时间来准备一切(如数据库、扩展、备份、应用层)。在此期间,您可以喝杯咖啡休息一下。
应用程序准备就绪后,您将看到数据库资源管理器。
定义数据库
在本节中,我们将学习数据库类。
我们只需要一个类,因为我们构建的是一个简单的应用程序。单击侧边栏上的 “创建类”,将其命名为 “文章
“,其他内容保持默认,然后单击 “创建类并添加列”。
添加以下五列:
+-----------+--------------+----------------+----------+
| Data type | Name | Default value | Required |
+-----------+--------------+----------------+----------+
| String | slug | <leave blank> | 1 |
+-----------+--------------+----------------+----------+
| String | title | <leave blank> | 1 |
+-----------+--------------+----------------+----------+
| File | cover | <leave blank> | 0 |
+-----------+--------------+----------------+----------+
| String | shortContent | <leave blank> | 1 |
+-----------+--------------+----------------+----------+
| String | content | <leave blank> | 1 |
+-----------+--------------+----------------+----------+
确保为您想存储的其他数据添加列。
默认情况下,数据库类处于 “保护模式”。如果我们想在前端应用程序中与它们交互,就必须稍微修改一下类级权限(CLP)。单击屏幕顶部的锁图标,然后像这样修改 CLP:
阅读以下文章,了解有关Parse 安全性的更多信息。
最后,在数据库中添加一些样本文章。
如果您没有任何想法,请随时导入该数据库转储。要导入它,请单击屏幕右上方的更多选项,然后点击 “导入 > 类数据”,然后导入 JSON。
很好,就是这样!
现在我们有了一些测试数据。
管理应用程序
目前,管理文章的唯一方法是通过 Back4app 数据库视图。这并不是最佳方式,因为您不想共享您的 Back4app 证书或将非技术人员添加到您的 Back4app 面板。
幸运的是,Back4app 为您的数据库模型提供了动态管理界面。要启用它,请选择侧边栏上的 “更多 > 管理应用程序”,然后点击 “启用管理应用程序”。
选择用户名、密码和管理应用程序子域。我选择
username: admin
password: verystrongpassword123
admin url: https://fullstack.admin.back4app.com/
现在,您可以通过选定的管理 URL 访问管理面板。
打开一个新标签页并导航至管理面板。使用您的凭据登录并浏览界面。您可以创建文章、更新文章,然后删除文章。
查看文档,了解有关 Back4app 管理应用程序的更多信息。
我们已经成功创建了一个完全成熟的后台,无需任何代码。
如何托管前端?
在本节中,我们将介绍前端应用程序。
目标
- 设置本地开发环境
- Dockerize 应用程序
- 在本地测试 Docker 映像
- 将源代码推送到 GitHub
- 将应用程序部署到 Back4app 容器中
本地设置
首先分叉该版本库的所有分支,然后将分叉克隆到本地计算机:
$ git clone <fork_remote_git_url> --branch dummy
$ cd back4app-heroku-deploy && git branch -m master
我们克隆了
虚拟
分支,因为它不包含后台代码。我们将在下一节讨论后台代码。
接下来,安装项目的依赖项:
$ npm install
最后,启动开发服务器:
$ npm run dev
打开您最喜欢的网络浏览器,导航至http://localhost:3000。您应该可以看到博客索引页面。尝试点击一篇文章,看看是否会重定向到文章详细信息页面。
目前,文章详情页是硬编码。别担心,我们稍后会解决这个问题。
Dockerize
要将应用程序部署到 Back4app Containers,必须先对其进行 dockerize。
Dockerization 是将代码打包到容器中的过程,容器可以部署到任何地方。对应用程序进行 Docker 化的最简单方法是使用Dockerfile。
Dockerfile
Dockerfile脚本包含创建 Docker 容器映像的说明。您可以使用该文件来定义环境、安装依赖项,并执行构建和运行应用程序所需的命令。
在项目根目录下创建一个Dockerfile,内容如下
# Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
RUN npm install -g next
EXPOSE 3000
CMD ["next", "start", "-p", "3000"]
此Dockerfile基于node:18-alpine
映像。它设置工作目录、处理依赖关系、复制项目并构建应用程序。
一旦应用程序构建完成,它就会暴露3000
端口,并启动一个监听该端口的 Next.js 服务器。
要了解有关 Dockerfiles 的更多信息,请查看官方文档。
.dockerignore
应尽量减小 Docker 镜像的大小。缩小 Docker 镜像大小的最简单方法是创建.dockerignore文件。通过该文件,你可以指定最终映像中应排除哪些文件和文件夹。
例如,你不想在镜像中包含 IDE 文件、构建文件、.git 文件或node_modules文件。
下面是一个.dockerignore文件的示例:
# .dockerignore
.idea/
/node_modules
/.next/
/out/
/build
.vercel
确保根据需要修改.dockerignore文件。
构建、运行、测试
在将 Docker 项目推送到云端之前,最好先在本地对其进行测试。测试Docker 文件的最简单方法是安装Docker Desktop。
安装完成后,您就可以创建图像了:
$ docker build -t blog-frontend:1.0 .
列出图像,查看是否成功创建了图像:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
blog-frontend 1.0 d361534a68da 2 minutes ago 1.08GB
使用刚刚构建的映像运行容器:
$ docker run -p 3000:3000 --name blog-frontend blog-frontend:1.0
打开您最喜欢的网络浏览器,导航至http://localhost:3000。您的应用程序应该就在那里!
要终止容器,请按键盘上的
CTRL + c
键。
推送到 GitHub
Back4pp Containers 与 GitHub 紧密集成。它提供了一个自动 CI/CD 系统,每次提交都会重新部署你的应用程序。要在下一节部署代码,必须先将更改推送到 VCS。
提交所有更改并将其推送到云端:
$ git add .
$ git commit -m "dockerized the application"
$ git push origin master
导航到 GitHub 代码库,确保Dockerfile在代码库中。
部署应用程序
您需要注册一个免费的Back4app 帐户,以便了解更多信息。如果您尚未注册,请免费注册!
首先,进入 Back4app 面板,点击 “构建新应用程序”。
由于我们部署的是 docker 化应用程序,因此请选择 “容器即服务”。
如果您是第一次使用 Back4app Containers,系统会要求您将 GitHub 账户与 Back4app 账户连接起来。确保启用对所有要部署的软件源的访问权限。
接下来,找到back4app-full-stack
软件仓库,点击 “选择”。
我们部署的应用程序不需要任何特殊配置。你只需提供一个描述性的 “应用程序名称”。我将使用back4app-full-stack
来保持条理清晰。
最后,点击 “部署”。
Back4app Containers 需要几分钟时间来构建和部署您的 Docker 映像。成功部署后,应用程序的状态将变为 “就绪”。
要访问您的应用程序,请单击绿色 URL,如下图所示。
很好,您已经成功地在 Back4app Containers 中部署了一个虚拟前端应用程序。
如何连接前台和后台?
在本节中,我们将把前端连接到 Back4app 后台。
目标
- 安装 Parse SDK
- 配置 Parse SDK
- 获取数据(如使用
ParseQuery)
安装 Parse SDK
首先,安装Parse SDK:
$ npm install parse
配置 Parse SDK
要初始化 Parse SDK,您必须提供 Back4app 的 “应用程序 ID “和 “JavaScript 密钥”。要获取它们,请导航至您的 Back4app 应用程序,选择侧边栏上的 “应用程序设置 > 安全与密钥”。
由于我们不想在源代码中公开这些秘密,因此需要创建一个.env.local文件:
# .env.local
NEXT_PUBLIC_PARSE_APPLICATION_ID=<your_parse_app_id>
NEXT_PUBLIC_PARSE_JAVASCRIPT_KEY=<your_parse_js_key>
确保用实际值替换占位符。
初始化 Parse SDK
接下来,导航到您的providers.js,然后像这样初始化 Parse:
// src/app/providers.js
// ...
import Parse from "parse/dist/parse";
const PARSE_APPLICATION_ID = process.env.NEXT_PUBLIC_PARSE_APPLICATION_ID;
const PARSE_JAVASCRIPT_KEY = process.env.NEXT_PUBLIC_PARSE_JAVASCRIPT_KEY;
Parse.initialize(PARSE_APPLICATION_ID, PARSE_JAVASCRIPT_KEY);
Parse.serverURL = "https://parseapi.back4app.com/";
export function Providers({children}) {
return (
// ...
);
}
为了能在所有视图中访问 Parse 实例,我们将使用 React 上下文。我们将使用React 上下文。
新建一个名为context/parseContext.js的文件,并在其中粘贴以下代码:
// src/app/context/parseContext.js
"use client";
import {createContext} from "react";
const ParseContext = createContext();
export default ParseContext;
接下来,用ParseContext
封装整个应用程序,并向其提供Parse
实例:
// src/app/providers.js
// ...
import ParseContext from "@/app/context/parseContext";
export function Providers({children}) {
return (
<CacheProvider>
<ColorModeScript initialColorMode={theme.config.initialColorMode} />
<ChakraProvider theme={theme}>
<ParseContext.Provider value={Parse}>
{children}
</ParseContext.Provider>
</ChakraProvider>
</CacheProvider>
);
}
就是这样!现在我们可以使用useContext()
钩子访问 Parse 实例了。
获取数据
我们要做的最后一件事是从后台获取数据。为此,我们将使用Parse.Query
。该类基本上是基于 Parse 的数据库的 ORM。
首先,用下面的内容替换src/app/page.jsx:
// src/app/page.jsx
"use client";
import NextLink from "next/link";
import {useContext, useEffect, useState} from "react";
import ParseContext from "@/app/context/parseContext";
import {Card, CardBody, Heading, Link, Spinner, Stack, Text} from "@chakra-ui/react";
export default function Home() {
const parse = useContext(ParseContext);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
const [articles, setArticles] = useState([]);
useEffect(() => {
(async () => {
try {
const query = new parse.Query("Article");
query.descending("createdAt");
const articles = await query.find();
setArticles(articles);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
})();
}, [parse.Query]);
if (loading) {
return <Spinner size="lg"/>;
}
if (error) {
return <Text color="red">{error}</Text>;
}
return (
<>
<Stack>
{articles.map((article) => (
<Card key={article.get("slug")}>
<CardBody>
<Stack>
<Heading size="lg">
<Link as={NextLink} href={article.get("slug")}>
{article.get("title")}
</Link>
</Heading>
<Text>{article.get("shortContent")}</Text>
</Stack>
</CardBody>
</Card>
))}
</Stack>
</>
);
}
- 我们通过
useContext()
钩子获得了 Parse 实例。 - 我们创建了一些状态,包括
加载
、出错
和文章
。 - 我们使用
useEffect()
钩子在页面打开时运行Parse.Query
。 Parse.Query
会获取按创建时间
排序的所有文章。- 我们修改了返回语句以呈现数据。
然后,用以下代码替换src/app/[slug]/page.js:
// src/app/[slug]/page.js
"use client";
import {formatDate} from "@/app/util/date-util";
import {useContext, useEffect, useState} from "react";
import ParseContext from "@/app/context/parseContext";
import {Card, CardBody, Heading, Image, Spinner, Stack, Text} from "@chakra-ui/react";
import ReactMarkdown from "react-markdown";
import ChakraUIRenderer from "chakra-ui-markdown-renderer";
export default function Article({params}) {
const parse = useContext(ParseContext);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
const [article, setArticle] = useState(null);
useEffect(() => {
(async () => {
try {
const query = new parse.Query("Article");
query.equalTo("slug", params.slug);
const article = await query.first();
if (!article) {
setError("This article does not exist.");
} else {
setArticle(article);
}
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
})();
}, [params.slug, parse.Query]);
if (loading) {
return <Spinner size="lg"/>;
}
if (error) {
return <Text color="red">{error}</Text>;
}
return (
<>
{article && (
<Stack>
<Card>
<CardBody>
<Stack>
<Heading as="h2" size="lg">{article.get("title")}</Heading>
<Text>Posted on {formatDate(article.get("createdAt"))}</Text>
{article.get("cover") && (
<Image
src={article.get("cover").url()}
alt={`${article.get("title")} cover`}
borderRadius="lg"
/>
)}
<ReactMarkdown
components={ChakraUIRenderer()}
children={article.get("content")}
skipHtml
/>
</Stack>
</CardBody>
</Card>
</Stack>
)}
</>
);
}
我们在上面的代码中使用了类似的概念。这两段代码的主要区别在于,我们获取的是一篇特定的文章,而不是这一段中的所有文章。
我们就大功告成了!继续在本地测试该项目:
$ next dev
确定一切正常后,将其推送到 VCS:
$ git add .
$ git commit -m "connected the frontend with the backend"
$ git push origin master
Back4app Containers 将自动根据最新更改重新部署您的应用程序。
结论
最后,我们成功地在 Back4app 上部署了一个全栈应用程序。通过这一过程,您获得了托管应用程序前端和后台的宝贵经验。现在,您部署自己的全栈应用程序应该不成问题了。
最终源代码可在back4app-full-stackrepo 上获取,你也知道了前端和后端托管在哪里。