Magick&&GitHub的pr:如何使用PWA给一个网站打包成一个App

许多网站并不提供完善的 PWA 支持,但这并不意味着它们不能被封装并转化为可安装的体验。本仓库是一个集中式的启动器,用于启动自定义PWA封装程序,使用户能够更安全、更自由地安装和浏览网页。


网站图标

我们需要准备一张尺寸为 512x512 或更小的webp格式的正方形图像(大约在10KiB内),放入pwa-store/docs/store/icons/对应的四个目录(我们关注的)下。
~/pwa-store/docs/store/icons/

  • pwa
  • msedge
  • wechatmini
  • wrappers
序号 条件 存放路径 是否生成包装 额外要求
1 有积木,能直接安装 pwa
2 无积木,但移动端浏览器能安装(安卓Edge好些, 有些浏览器不能安装的它可以) msedge 包装需添加 apptype: msedge
3 无积木,移动端(安卓, 苹果)也不能安装 wrappers
4 微信小程序专区 wechatmini 仅需放置小程序封面图+小程序链接/码

注意:就目前来看,因为移动端Edge浏览器可以兼容很多其他浏览器不能安装的,所以msedge作为保底的标识符,代表移动端浏览器可以按装的, 而并非只是Edge。

图片方面
图片裁剪:可以将获取到的图片然后前往在线工具Real Favicon Generator, 点击按钮Pick your favicon image上传您的图像文件。下一步,网页将显示所有使用场景。您可以保留默认选项,滚动到页面底部,然后点击按钮Next →生成网站图标。 这样我们会下载一个安装包, 里面有web-app-manifest-512x512.png的图片。
转化格式:由于我采用的是Fedora发型版,使用Magick(ImageMagick)工具转换, 比如在终端运行命令magick web-app-manifest-512x512.png web-app-manifest-512x512.webp就会得到webp格式的图片, 然后修改成网站的名称(推荐英文格式)就好。

积木解释
pwa:比如打开chirpy网页(无论是电脑,还是手机),会发现有个“小积木”,这个是能够直接完善支持PWA的。
image
msedge:比如美国北卡罗来纳州夏洛特市本地新闻电视台官网, 会发现,并没有小积木,但是在手机edge浏览器上->三横(三)->添加手机(Add to phone), 然后可以在移动端桌面出现wbtv应用,这个是移动端(安卓)Edge浏览器能安装的。
image
wrappers:这种情况就是前两者都不能创建的,无积木,安卓也不能安装。
wechatmini:微信小程序的基本都熟悉。
image


mesedge

  1. 图标处理
    pwa非常容易, 我们来看看mesedage, 比如美国北卡罗来纳州夏洛特市本地新闻电视台官网https://www.wbtv.com/, 打开浏览器,会发现它并没有“小积木”, 但是如果在移动端浏览器上,我们可以把它添加到移动端桌面。所以判断它属于mesedge。
    将已经处理的512x512的png格式的图片,转换为webp格式的图片。或许你可能会问为什么需要webp格式?或许是PNG 清晰透明、JPG 小但糊、WebP 又小又清,日常用 WebP 基本是最优解。
magick wbtv.png wbtv.webp

image

  1. 设置中英文介绍
    接下来需要来到~/pwa-store/docs/store/locale/下设置中英文,我们提交pr的只关注的只有两个英文:enus.js和zhcn.js,

首先看enus.js

方式 对应增添部分
pwa // PWA
msedge // Microsoft Edge
wechatmini // WeChat Mini Programs
wrappers // Wrappers

注意:Edge浏览器全称Microsoft Edge,这是指移动端的。

把其中一已有的示例丢给ai,按照格式分别生成英中文的json格式

threeblueonebrown_name: "3Blue1Brown",
threeblueonebrown_desc: "Opens 3Blue1Brown, a site featuring visual and intuitive explanations of advanced math topics.",
按照上述格式生成以下的:
https://www.icloud.com
https://www.wbtv.com

这里丢给豆包, 产出如下内容:

icloud_name: "iCloud",
icloud_desc: "Opens iCloud, a cloud service by Apple for storing photos, files, notes, mail and syncing data across devices.",
icloud_name: "iCloud",
icloud_desc: "打开 iCloud,苹果官方云服务,可存储照片、文件、备忘录、邮件并在多设备间同步数据。",

前者追加enus.js文件中// Microsoft Edge后面
同理,后者追加zhcn.js文件中// Microsoft Edge后面

效果
image
image

  1. 执行脚本并手动归类

