介绍
单独管理前端和后端的设置可能会耗费时间和令人沮丧。单代码库可以将这两个应用程序合并到一个代码库中,从而让开发和维护更加轻松。
在这个项目中,我们使用Turborepo来建立一个包含前端和后端的单一代码库,前端使用React作为前端,后端使用Express.js作为后端。Turborepo允许我们为每个应用保持独立的环境、包配置和依赖,同时,它们仍能无缝协作。
在继续往下读之前,请查看react-express-monorepo GitHub 项目,以便更清楚地了解整体结构。
今天这篇博客,我们将介绍如何搭建开发服务器、管理环境配置以及处理生产问题,确保一切在一处顺利运行。
为何选择 Turborepo?管理单独管理前端和后端的设置可能会既耗时又令人沮丧。虽然有多重方法可以简化这个过程,这个项目使用了Turborepo来创建一个单仓库。
Turborepo 允许为不同应用维护独立的环境、package.json
文件和 node_modules
,同时仍能使其无缝协作。这提供了独立开发每个应用的灵活性,同时也带来了统一单存储库结构的优势。
问题:前端和后端用不同的端口
在这套配置中,前端使用了Vite,默认运行在localhost:5173
,而后端使用Express.js,假设运行在端口3000
上。API 以 /api
开头,但目标是让前端仅使用 /api
(例如 /api/user/1
)进行请求,而不是直接访问 localhost:3000/api
。这样内部会将请求路由到后端的 localhost:3000
。
解决办法:Vite 代理
可以在 Vite 中配置代理,将请求转发到后端。这样一来,任何对 /api
或 /api/*
的请求都会被转发到 localhost:3000/api
,从而实现前后端的无缝通信。
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
// https://vitejs.dev/config/
// 定义配置,用于配置插件和其他开发服务器设置
export default defineConfig({
plugins: [react()],
// 设置插件,使用 react 插件进行编译
server: {
proxy: {
"/api": {
// 设置代理,将 /api 请求转发到 http://localhost:3000
target: "http://localhost:3000",
changeOrigin: true
}
}
}
});
这样的代理配置将确保前端发往 /api
的请求将会被转发到后端的 localhost:3000
。
注意: 请注意,所有后端路由都应以 /api
开头,以确保正确路由。比如 /api/users
,以使得说明更加具体和易于理解。
// Express.js 路由定义
app.get("/api", (req, res) => {
res.send("Hello, World!");
});
// 这是一个用于返回 'OK' 的健康检查路由
app.get("/api/health", (req, res) => {
res.send("OK");
});
这保证前端和后端保持一致,并且所有的API路由都正确地代理。
问题2:一次性使用一条命令启动两个开发服务器
目标是通过一个命令,例如 pnpm dev
,启动前端和后端的开发服务器,并采用同样的方式来打包构建、代码检查以及启动生产环境的服务器。
要实现这一点,所有应用程序都应该放在一个 apps
文件夹里,例如,
- 前端代码 :
apps/react
- 后端代码 :
apps/express
在每个应用的 package.json
文件中定义了相同的 dev
、build
、lint
和 start
命令后,我们就可以用 Turborepo 来高效管理这些命令。下面是如何设置的:
在 apps/react/package.json
文件中:
{
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
}
}
Express 后端开发 (Express hòu duān kāfā)
打开 apps/express/package.json
文件,可以看到:
{
"scripts": {
"dev": "tsx watch --clear-screen=false src/index.ts # 开发模式命令,用于监视并编译src/index.ts文件",
"build": "tsup # 构建命令,用于打包项目",
"start": "node dist/index.js # 启动命令,用于运行dist/index.js文件"
}
}
TurboRepo (全栈)
在根目录下的 package.json
文件中,使用 dotenvx 来加载 CLI 的环境变量。turbo
命令将协调运行前端和后端的脚本。
{
"scripts": { // 脚本定义 (define scripts)
"dotenvx": "dotenvx", // dotenvx 环境变量管理工具 (dotenvx is an environment variable management tool)
"build": "dotenvx run -- turbo build", // 构建项目 (build the project)
"dev": "dotenvx run -- turbo dev", // 开发环境启动 (start development environment)
"lint": "dotenvx run -- turbo lint", // 代码检查 (code linting)
"start": "node apps/express/dist/index.js" // 启动 Express 应用程序 (start the Express application)
}
}
这样一来,我们可以确保以下几点:
- 运行
pnpm dev
将同时运行前端和后端的开发脚本。 pnpm build
会构建前端和后端。pnpm lint
会进行前端和后端的代码检查。pnpm start
将启动生产后端。
在这种情况下,环境变量通过dotenvx注入到CLI中。虽然Vite(前端)可以轻松访问这些环境变量,但Express.js(后端)无法直接获取这些环境变量,除非进行额外配置。
使用方法:使用dotenvx
并使用相对路径
为了确保 Express.js 能访问全局环境变量,需要使用 dotenvx(或 dotenv)配置一个相对于全局 .env
文件的路径。可以这样配置:
import dotenv from "@dotenvx/dotenvx";
import path from "path";
dotenv.config({
path: path.join(__dirname, "../../../.env"), // 请根据实际情况修改路径
});
通过指定全局 .env
文件的路径,后端可以像前端一样访问相同的环境变量,确保前后端应用的一致性。这样,后端可以像前端一样访问相同的环境变量,确保前后端应用的一致性。
Vite 代理配置在部署时不起作用,遇到了问题
在实际生产环境中,Vite 的代理设置在实际生产中不起作用了,因为在打包过程中,React 被转换成了静态文件(如 HTML、CSS 和 JS)。因此,直接将API请求代理到后端已经不可能了。
后端服务静态文件的技巧一个简单的解决方法是从后端服务器提供前端的静态文件。后端会提供静态文件,任何未匹配的路由(除了API路由之外的)将回退到前端应用。
步骤如下:- 服务静态文件: 使用《Express.js》来提供构建的 React 前端文件。
// 用于提供静态文件服务
app.use(express.static(path.join(__dirname, "../../react/dist")));
- 未匹配路由的默认处理方式: 如果某个路由与任何 API 路由都不匹配,则提供构建中
index.html
文件。这样 React Router(如果有在用的话)就能处理客户端的路由了。
如果任何API路由不匹配,则回退到前端显示,即发送请求到前端的HTML文件。
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "../../react/dist/index.html"));
});
有了这种设置,后端将服务静态的前端文件,并通过由 React 应用程序接管来处理所有非 API 路由,确保客户端路由在生产中正常运作。
结论使用Turborepo可以同时管理前端和后端代码,让开发过程变得更加简单和高效。这样我们可以在一个地方搞定所有事情,同时在需要时仍然可以保持前端和后端的分离。
通过遵循此设置,你可以让你的工作流程更简单,使应用开发和部署更快捷。
想了解更多,请查看react-express-monorepo GitHub 仓库页面,查看设置情况。
共同学习,写下你的评论
评论加载中...
作者其他优质文章