Quickstarters
How to Build a Qwik Frontend and Connect It to a Backend?
29 分
在本教程中,您将使用 qwik 构建一个待办事项列表应用程序,并将其连接到由 back4app 提供强大后端支持的系统。 本指南专为希望利用 qwik 的可恢复性和懒加载功能,同时与托管后端集成基本 crud(创建、读取、更新、删除)操作的开发人员量身定制。 到最后,您将拥有一个功能齐全的应用程序,展示如何将现代 qwik 前端与 back4app 的可靠后端服务结合起来。 构建全栈应用程序可能具有挑战性,因为它涉及后端设置、数据库管理、身份验证和部署。 为了简化这些任务,我们使用 back4app— 一个可扩展的后端即服务(baas) 解决方案—这样您就可以专注于构建您的 qwik 应用程序,而它则负责托管、数据库和 api。 back4app 提供了一整套后端服务,包括现成的 nosql 数据库、身份验证、用于服务器端逻辑的云代码以及流畅的 sdk 集成。其容器化部署支持使其成为现代全栈应用程序的优秀选择。 借助这些工具,您可以快速开发和部署应用程序,而无需管理服务器基础设施的开销。 关键要点 通过遵循本教程,您将学习到: 初始化一个现代的 qwik 项目。 集成后端服务以管理您的应用程序数据。 为交互式用户界面实现基本的 crud 操作。 部署一个 功能齐全的待办事项应用程序 ,使用 back4app 上的容器化工作流。 先决条件 在您开始之前,请确保您具备以下条件: node js 和 npm 从 nodejs org https //nodejs org/ 安装最新的 lts 版本,并通过 node v 和 npm v 进行验证。 基本的 qwik 知识 熟悉 qwik 的组件、信号(使用 usesignal )和其可恢复性概念是推荐的。如果您是 qwik 新手,请先查看其文档。 一个 back4app 账户 在 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 前端链接。 设置您的后端应用程序 登录 到您的 back4app 仪表板 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 部署 登录到 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 上的容器化工作流部署您的网站。 在继续开发时,请考虑添加高级用户身份验证、实时更新和第三方集成等功能。 有关更多信息和支持,请参考 back4app 文档 https //www back4app com/docs 。