然后打开~/pwa-store/scripts/下generate_wrappers.py的脚本文件,归类放入WRAPPERS = []里面,格式和前面一样,使用现有的例子丢给ai: 提示词如下。

比如按照
  { "name" : "University of Oxford", "url": "https://www.ox.ac.uk", "keyify_name": "oxford", "apptype": "msedge" },
格式生成
https://www.wbtv.com

ai会输出

{ "name" : "WBTV", "url": "https://www.wbtv.com", "keyify_name": "wbtv", "apptype": "msedge" },

将输出内容追加到WRAPPERS = []括号里面。

因为在站点都写了 "apptype": "msedge",所以脚本会去这里找图标: docs/store/icons/msedge/ 而不是 docs/store/icons/ 根目录。
也就是说你需要确认这个文件存在:docs/store/icons/msedge/wbtv.webp

然后回到项目根目录~/pwa-store,执行下列命令:

python scripts/generate_wrappers.py ~/pwa-store

这个脚本会删掉掉并重建_:

  • docs/wrappers/
  • docs/extensions/
  • docs/msedge/

然后重新生成你的新 wrapper。
对你这个站点,生成结果应该会出现在:

  • docs/msedge/wbtv/

手动归类:目的是把这个应用条目补进源 categories里面, 在docs/store/categories.js里面按照下面列表手动修改归类。
比如我们的WBTV判断是News部分, 所以追加到News里面。

  {
    name: "News",
    nameKey: "news_name",
    apps: [
      {
        name: "WBTV",
        nameKey: "wbtv_name",
        descriptionKey: "wbtv_desc",
        icon: "icons/msedge/wbtv.webp",
        url2: "/msedge/wbtv",
        apptype2: "wrapper",
        apptype_hide: "msedge",
        url: "https://www.wbtv.com"
      },
    ],
  },

50个顶层分类export const categories = [...] 里一共 50 个顶层分类(categories)。

