Quickstarters
How to Build a Qwik Frontend and Connect It to a Backend?
29 分
在本教程中,您将使用 qwik 构建一个待办事项列表应用程序,并将其连接到由 back4app 提供强大后端支持的系统。 本指南专为希望利用 qwik 的可恢复性和懒加载功能,同时与托管后端集成基本 crud(创建、读取、更新、删除)操作的开发人员量身定制。 到最后,您将拥有一个功能齐全的应用程序,展示如何将现代 qwik 前端与 back4app 的可靠后端服务结合起来。 构建全栈应用程序可能具有挑战性,因为它涉及后端设置、数据库管理、身份验证和部署。 为了简化这些任务,我们使用 back4app— https //blog back4app com/backend as a service baas/ 解决方案—这样您就可以专注于构建您的 qwik 应用程序,而它则负责托管、数据库和 api。 back4app 提供了一整套后端服务,包括现成的 nosql 数据库、身份验证、用于服务器端逻辑的云代码以及流畅的 sdk 集成。其容器化部署支持使其成为现代全栈应用程序的优秀选择。 借助这些工具,您可以快速开发和部署应用程序,而无需管理服务器基础设施的开销。 关键要点 通过遵循本教程,您将学习到: 初始化一个现代的 qwik 项目。 集成后端服务以管理您的应用程序数据。 为交互式用户界面实现基本的 crud 操作。 部署一个 https //todoapp ku5ofg8s b4a run/ ,使用 back4app 上的容器化工作流。 先决条件 在您开始之前,请确保您具备以下条件: node js 和 npm 从 https //nodejs org/ 安装最新的 lts 版本,并通过 node v 和 npm v 进行验证。 基本的 qwik 知识 熟悉 qwik 的组件、信号(使用 usesignal )和其可恢复性概念是推荐的。如果您是 qwik 新手,请先查看其文档。 一个 back4app 账户 在 https //www back4app com/ 注册以设置和管理您的后端服务。 在具备这些先决条件后,您就可以开始设置项目并开始构建。 项目设置 首先设置您的本地开发环境并初始化您的 qwik 项目。 确认已安装 node js (lts 版本) node v npm v 使用 qwik cli 创建一个新的 qwik 项目。运行以下命令: npm create qwik\@latest 回答 cli 提供的提示。将项目命名为 todo app 或用您喜欢的任何名称替换。 切换到您的项目目录: cd todo app 启动开发服务器以验证您的设置: npm start 您的 qwik 应用现在应该在本地运行。打开提供的 url 以确认。接下来,您将配置 back4app 上的后端以管理数据存储和 api 交互。 创建待办事项后端 back4app 提供一个完全托管的后端服务,基于 parse 该服务提供一个 nosql 数据库、身份验证、云代码和自动生成的 api。 本节指导您创建一个 task 数据模型,以存储您的待办事项,并将其与您的 qwik 前端链接。 设置您的后端应用程序 登录 到您的 https //www back4app com/ 并点击 "创建新应用。" 命名您的应用程序 (例如, todoqwikapp ) 并选择 nodejs/parse 作为后端类型。 创建后,导航到 "数据库" > "浏览器" 点击 "创建一个类" 并选择 "自定义" 命名该类为 task 并设置 类级别权限 以允许公共读取和写入(您可以稍后细化这些设置)。 在 task 类中,添加以下字段: 标题 (字符串)– 任务的标题。 描述 (字符串)– 关于任务的详细信息。 完成 (布尔值)– 指示任务是否已完成。 截止日期 (日期)– 任务的截止日期。 点击 "保存" 以完成您的模式。 将 back4app 与 qwik 集成 使用 parse javascript sdk 将 back4app 集成到您的 qwik 项目中。通过 npm 安装 sdk npm install parse 通过使用您的 应用程序 id 和 javascript 密钥 来初始化 sdk。 从您的 back4app 仪表板的 应用设置 > 安全性与密钥 中获取这些凭据。 创建一个配置文件(例如, src/lib/parse js ) 并添加以下内容: import parse from "parse/dist/parse min js"; const parse app id = 'your application id'; const parse js key = 'your javascript key'; const parse server url = 'https //parseapi back4app com/'; parse initialize(parse app id, parse js key); parse serverurl = parse server url; export default parse; 您现在可以在您的 qwik 组件和路由中导入此配置,以与您的后端进行交互。 使用 qwik 开发前端 现在您的后端已连接,使用 qwik 构建您的待办事项应用程序的用户界面。您将创建组件来添加、显示、更新和删除任务,同时使用 qwik 信号管理状态。 组织您的组件 您的应用程序将包括以下关键组件: taskform tsx – 一个处理添加新任务的组件。 tasklist tsx – 一个显示所有任务并提供标记任务完成或删除它们的控件的组件。 taskitem tsx – 一个表示单个任务的组件,具有切换完成状态或删除它的操作。 在 src 中创建一个 components 文件夹并添加这些文件: mkdir src/components touch src/components/taskform tsx src/components/tasklist tsx src/components/taskitem tsx 使用 qwik 信号管理状态 利用 qwik 的 usesignal 进行响应式状态管理。在你的主页面(例如, src/routes/index tsx ),按如下方式设置状态和数据获取: import { component$, usesignal, usevisibletask$, $ } from '@builder io/qwik'; import parse from ' /lib/parse js'; import taskform from ' /components/taskform'; import tasklist from ' /components/tasklist'; export default component$(() => { const tasks = usesignal< { id string; createdat string; updatedat string; title string; description string; completed boolean; }\[] \>(\[]); const fetchtasks = $ ( async () => { try { const task = parse object extend("task"); const query = new parse query(task); const results = await query find(); tasks value = results map(task => ({ id task id ?? '', createdat task createdat ? task createdat toisostring() '', updatedat task updatedat ? task updatedat toisostring() '', title task get('title') ?? '', description task get('description') ?? '', completed task get('completed') ?? false, })); } catch (error) { console error("error fetching tasks ", error); } }); usevisibletask$(async () => { await fetchtasks(); }); return ( \<div class="container"> \<h1>to do list\</h1> \<taskform ontaskadded$={fetchtasks} /> \<tasklist tasks={tasks value} ontaskschange$={fetchtasks} /> \</div> ); }); 构建任务表单组件 在 src/components/taskform tsx , 创建一个表单组件来添加任务。使用 qwik 的响应信号作为表单输入: import { component$, usesignal, $, qrl } from '@builder io/qwik'; import parse from ' /lib/parse js'; interface taskformprops { ontaskadded$ qrl<() => void>; } export default component$((props taskformprops) => { const title = usesignal(''); const description = usesignal(''); const handlesubmit$ = $(async (e event) => { e preventdefault(); try { const task = parse object extend("task"); const task = new task(); task set("title", title value); task set("description", description value); task set("completed", false); await task save(); title value = ''; description value = ''; return true; } catch (error) { console error("error adding task ", error); return false; } }); return ( \<form preventdefault\ submit onsubmit$={async (event) => { const success = await handlesubmit$(event); if (success) { await props ontaskadded$(); } }} \> \<input type="text" placeholder="task title" value={title value} oninput$={(e) => title value = (e target as htmlinputelement) value} required /> \<input type="text" placeholder="description" value={description value} oninput$={(e) => description value = (e target as htmlinputelement) value} required /> \<button type="submit">add task\</button> \</form> ); }); 构建任务列表和项目组件 在 src/components/tasklist tsx , 渲染任务列表 import { component$ } from '@builder io/qwik'; import taskitem from ' /taskitem'; interface task { id string; title string; description string; completed boolean; } interface tasklistprops { tasks task\[]; ontaskschange$ () => void; } export default component$((props tasklistprops) => { return ( \<div> {props tasks length === 0 ? ( \<p>no tasks available\</p> ) ( props tasks map(task => ( \<taskitem key={task id} task={task} ontaskschange$={props ontaskschange$} /> )) )} \</div> ); }); 在 src/components/taskitem tsx , 创建一个用于单个任务的组件,具有切换完成状态或删除任务的操作 import { component$, $ } from '@builder io/qwik'; import parse from ' /lib/parse js'; interface task { id string; title string; description string; completed boolean; } interface taskitemprops { task task; ontaskschange$ () => void; } export default component$((props taskitemprops) => { const handletoggle = $(async () => { try { const query = new parse query("task"); const tasktoupdate = await query get(props task id); tasktoupdate set("completed", !props task completed); await tasktoupdate save(); props ontaskschange$(); } catch (error) { console error("error updating task ", error); } }); const handledelete = $(async () => { try { const query = new parse query("task"); const tasktodelete = await query get(props task id); await tasktodelete destroy(); props ontaskschange$(); } catch (error) { console error("error deleting task ", error); } }); return ( \<div class={`task item ${props task completed ? "completed" ""}`}> \<h3>{props task title}\</h3> \<p>{props task description}\</p> \<button onclick$={handletoggle}> {props task completed ? "undo" "complete"} \</button> \<button onclick$={handledelete}>delete\</button> \</div> ); }); 为您的应用程序设置样式 创建一个 src/global css 文件以添加基本样式: / src/global css / container { max width 600px; margin 40px auto; padding 0 20px; text align center; font family sans serif; } container h1 { margin bottom 20px; } form { display flex; flex direction column; align items center; gap 10px; margin bottom 20px; } form input\[type="text"] { width 80%; max width 400px; padding 8px; box sizing border box; font size 1rem; } form button { padding 8px 16px; cursor pointer; font size 1rem; border none; background color #eaeaea; transition background color 0 2s ease; } form button\ hover { background color #ccc; } container p { font size 1rem; } task item { display flex; flex direction column; align items center; justify content center; gap 12px; border 1px solid #ccc; border radius 6px; padding 15px; margin 10px 0; background color #fafafa; text align center; transition background color 0 2s ease; } task item completed h3, task item completed p { text decoration line through; color #888; } task item h3 { margin 0; font size 1 1rem; } task item p { margin 0; font size 1rem; } task item button { padding 6px 12px; border none; background color #eaeaea; cursor pointer; font size 0 9rem; } task item button\ hover { background color #ccc; } @media (min width 600px) { task item { flex direction row; } } 在你的根文件中导入全局样式(例如, src/root tsx ) import " /global css"; 完成用户界面 你的 qwik 待办事项应用程序现在具有与 back4app 集成的动态前端和自定义样式。该应用程序允许你添加、显示、更新和删除任务,同时确保前端和后端之间的顺畅通信。 接下来,你将使用 back4app 的 web 部署平台部署你的 qwik 应用程序。 在 back4app 上部署前端 back4app web deployment 提供了一个完全托管的、容器化的环境来托管您的应用程序。通过基于 docker 的部署,您可以打包您的 qwik 应用并无缝部署。 添加 express 服务器适配器 qwik 允许您为特定目标配置部署适配器。我们将添加 express 适配器以在生产中服务您的项目。 安装适配器: npm run qwik add 然后选择 适配器:node js express 服务器 并确认安装。这将更新您的 readme 并在您的 package json 中添加新的部署脚本。 更新启动脚本: 打开 package json 并将启动脚本更改为: "start" "node server/entry express" 可选地,如果需要,可以保留一个单独的开发脚本。这确保您的项目使用 express 来服务生产构建。 为生产配置 qwik 使用以下命令构建您的生产就绪 qwik 网站: npm run build 为您的应用创建 dockerfile 在项目根目录创建一个 dockerfile 以容器化您的 qwik 应用程序 # build stage from node\ lts alpine as builder user node workdir /home/node copy package json run npm ci copy chown=node\ node run npm run build \# final run stage from node\ lts alpine as runner env node env=production user node workdir /home/node copy from=builder chown=node\ node /home/node/package json copy from=builder chown=node\ node /home/node/node modules /node modules copy from=builder chown=node\ node /home/node/dist /dist copy from=builder chown=node\ node /home/node/server /server arg port expose ${port 3000} cmd \["node", "server/entry express"] 推送到 github 并通过 back4app 部署 将您的项目推送到 github git init git add git commit m "initial commit for back4app deployment" git branch m main git remote add origin \<your github repository url> git push u origin main 然后,使用 back4app web 部署 登录到 https //www back4app com/containers 点击 "创建新应用" , 提供一个名称,并选择 github 仓库 授权 back4app 访问您的仓库并选择您的 qwik 项目仓库。 选择 dockerfile 部署 并确认构建设置。 点击 "部署" 以启动构建过程。 监控和管理部署 部署后,使用 back4app 仪表板来 查看日志以进行故障排除。 监控容器性能和资源使用情况。 当有新提交时触发重新部署。 如有需要,配置自定义域名。 测试和调试您的应用程序 一旦部署,彻底测试您的 qwik 应用程序: 验证 api 连接: 打开浏览器的开发者控制台 (f12 → 网络) 以检查任务操作期间的 api 调用。 添加和检索任务: 使用 ui 添加任务,然后刷新以确认数据在 back4app 数据库浏览器中的持久性。 测试 crud 操作: 确保标记任务完成和删除在后端正确反映。 处理边缘情况: 验证表单输入并使用开发者工具模拟慢速网络条件。 如果出现问题,请查看 back4app 日志或仔细检查您的 api 配置。 使用 back4app 服务的最佳实践 通过以下方式增强应用程序的性能和安全性: 优化 api 调用: 对于多个操作使用批量请求,并仅查询必要的字段。 保护敏感数据: 将应用程序 id 和 javascript 密钥等凭据存储在环境变量中。在 qwik 中,创建一个 env 文件: vite parse app id=your app id vite parse js key=your js key 启用自动扩展: 在 back4app web 部署中激活自动扩展以管理高流量。 增强安全性: 限制类级别权限 (clps) 以控制数据修改,并根据需要设置 acl。 利用云代码: 将复杂逻辑卸载到云代码中,以提高性能并减少 api 暴露。 结论 您现在已经使用 qwik 构建了一个全栈待办事项应用程序,前端使用 qwik,后端使用 back4app 的强大服务。 本教程指导您设置 qwik 项目,集成 parse sdk,并使用 back4app 上的容器化工作流部署您的网站。 在继续开发时,请考虑添加高级用户身份验证、实时更新和第三方集成等功能。 有关更多信息和支持,请参考 https //www back4app com/docs 。

