多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Puter Dev Center 源码详解:在开源 Puter 中发布、部署与管理 Apps、Websites 和 Workers

Puter Dev Center 源码详解:在开源 Puter 中发布、部署与管理 Apps、Websites 和 Workers 后端前端云原生【免费下载链接】puter The Internet Computer! Free, Open-Source, and Self-Hostable.项目地址https://gitcode.com/GitHub_Trending/pu/puter点击查看免费下载Dev Center 是 Puter 内置的开发者中心应用负责把「写好的静态页面、Worker 脚本或整个目录」变成可访问的 Puter 应用与子域名站点。本文基于开源仓库中 Dev Center 的说明文档 与完整前端源码展开带你梳理它的整体结构、URL 参数机制、App 创建与部署流程、Websiteputer.site 子域名管理、Worker 部署逻辑以及自托管环境下的适配方式读完后你可以完整看懂一个 Puter 应用从创建、部署到更新、删除的全生命周期。一、Dev Center 是什么README 对 Dev Center 的定位只有一句话但信息量足够大Dev Center is a Puter app that allows you to publish and manage web apps. It is built with Puter SDK and is available on Puter.com as well as the self-hosted Puter.也就是说它本身是一个 Puter 应用——运行在 Puter 桌面环境里而不是一个独立的 Web 后台它完全用 Puter SDKputer-js构建——所有数据操作都走puter.apps、puter.hosting、puter.workers、puter.fs、puter.kv等标准 SDK 接口云端puter.com与自托管 Puter 均可用两者差异主要在开发者资料、激励计划等云端专属能力上。源码层面Dev Center 是一个纯静态前端应用目录结构如下src/dev-center/index.html单页入口包含侧边栏Apps / Websites / Workers / Payout Method 四个页签与所有对话框src/dev-center/js/dev-center.js全局初始化、URL 参数解析、拖放即部署insta-deploy入口src/dev-center/js/apps.jsApp 的创建、部署、编辑、统计、删除约 3200 行是核心逻辑所在src/dev-center/js/websites.jsWebsites静态子域名站点管理src/dev-center/js/workers.jsWorkersServerless Worker管理src/dev-center/js/images.js页面用到的 Spinner、占位文案、SVG 图标等静态字符串。页面引入的第三方依赖见 index.html 的head与尾部 script 标签包括 jQuery 3.6.0、jquery.dragster拖放区、slugify名称 slug 化、html-entitiesHTML 转义、moment.js日期格式化以及 CDN 上的 Chart.js统计图表、Tagify文件类型关联的标签输入和 Tippytooltip。整个模块采用 AGPL-3.0 许可证见 src/dev-center/LICENSE.txtREADME 同时列出了界面图标的来源jolloficons、svg-credit-card-payment-icons、Bootstrap Icons、svg-spinners 等开源图标集。二、启动流程与自托管 URL 参数2.1 引导顺序页面加载后的初始化顺序在 dev-center.js 中定义window.dev_center_uid puter.appID; // 当前 Dev Center 应用自身的 UID (async () { window.user await puter.auth.getUser(); if ( user?.username ) window.auth_username user.username; })(); $(document).ready(async function () { await initializeAssetsDirectory(); // 先确保“素材目录”存在 puter.ui.showSpinner(); init_apps(); // apps.js init_websites(); // websites.js init_workers(); // workers.js puter.ui.hideSpinner(); });三个init_*分别调用puter.apps.list({ icon_size: 64 })、puter.hosting.list()、puter.workers.list()拉取各自的资源列表并渲染表格。dev_center_uid取自puter.appID非常关键——它是 Dev Center 在用户 AppData 中的命名空间后文所有目录路径都依赖它。2.2 URL 参数让 Dev Center 适配任意部署环境自托管 Puter 的域名、端口、协议各不相同。Dev Center 通过 URL 查询参数解决这一问题解析逻辑集中在 dev-center.js#L41-L77参数默认值作用puter.domainputer.com主站域名用于拼接应用访问链接{protocol}://{domain}/app/{name}puter.port空端口号非空时静态托管域会拼成site.{domain}:{port}puter.protocolhttps仅允许https或httpsource_path空预置“待部署的 Puter 路径”用于从文件管理器拖入/启动 Dev Center 时直接进入 insta-deploy 流程其中静态托管域即子域名站点的根域的推导规则为window.static_hosting_domain puter.site; if ( window.domain puter.localhost ) { window.static_hosting_domain site.puter.localhost; } else if ( window.domain window.domain ! puter.com ) { window.static_hosting_domain site.${window.domain}; } // 若提供了 puter.port则再拼接 :port即云端固定为puter.site自托管本地puter.localhost为site.puter.localhost其他自托管域名为site.你的域名。后端 SubdomainDriver 的边界测试 中同样以static_hosting_domain: puter.site作为基准用例可印证前后端对根域的一致性约定。三、Apps 管理列表、搜索、排序与审批徽章「My Apps」页签渲染自puter.apps.list()的返回结果。每行 App 卡片generate_app_card见 apps.js#L1564-L1673包含图标与标题若app.metadata.locked为真则附加锁形 tooltip 图标应用链接{protocol}://{domain}/app/{name}Users 列stats.referral_count stats.user_count注册用户 通过分享链接进入的访客Opens 列stats.open_count启动次数创建时间moment.js 格式化为MMM Do, YYYY三个审批徽章approved_for_listingApp Center 上架、approved_for_opening_items可作为文件打开目标、approved_for_incentive_program激励计划资格。搜索是纯前端过滤匹配字段为title、name、description与uid四个字段search_appsapps.js#L2312-L2342点击表头可按name、user_count、open_count、created_at升/降序排序切换页签或点击刷新按钮会重新调用puter.apps.list拉取最新数据。四、创建 App从命名到子域名注册的完整链路点击「New App」后Dev Center 用puter.ui.prompt询问标题上限 60 字符随后create_app(title, source_path, items)执行一串固定的 SDK 调用apps.js#L167-L280生成 nameslugify(title, { lower: true, strict: true })即标题转成小写 slug默认图标把本地./img/app.svg读成 Base64 Data URL 作为占位图标注册应用puter.apps.create({ title, name, indexURL: https://dev-center.puter.com/coming-soon.html, // 占位入口 icon, description: , maximizeOnStart: false, background: false, dedupeName: true, // name 冲突时自动去重 feedbackEnabled: true, // 新应用默认开启用户反馈 metadata: { window_resizable: true, fullpage_on_landing: true }, });SDK 侧puter.apps.create的实现见 apps/create.jsname与indexURL为必填最终通过makeDriverMethod调用后端puter-apps接口的es:app驱动create方法并在创建成功后调用addUserIteration计入用户迭代数据 4.建立 AppData 目录puter.fs.mkdir(/{username}/AppData/{dev_center_uid}/{app.uid})这是该应用部署文件的落盘位置 5.注册初始子域名puter.hosting.create({name}-{随机后缀}, app_dir.path)——注意这里已经为应用创建了一个静态路由此时站点内容还是空的 6.回写 indexURL若携带了source_path拖放部署场景立即更新为https://{subdomain}.{static_hosting_domain}否则保持 coming-soon 占位页 7.创建桌面快捷方式在/{username}/Desktop上传一个带appUID标记的空文件用户在桌面双击即可启动该应用。其中puter.hosting.create的 SDK 实现见 hosting/create.js参数支持create(subdomain, dirPath)或create({ subdomain, root_dir })传入完整主机名如sub.puter.site会被自动剥掉只保留 label后端对应 SubdomainDriver。子域名重名或路径不存在会直接拒绝。五、部署Deploy三种来源、一个硬性约束进入应用编辑页后「Deploy」页签提供两种发布方式与 index.html 中部署卡片模板一致Use files拖放/选择 Puter 内的文件或目录也可从本地拖入把静态资源复制到应用目录并部署Use link直接把应用的 Index URL 指向一个已有公网地址保存时同样走saveEditedApp的完整校验。5.1 硬性约束根目录必须含 index.html无论哪种输入前端都会构建目录树generateDirTree并检查hasRootIndexHtml既接受根目录下的index.html也接受「拖入的单个文件夹内部根目录含index.html」。缺失时弹出index_missing_errorPlease upload an index.html file or if youre uploading a directory, make sure it contains an index.html file at its root.文案定义在 images.js。另一个防御性检查是.git目录探测hasGitDirectoryshowGitWarningDialog若部署内容包含.git会警告「可能泄露提交历史与配置、显著增大部署体积」并允许勾选“不再提示”该偏好写入puter.kv的skip-git-warning键。5.2 部署状态机window.deploy(app, items)apps.js#L1858-L2087按items的类型分三条路径但共享同一套“换域名”策略先puter.fs.stat查询应用目录并取回它当前的subdomains删除旧应用目录重建/{username}/AppData/{dev_center_uid}/{app.uid}按来源写入文件(A) Puter 路径字符串目录则readdir后逐个puter.fs.copy(file.path, appdata_dir.path, { overwrite: true })文件则直接copy每复制一个更新一次进度百分比(B) Puter 条目数组逐个copy路径兼容fullPath/path/filepath三种字段(C) 本地文件puter.fs.upload(items, ...)带progress回调、parsedDataTransferItems: true、createMissingAncestors: true一次性把本地目录树上传到 AppData为本次部署生成一个全新 hostname{name}-{(Math.random()1).toString(36).substring(7)}然后puter.hosting.create(hostname, appdata_dir.path)新路由创建成功后puter.apps.update把indexURL指向https://{hostname}.{static_hosting_domain}此时才调用deleteOldHostnames()清理旧子域名回填 Settings 页的 Index URL 输入框、展示成功提示、复位拖放区。源码中的注释解释了“每次部署都换新 hostname”的动机we change hostname every time to prevent caching issues换域名规避 CDN/浏览器缓存而“先更新 indexURL 再删旧域名”的顺序则是为了保证一致性——Old hostnames are deleted only once the app points at the new one, so a deploy that dies midway never leaves the app on an unregistered name.中途失败的部署不会把应用留在一个未注册的名字上。5.3 Insta-Deploy拖到页面任意位置即可发布除了编辑页内的拖放区整个页面 body 也监听 drop 事件dev-center.js#L356-L443把 Puter 文件或本地目录拖进 Dev Center 任意空白处会弹出「Deploy to: New App / An Existing App」对话框index.html 中的.insta-deploy-modal。选 New App 走create_app(title, source_path)一条龙选 Existing App 则列出全部应用供选择选中后直接deploy({ uid }, source_path ?? dropped_items)。此外source_pathURL 参数与puter.ui.onLaunchedWithItems回调支持从文件管理器“发送到 Dev Center”的场景。六、Settings应用元数据的完整字段与校验规则「Settings」页签对应saveEditedAppapps.js#L1127-L1365字段与校验规则可以整理成一张完整表格字段校验/取值写入位置Title必填≤ 60 字符titleName必填≤ 60 字符正则^[a-zA-Z0-9-_-]$字母、数字、-、_nameIndex URL必填合法 URL 且必须以http://或https://开头indexURLIcon从图片选择器读取转 Base64若来自 URL 则下载后校验≤ 5MB且 MIME 为图片iconDescription自由文本descriptionCategory15 个预置分类Games、Developer Tools、Photo Video、Productivity、Utilities、Education、Business、Social、Graphics Design、Music Audio、News、Entertainment、Finance、Health Fitness、Lifestylemetadata.categoryFile AssociationsTagify 标签输入支持批量粘贴逗号/空格/Tab 分隔与逗号快捷添加白名单涵盖常见扩展名与 MIME如.pdf、text/*、image/*保存时归一化为.ext或type/sub小写形式filetypeAssociationsWindow初始宽高表单默认 680×380保存时空值回退 800×600、初始 top/left、window_resizable、hide_titlebar、maximize_on_start、fullpage_on_landing、background后台进程、set_title_to_opened_filemetadata.*User Feedback开关开启后用户可在 Puter 内对本应用提交反馈反馈投递到开发者账户邮箱feedbackEnabledDelete Protection开关开启后metadata.locked应用无法被删除删除入口会直接拒绝metadata.locked几个实现细节值得注意变更追踪trackOriginalValues在进入编辑页时快照所有字段hasChanges()逐项比对含图标 Base64、社交图、预览图序列化状态只有存在差异时才点亮 Save/Reset 按钮社交图与预览图走“素材托管”initializeAssetsDirectory在用户 AppData 下创建assets目录并为其注册一个assets-{随机串}子域名URL 存入puter.kv的assets_url键之后社交图推荐 1200×630上传为{assets_url}/{app_name}.pnghandleSocialImageUpload预览图按设备类型desktop / tablet / mobile每类最多 10 张上传为{assets_url}/previews/{app_name}/{app_name}-{device}-{i1}.pnghandlePreviewImagesUpload最终把托管 URL 写回metadata.social_image与metadata.preview_imagesApp ID 展示编辑页提供只读的uid输入框与复制按钮便于开发者在别处引用该应用。删除应用时的清理逻辑同样值得参考puter.apps.delete成功后先puter.fs.stat({ returnSubdomains: true })取回应用目录关联的子域名并puter.hosting.delete再递归删除AppData目录apps.js#L1386-L1451——即「应用 注册信息 子域名路由 AppData 目录」三件套的完整回收。七、Analytics按时间粒度拉取统计「Analytics」页签通过puter.apps.get(name, { stats_period, stats_grouping })拉取统计时间粒度随周期自动切换render_analyticsapps.js#L2936-L2957today/yesterday→stats_grouping: hour周/月/7d/30d 类周期 →day年类与12m、all→month。周期下拉共 15 个选项Today、Yesterday、This/Last week、7d、30d、This/Last month、This/Last year、12m、All time数据源为app.stats.grouped_stats.open_count用 Chart.js 渲染曲线并展示 Users / Opens 两张统计卡Users 卡附带「View Users」入口弹出app-users-modal表格展示曾向该应用认证的 Username 与 Email。八、Websites 管理把任意目录变成 puter.site 子域名「Websites」页签与 Apps 独立操作对象是 websites.js 中的puter.hosting资源创建点击「New Website」→puter.ui.showDirectoryPicker()选择 Puter 目录 → 输入子域名默认示例my-awesome-website→puter.hosting.create(name, dirPath)列表卡片直接渲染为可点击的https://{subdomain}.puter.site链接并展示关联目录点击目录名会用puter.ui.launchApp(explorer, { path })在文件管理器中打开更换目录右键菜单「Change Directory」→ 选择新目录并确认 → 先puter.hosting.delete(website_name)再puter.hosting.create(website_name, 新路径)即“同域名换根目录”是通过删除重建实现的删除支持单个右键 Delete与批量勾选 Delete 按钮两种路径均为puter.hosting.delete(name)并附确认对话框搜索/排序搜索匹配subdomain与root_dir.name表头支持按 name、Connected Directory、Created 排序支持 Shift 连选。九、Workers 管理部署 Serverless Worker「Workers」页签workers.js封装了puter.workers模块前置条件账号必须完成邮箱确认否则先走puter.ui.requestEmailConfirmation()流程!window.user?.email || !window.user?.email_confirmed时拦截创建puter.ui.showOpenFilePicker({ accept: .js })仅允许选择.js文件 → 输入 Worker 名默认示例my-awesome-worker→puter.workers.create(name, selectedFile.path)列表与交互卡片展示 name、file_path、创建时间点击文件路径会puter.ui.launchApp({ name: editor, file_paths: [file_path] })直接在代码编辑器中打开源码右键菜单提供 Delete语义SDK 文档注释Workers.js明确“worker 与其名字绑定——create 一次之后更新方式是覆写其源文件而不是重复创建”用户 token 部署时会自动挂到名为sandbox-{workerName}的沙箱应用下自带独立 KV / AppData 命名空间且要求已验证账号、源文件小于 10MB。十、云端专属能力开发者资料、激励计划与收款方式init_apps中有一段分支只有当domain puter.com时才调用puter.apps.getDeveloperProfile()源码注释This is only for puter.com for now as we dont have dev profiles in self-hosted Puter据此approved_for_incentive_program !joined_incentive_program→ 展示“加入 Puter Incentive Program”表单joined_incentive_program→ 侧边栏出现「Payout Method」页签展示 PayPal 收款邮箱dev_profile.paypal首次进入且未关闭过弹出「Developers earn money on Puter」引导对话框关闭动作以puter.kv.set(earn-money-c2a-closed, true)记录。加入表单的提交逻辑dev-center.js#L154-L227为字段first_name/last_name/paypal均必填且 ≤ 100 字符paypal 需通过validateEmail正则\S\S\.\S然后以Authorization: Bearer {puter.authToken}POST 到{puter.APIOrigin}/jip成功即切换为成功页并把 Payout Method 页签显示出来。十一、自托管部署与适用边界综合前文对自托管运维者最实用的事实是Dev Center 是静态应用随 Puter 一起分发位于 src/dev-center 目录无独立构建步骤打开时带上?puter.domain你的域名puter.port端口puter.protocolhttp即可让应用链接与静态托管域正确指向自托管环境静态域默认为site.{domain}本地开发为site.puter.localhost开发者资料、激励计划、Payout Method 目前仅 puter.com 可用源码中有明确注释与domain puter.com守卫自托管环境的核心发布能力Apps 创建/部署、Websites、Workers不受影响所有 SDK 接口puter.apps/puter.hosting/puter.workers/puter.fs/puter.kv在后端由 src/backend/drivers 下的对应驱动实现如 SubdomainDriver自托管时这些能力一并可用。十二、小结Dev Center 的价值不在于界面而在于它把 Puter SDK 的一组原语——apps.create/update/delete、hosting.create/delete、workers.create、fs与kv——编排成了开发者真正需要的发布流程slug 化命名与 AppData 命名空间、每次部署更换子域名以规避缓存、“先切流再删旧路由”的更新顺序、index.html与.git两道部署前检查、以及素材社交图/预览图的独立托管。阅读 src/dev-center 下这四个 JS 文件基本就掌握了 Puter 静态托管与应用注册的完整前端模型若需继续深入可顺着 SDK 模块 apps/create.js、hosting/create.js 与 Workers.js 追踪到后端驱动的请求路径。赞分享后端前端云原生【免费下载链接】puter The Internet Computer! Free, Open-Source, and Self-Hostable.项目地址https://gitcode.com/GitHub_Trending/pu/puter点击查看免费下载相关推荐Puter 开源项目上手与自托管部署全指南Puter 开源项目上手与自托管部署全指南 Puter 是一个开源的互联网电脑Internet Computer项目它把桌面操作系统搬进浏览器让你把后端前端云原生Puter.js Apps API 完整开发指南在 Puter 桌面操作系统中创建、管理与分发应用Puter.js Apps API 完整开发指南在 Puter 桌面操作系统中创建、管理与分发应用 Apps API 是 Puter.js 为开发者提供的一套后端前端云原生15分钟跑起来一个 AzerothCore 魔兽世界私服Docker 部署实战15分钟跑起来一个 AzerothCore 魔兽世界私服Docker 部署实战 本文带你用 Docker 完成一次 AzerothCore 魔兽世界私服Wo游戏开发后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表