序号 英文分类名 中文翻译对照 对应的分类结构
1 Fundamental 基础的 "nameKey": "fundamental_name", "name": "Fundamental", apps: [ ... ] 里面
2 Alternatives 替代方案 "nameKey": "alternatives_name", "name": "Alternatives", apps: [ ... ] 里面
3 Weather 天气 "nameKey": "weather_name", "name": "Weather", apps: [ ... ] 里面
4 WeChat Builtins 微信内置功能 "nameKey": "wechatbuiltins_name", "name": "WeChat Builtins", apps: [ ... ] 里面
5 Chatbots 聊天机器人 "nameKey": "chabots_name", "name": "Chatbots", apps: [ ... ] 里面
6 Cybersecurity 网络安全 "nameKey": "cybersecurity_name", "name": "Cybersecurity", apps: [ ... ] 里面
7 Time 时间 "nameKey": "time_name", "name": "Time", apps: [ ... ] 里面
8 Microsoft Services 微软服务 "nameKey": "microsoft_services_name", "name": "Microsoft Services", apps: [ ... ] 里面
9 Google Services 谷歌服务 "nameKey": "google_services_name", apps: [ ... ] 里面
10 Office Suites 办公套件 "nameKey": "officesuites_name", "name": "Office Suites", apps: [ ... ] 里面
11 Programming 编程 "nameKey": "programming_name", "name": "Programming", apps: [ ... ] 里面
12 Internet Services 互联网服务 "nameKey": "internetservices_name", "name": "Internet Services", apps: [ ... ] 里面
13 Mail 邮件 "nameKey": "mail_name", "name": "Mail", apps: [ ... ] 里面
14 Social Media 社交媒体 "nameKey": "socialmedia_name", "name": "Social Media", apps: [ ... ] 里面
15 Finance 金融 "nameKey": "finance_name", "name": "Finance", apps: [ ... ] 里面
16 Business 商业 "nameKey": "business_key", "name": "Business", apps: [ ... ] 里面
17 Billing 缴费 "nameKey": "billing_key", "name": "Billing", apps: [ ... ] 里面
18 Tech 科技 "nameKey": "tech_key", "name": "Tech", apps: [ ... ] 里面
19 Resource Distributions 资源分发 "nameKey": "resourcedistributions_name", "name": "Resource Distributions", apps: [ ... ] 里面
20 Media Tools 媒体工具 "nameKey": "mediatools_name", "name": "Media Tools", apps: [ ... ] 里面
21 News 新闻 "nameKey": "news_name", "name": "News", apps: [ ... ] 里面
22 Fashion 时尚 "nameKey": "fashion_name", "name": "Fashion", apps: [ ... ] 里面
23 Entertainment Platform 娱乐平台 "nameKey": "entertainmentplatform_name", "name": "Entertainment Platform", apps: [ ... ] 里面
24 Games 游戏 "nameKey": "games_name", "name": "Games", apps: [ ... ] 里面
25 Gaming Community 游戏社区 "nameKey": "gamingcommunity_name", "name": "Gaming Community", apps: [ ... ] 里面
26 Learning 学习 "nameKey": "learning_name", "name": "Learning", apps: [ ... ] 里面
27 Forums 论坛 "nameKey": "forums_name", "name": "Forums", apps: [ ... ] 里面
28 Knowledge & Pedias 知识与百科 "nameKey": "knowledgespedia_name", "name": "Knowledge & Pedias", apps: [ ... ] 里面
29 Religion 宗教 "nameKey": "religion_name", "name": "Religion", apps: [ ... ] 里面
30 Analytics 分析工具 "nameKey": "analytics_name", "name": "Analytics", apps: [ ... ] 里面
31 Live Tracking 实时追踪 "nameKey": "livetracking_name", "name": "Live Tracking", apps: [ ... ] 里面
32 Streaming 流媒体 "nameKey": "streaming_name", "name": "Streaming", apps: [ ... ] 里面
33 E-commerce 电子商务 "nameKey": "ecommerece_name", "name": "E-commerce", apps: [ ... ] 里面
34 Food 食物 "nameKey": "food_name", "name": "Food", apps: [ ... ] 里面
35 Mobility & Logistics 出行与物流 "nameKey": "mobilitylogistics_name", "name": "Mobility & Logistics", apps: [ ... ] 里面
36 Cars 汽车 "nameKey": "cars_name", "name": "Cars", apps: [ ... ] 里面
37 Tickets 票务 "nameKey": "tickets_name", "name": "Tickets", apps: [ ... ] 里面
38 Housing 住房 "nameKey": "housing_name", "name": "Housing", apps: [ ... ] 里面
39 Jobs 求职 "nameKey": "jobs_name", "name": "Jobs", apps: [ ... ] 里面
40 Cloud (is someone else's computer) 云服务(别人的电脑) "nameKey": "cloud_name", "name": "Cloud (is someone else's computer)", apps: [ ... ] 里面
41 LegalTech 法律科技 "nameKey": "legaltech_name", "name": "LegalTech", apps: [ ... ] 里面
42 Websites & Blogs 网站与博客 "nameKey": "websitesblogs_name", "name": "Websites & Blogs", apps: [ ... ] 里面
43 Manosphere 男性圈 "nameKey": "manosphere_name", "name": "Manosphere", apps: [ ... ] 里面
44 United States Government🇺🇸 美国政府 "nameKey": "usgov_name", "name": "United States Government🇺🇸", apps: [ ... ] 里面
45 Chinese Government🇨🇳 中国政府 "nameKey": "cngov_name", "name": "Chinese Government🇨🇳", apps: [ ... ] 里面
46 Organizations 组织机构 "nameKey": "organizations_name", "name": "Organizations", apps: [ ... ] 里面
47 Health & Insurance 健康与保险 "nameKey": "healthinsurance_name", "name": "Health & Insurance", apps: [ ... ] 里面
48 Life 生活 "nameKey": "life_name", "name": "Life", apps: [ ... ] 里面
49 Sports 体育 "nameKey": "sports_name", "name": "Sports", apps: [ ... ] 里面
50 Research 研究 "nameKey": "research_name", "name": "Research", apps: [ ... ] 里面
51 Education 教育 "nameKey": "education_name", "name": "Education", apps: [ ... ] 里面
52 Web Portal 网址导航/门户 "nameKey": "webportal_name", "name": "Web Portal", apps: [ ... ] 里面
53 Other PWA Stores 其他 PWA 商店 "nameKey": "otherpwastores_name", "name": "Other PWA Stores", apps: [ ... ] 里面
54 Boards 版块/图板 "nameKey": "boards_name", "name": "Boards", apps: [ ... ] 里面
55 Bluetooth Devices 蓝牙设备 "nameKey": "bluetoothdevices_name", "name": "Bluetooth Devices", apps: [ ... ] 里面
56 Adult 成人内容 "nameKey": "adult_name", "name": "Adult", apps: [ ... ] 里面

各分类里 app 的“添加方式”

基础字段 含义 基础(共有) pwa msedge wrapper wechatmini
name 展示名称
nameKey 名称对应的多语言键名
apps 该分类下的应用列表
icon 图标路径
url 主访问地址;也可能是站点地址、站内相对路径、小程序唤起地址等
descriptionKey 描述文本对应的多语言键名
manifestUrl Web App Manifest 地址
manifestId Manifest 对应的应用 ID / 安装标识
urlDisplay 对外展示的网址,一般用于 wrapper 显示原站地址
apptype 应用类型,例如 wrapperpwamsedgewechatmininativeextension ✅pwa ✅msedge ✅wrapper ✅wechatmini
hide 是否隐藏;为 true 时通常不在前台正常展示
url2 第二访问入口,常用于同时保留另一种安装/包装方式
apptype2 第二应用类型,对应 url2
manifestUrl2 第二 Manifest 地址,对应 url2
manifestId2 第二 Manifest ID,对应 url2
namekey 另一种写法的小写字段名,作用与 nameKey 相同,但属于文件中的不统一写法

示例
pwa:最常见的“普通 PWA/网页站点”写法通常是:

{
  "name": "Google",
  "icon": "icons/pwa/google.webp",
  "url": "https://www.google.com",
  "descriptionKey": "google_desc"
}

msedge: Microsoft Edge类(指的是移动端浏览器):apptypemsedge,通常保留原站 URL。

{
  "name": "Laptop Mag",
  "nameKey": "laptopmag_name",
  "descriptionKey": "laptopmag_desc",
  "icon": "icons/msedge/laptopmag.webp",
  "url": "https://www.laptopmag.com",
  "apptype": "msedge",
  "url2": "/msedge/laptopmag",
  "apptype2": "wrapper",
  "manifestUrl2": "/msedge/laptopmag/manifest.json",
  "manifestId2": "/msedge/laptopmag"
}

wrapper: Wrapper 型:url 指向本项目内部路径 /wrappers/...,并带 apptype: "wrapper"

{
  "name": "Perplexity",
  "icon": "icons/wrappers/perplexity.webp",
  "url": "/wrappers/perplexity",
  "urlDisplay": "https://www.perplexity.ai",
  "descriptionKey": "perplexity_desc",
  "apptype": "wrapper",
  "manifestUrl": "/wrappers/perplexity/manifest.json",
  "manifestId": "/wrappers/perplexity"
}

wechatmini: 微信小程序型。

{
  "name": "China Telecom",
  "nameKey": "chinatelecom_name",
  "descriptionKey": "chinatelecom_desc",
  "icon": "icons/wechatmini/chinatelecom.webp",
  "url": "#小程序://中国电信App/euxKgI21HGTS3KJ",
  "apptype": "wechatmini"
}

提pr

一、前提(你已经满足)

  • 你有 Fork 过别人的仓库(或自己仓库想跨分支合并)
  • 你本地改完、commit、push 到 你自己的 Fork 仓库(你的分支)
  • 现在想把你的改动 提交给原仓库(上游)合并 → 这就是 PR

二、网页端提交 PR(最常用)

  1. 进入你的 Fork 仓库,比如:https://github.com/rockosdev/pwa-store
  2. 切换到你改完的分支
    会看到这样一行提示:This branch is 12 commits ahead of and 2 commits behind trcrsired/pwa-store:main
    | 英文 | 中文 | 含义 |
    | ---------------- | ----- | ------------------------------- |
    | commits behind | 落后提交 | 🔴我的库比官方库少了若干次提交,这部分需要从官方库拉取到自己库,以保持同步 |
    | commits ahead | 超前提交 | 🟢我的库比官方库多了若干次提交,这部分可以提交给官方 |

image

点击2 commits behind, 将官方多的提交拉取到自己库。
image
image
image
image

点击12 commits ahead,将自己库提交给官方库。
image
image
image
✅ 完成! 等作者合并就行。

这样操作可能需要本地更新本地的仓库,然后来到~/pwa-store下, 按以下顺序执行命令就好。

命令 英文含义 中文作用
git fetch origin Fetch latest changes from remote 从远程仓库下载最新代码(不合并、不覆盖)
git pull origin main --rebase Pull and rebase local changes on top of remote 拉取并同步远程最新代码,把你的本地修改放在最新版本后面
git push origin main Push local commits to remote main branch 把本地代码推送到 GitHub

提交后流程(你要知道)

  • 原仓库维护者会 Review 代码
  • 有问题会评论 → 你在本地继续改、push 同分支 → PR 自动更新
  • 通过后 → 维护者 Merge PR → 你的代码合进 main

posted @ 2026-04-11 13:08  游翔  阅读(6)  评论(0)    收藏  举报