我的技术和生活

  • 使用 `postMessage` 跨域名迁移 `localStorage`

    使用 `postMessage` 跨域名迁移 `localStorage`

    朋友的网站有个需求:要从 A 域名迁移到 B 域名。所有内容不变,只是更改域名。这个需求不复杂,理论上改下配置然后 301 即可。但这个网站是纯静态网站,用户数据都存在 localStorage 里,所以他希望能够自动帮用户把数据也迁移到新域名。

    我们知道,localStorage 是按照域名存储的,B 网站无法访问 A 网站的 localStorage。所以我们就需要一些特殊的手段来实现需求。经过一些调研,我们准备使用 postMessage() 来完成这个需求。

    大体的方案如下:

    首先,增加 migrate.html 页面。这个页面不需要具体的功能,只要侦听 message 事件,并且把 localStorage 发出即可。

    <script>
      window.addEventListener('message', function (message) {
        const { origin, source } = message;
        // 验证来源,只接受我们自己的域名发来的请求
        if (origin !== 'https://wordleunlimited.me') return;
    
        const local = localStorage.getItem('wordle');
        // `source` 是浏览器自动填充的,即调用 `postMessage` 的来源。作为跨域 iframe 里的页面,拿不到外层 window,只能通过这种方式往回传递数据。
        source.postMessage({
          type: 'migrate',
          stored: local,
        }, 'https://wordleunlimited.me');
      });
    </script>

    然后,在应用里增加 <iframe>,因为我用 Vue3,所以这里也用 Vue 组件的方式处理。

    <template lang="pug">
    migrate-domain(v-if="needMigrate")
    </template>
    
    <script setup>
    // 我会把迁移的状态持久化,以免反复提示打扰用户
    const needMigrate = location.hostname === 'wordleunlimited.me' && !store.state.migrated19;
    </script>
    <script lang="ts" setup>
    import {ref} from "vue";
    // 项目启动得早,还在用 vuex
    import {useStore} from "vuex";
    import {key} from "@/store";
    
    const store = useStore(key);
    const migrateIFrame = ref<HTMLIFrameElement>();
    
    // migrate.html 接到请求后,验证来源,然后会把 localStorage 的数据发回。我们用这个函数接收。
    window.addEventListener('message', message => {
      const { origin, data } = message;
      // 同样验证来源
      if (origin !== 'https://mywordle.org' && origin !== 'https://mywordgame.com') return;
      const { type, stored } = data;
      if (type !== 'migrate') return;
      if (stored) {
        // 迁移数据时,需加入特殊标记,用来标记“已迁移”状态
        localStorage.setItem('wordle', stored.replace(/}$/, ', "migrated19": true}'));
        // 很奇怪,直接 reload 可能会迁移失败,所以这里稍微等一下
        setTimeout(() => {
          if (confirm('Data migrated, reload the page?')) {
            location.reload();
          }
        }, 100);
      }
    });
    
    // iframe 加载完即执行这段 JS,向 iframe 内的页面传递迁移请求
    function onLoad() {
      const contentWindow = migrateIFrame.value?.contentWindow;
      if (contentWindow) {
        contentWindow.postMessage('migrate', 'https://mywordle.org');
      } else {
        console.warn('no content window');
      }
    }
    </script>
    
    <template lang="pug">
    iframe(
      ref="migrateIFrame"
      src="https://mywordle.org/migrate.html"
      frameborder="no"
      width="0"
      height="0"
      @load="onLoad"
    )
    </template>
    
    <style scoped>
    iframe {
      width: 0;
      height: 0;
    }
    </style>

    至此,功能完成。

    如此一来,老用户打开网站后,会被跳转到新域名。然后应用 JS 会检查 localStorage 里存储的数据,如果没有迁移过,就会使用 <iframe> 加载老域名下的 migrate.html。等待目标页面加载完成之后,调用 postMessage() 发送迁移请求。接下里,migrate.html 接到请求后,返回之前存储的数据。新域名储存之后,提示刷新。

    主要的坑在于 <iframe> 里的页面无法直接跟跨域页面通信,所以需要父页面先找到子页面,发起请求;然后子页面再把数据回传给父页面。其它方面应该就是一般的 API 调用,以及体验性问题。

    希望本文对大家有帮助。如果各位对 postMessage() 或者其它相关技术有问题的话,欢迎留言交流。

    本文参与了「SegmentFault 思否写作挑战赛」,欢迎正在阅读的你也加入。

  • 【视频】肉山的模拟面试系列:初中级前端,欢迎奥利奥同学

    【视频】肉山的模拟面试系列:初中级前端,欢迎奥利奥同学

    某天群里,奥利奥同学突然提问:想参加模拟面试,不知道能不能搞。我一想,可以呀。我工作 16+ 年,面试过很多新人,也带过不少新人;给自己的公司招过人,也帮朋友招过人;有面试过新人,也跟资深老鸟聊过。感觉有蛮多能分享的内容。从客观需求来说:近期有朋友委托我帮忙做前端面试;我很久以前分享过的前端面试题也该更新一波了。

    于是就答应下来,准备每周做一期。开门第一单,就邀请奥利奥同学来做吧。于是就有了下面的视频:

    也欢迎大家移步 B 站帮我三连分享:肉山的模拟面试系列:初中级前端,欢迎奥利奥同学

    这位奥利奥同学,他毕业后就加入一家偏传统的公司,待了一年半。现在感觉有点被天花板挤压,想试试看新的挑战。于是我结合我的经验,对他的简历进行评价,然后简单过了一轮面试。以下是视频内容大纲:

    1. 如何准备简历
    2. 奥利奥同学的简历分析
    3. 初中级别前端面试
    4. 结对编程测试
    5. 面试点评
    6. 问题解答+交流

    希望以上内容对近期求职面试的同学有帮助。如果你对求职面试入职过试用期等有问题,欢迎在留言、弹幕里提出,与我讨论交流。如果你也想参加模拟面试,可以跟我联系,预约时间。

    感谢奥利奥同学帮我想到这个方向。

  • 2023 Git 必备知识(三):小知识推荐配置与小技巧

    2023 Git 必备知识(三):小知识推荐配置与小技巧

    (本文好像内容较少,我会继续完善。)

    Git 系列文章

    “我们有多个客户,交付给每个客户的功能不一样,要维护几个分支?”

    这是一个很常见的问题,也是大家经常出错的地方。比如我之前待过的某厂,给客户交付部署了 a0 版本。然后我们继续开发,搞出来了 bcd 等功能。客户想增加功能,但是不想多付钱;我们收不到钱,又不想得罪客户,于是跟他们协商,只交付 c 功能。于是,负责版本的同学就 cherry-pick c 功能的每次提交,交付给客户。

    第一次交付比较顺利,后来就越来越麻烦,交付分支和开发分支的差异越来越大,难以维护。

    git 设计用来管理代码的版本,方便我们并行开发、快速迭代。于是它是线性的,基本上是个单向链,我们很难往分支中段插入一个 commit,或者将某个 commit 轻松发布到某几个特定的版本当中。故而,功能模块化和热插拔跟 git 无关,不应该放在一个问题里讨论。

    类似的工作,我们需要使用模块化控制,比如构建脚本等。大部分脚手架工具,比如 webpack、vite 都提供有 define 功能,即定义变量,并注入到最终代码。我们可以利用这个功能,配合环境变量,给功能添加开关,然后在编译阶段进行调整,针对不同的用户,输出包含不同功能的代码。

    以 Vite 为例,大概是这个样子:

    export default defineConfig({
      define: {
        __CLIENT__: process.env.CLIENT,
      },
    });
    const routes = [
      // 通用路由
    ];
    
    // 只有客户是 meathill,才能看到某些路由,配合路由 lazyload,实现打包区分
    if (__CLIENT === 'meathill') {
      routes.push({
        path: '/pay-before-use-feature',
        component: () => import('./pay-before-use-feature.vue');
      })
    } else {
      routes.push({
        path: '/pay-before-use-feature',
        component: SorryYouAreNotAllowed,
      });
    }

    如果你有不同意见的话,可以到 这个问答 里讨论。

    推荐配置

    git config --global pull.ff only

    全局配置 git pull 的时候只使用 fast forward only 模式,即只会在采用快进模式,不会将远程分支通过创建 merge commit 的方式合并到本地。可以避免产生多余的 merge commit

    git config --global core.autocrlf true

    如果你使用 Windows 系统作为主力开发系统,那最好把自动转换换行符的选项钩上,以便和主要用其它系统的同事一起工作。

    Tips

    • GUI 推荐 GitHub Desktop,GitHub 集成很好,其它平台也能用
    • 分支名不要太长,可能导致构建工具失败
    • 依赖变更,翻译更新尽量单独开分支来做,即使跟功能相关的翻译,也要单开分支,这样可以大大减轻 code reviewer 的负担,并且更不容易产生冲突
    • VS Code 处理冲突比较好用,比 JetBrains 系列 IDE 好用
    • rebase 时如果 lock 文件产生冲突,可以直接 git checkout --theirs 回退开发分支的修改,rebase 结束后重新安装即可。

    总结

    至此,我现阶段对 Git 的理解就分享完毕,希望对大家有帮助。未来我收获新知也会继续分享。如果你对 Git 或者版本管理有什么问题或者想法,欢迎留言交流。

  • 【视频】Node.js 开发 RAR 解压缩命令行工具

    【视频】Node.js 开发 RAR 解压缩命令行工具

    拖来拖去,终于把 使用 node.js 开发命令行工具 workshop 的视频剪出来了,前几天上传到 B 站,访问量很一般,所以在自己的博客再捞一下。

    这次视频主要面向新手,主要呈现从 0 到 1 实现命令行工具的做法,希望观众无论基础如何,都能在看完视频之后,掌握封装仓库、实现命令行工具的做法。内容大约是:

    1. 不同系统下安装 node.js
    2. 创建命令行工具项目
    3. package.json 结构介绍
    4. 介绍 unrar-promise
    5. 介绍 yargs 实现命令行接口
    6. 开发功能
    7. 发布到 npm

    完成的项目放在 GitHub:meathill/unrar: a simple script to unarchive rar files (github.com) 非常简单,大家可以参考。

    有任何问题、建议均欢迎留言讨论。新的一年,我会努力多做视频、多做好视频,希望大家支持我。

  • 2023 Git 必备知识(二):常见问题解决

    2023 Git 必备知识(二):常见问题解决

    Git 系列文章

    处理 hotfix

    有时候,我们在迭代中间,会发现 master 存在一些 bug,于是我们就需要修复这个 bug。但此时 dev 通常不能合并到 master,于是我们应该在 master 上修复这个 bug。

    1. 此时不需要对 master 与 dev 做合并操作
    2. 我们从 master 上开启新分支,并修复这个 bug
    3. 采用和之前一样的策略完成代码合并
    4. 将 master 上线
    5. 如果此 bug 同时影响 master 与 dev,我们应该在 dev 分支 cherry-pick 这个修复
    6. 迭代发版时,先将 dev rebase master,与 master 同步
    7. 然后切换到 master,快进 git merge dev --ff-only
    8. 如此就完成两个分支的合并,同时保留单线历史记录

    git rebase dev -i

    有时候,我们开发过程中会产生一些冗余 commit。比如,我原先要用 A 方案,
    后来又改成 B 方案。于是,开发 A 方案时产生的 commit 就没有必要存在代码仓库中。

    此时,我们可以使用 git rebase dev -i,启动交互式 rebase,大概会看到这样的输出:

    pick 2662533e feature: plan A
    pick 7af8e1ef feature: plan B

    现在两个 commit 前面都是 pick,表示这两个 commit 我都要。但其实我们只想要第二个,
    就可以把第一个的 pick 改成 squash,或者简写成 s,这样就只会保留第二个 commit。

    s 2662533e feature: plan A
    pick 7af8e1ef feature: plan B

    保存退出,再 git log,就会只剩下第二个 commit 了。

    Note: 强烈建议大家在每次 merge PR 之前,都这样操作一次。删掉所有不必要的 commit,比如自己的尝试、测试同学发现的 bug,等。

    git reset --hard COMMIT

    使用 git reset 的时候,我建议大家轻易不要 git reset --hard COMMIT
    因为这样一不小心代码就丢了。损失难以估量。

    建议大家这样做:

    1. git checkout -b xxx_backup 先备份到新分支。
    2. git reset --mixed COMMIT,回退版本,但是不清除代码修改。
    3. git stash 将修改放入暂存区。
    4. 如果后续操作无误,清理掉暂存区 git stash drop,在删掉没用的备份分支即可

    万一 git reset --hard 失误

    实际上 git reset 只是重置分支头的位置,并不会真的去动 commit,所以那些 commit 其实都还在我们本地,只不过这些 commit 不太容易找到。

    此时我们可以使用 git reflog 查看分支的变更记录,找到之前的 commit 信息,然后再次使用 git reset 把分支指向对的 commit。

    注意:这个方法只适用于修复最近的失误。如果你的代码没有提交(生成 commit),或者 git reset 发生在很久之前,那也就回天乏力。所以日常操作还是要小心。


    上面这些问题都是我日常工作中实际遇到并解决过的。如果你有其它问题不知道怎么解决,欢迎留言提问;如果你对上面的解决方案有不同意见,也欢迎指教。

    下篇会分享一下小技巧和一些问题讨论,敬请期待。

  • 再获思否 Top Writer

    再获思否 Top Writer

    总结的时候说过,2022 年虽然生活很糟心,但是对我个人来说,却是比较有收获的一年。尤其在自媒体方面,B 站粉丝、推特粉丝、思否粉丝都涨了不少,思否基本上坚持一年,每天至少回答一个问题,最终再次拿到问答组 Top Writer 称号。

    喔耶!

    去年文章写的不算多,而且基本都发在自己的博客,没往思否搬,所以年底声望 17k+,没完成去年 25k 的目标。今年尽量多搬运一些,希望声望有所成长。而且,思否目前 5k+ 粉丝,感觉也应该运营一下。

    2023 年,寄望甚多,希望努力能换来收获,希望能帮到更多的人,希望我的自媒体能有所成长。也希望大家多多支持我,多给我点赞、帮我转发,感恩一键三连。提前感谢。


    权威发布 | SegmentFault 思否 2022 年度 Top Writer

  • 2023年直播视频计划

    2023年直播视频计划

    趁着这会儿没正经工作,盘点盘点去年挖下的坑,和一些零星的想法,做一下 2023 年的视频计划。具体执行可能会有变化,当作许愿吧。欢迎关注,欢迎点菜,欢迎提意见,敬请期待。

    日常直播安排

    • 尽量保证每周七天都播
    • 周一至周六,直播写代码、准备 Slide 等
    • 周日直播教学内容,录像剪辑并上传
    • 白天随缘直播,如果写的是自己的东西,可以多播一些

    待填大坑

    去年遗留了几个系列坑还没填,今年争取都填上、填满。

    JS 设计模式

    《设计模式》那本书诞生快 30 年了,还有人在照本宣科死搬硬套的把当年 C++ 的模式拿来简单改改当成 JS 设计模式讲。我想在这个系列里,结合 ESNext、流行框架、类库,讲解设计模式在 2023、JS/TS 领域如何使用。

    这个系列就像酒店里的那些艺术品,摆在那里,没啥人看,但是如果你没有,档次就上不去……目前前两集加起来不到 1k 的播放量,实在让人动力不足……

    Nuxt.js 简历网站开发

    去年年底,Nuxt.js 正式发布 v3;我也正巧需要一个简历工具。于是计划做一个简历分享网站,基于 Nuxt.js+TailwindCSS+DaisyUI+Serverless(leancloud)打造。

    目前缓慢开发中,估计还有一个月能做完。

    Shopify Hydrogen 电商独立建站

    前阵子朋友介绍的活儿,钱不多,但是 Hydrogen 框架很吸引我,于是接了,打算基于它做一套系列教学视频。目前网站开发中,前期的开发很简单,就是改改样式。后面发现 Hydrogen 不支持以前(现有)的插件机制,甲方对产品详情页的一些要求无法实现,所以需要手动开发。正好可以更深入一些。

    预计本月内结项,希望下月初可以周日开始直播。

    Git 规范及技巧

    我以为 2023 年了,不需要再分享 Git。结果结合最近几份工作目睹的现状,看到一些技术论坛上乱七八糟的分享文,决定还是做个系列。

    本周会开始,先做 slide,周日录视频。

    一些散坑

    node.js 开发命令行应用

    早就录完了,尽快把视频剪出来。预计本周三之前上线。

    已经上线:Node.js 开发 RAR 解压缩命令行工具

    工作中学会说不

    春节前一位同学找到我,说绩效被打了 B,心里不爽;尤其让他想不通的是,一个平日里对他仰赖甚多的同事也给他差评。我帮他分析了半天,得到一个结论:工作中要学会给自己定价,要学会说不。

    Web 性能测试

    进阶课程,初学者可能暂时用不到,但是初中晋级必备的知识。估计分成几个方面:

    1. 网页初始化性能评价与优化(视频讲过
    2. JS 函数的性能评价,比如该用 for ... of ... 还是 Array.each
    3. 页面卡顿的排查(普通 JS、Vue)
    4. 内存泄漏的机制与排查

    告别 CSS 预处理工具

    因为一些函数存在冲突、CSS 变量也日益普及,CSS 预处理工具价值越来越小,甚至有时候还要起反作用。所以我现在就在逐步从项目里移除预处理工具,我也计划分享一下这方面的经验。

    WebRTC

    去年留下来的坑,今年有希望填上。等我的 Demo 跑通了就讲这个。

    Vercel 薅羊毛

    Vercel 部署后,用自己的域名 CNAME 就可以放心使用,它又提供了 Severless function / Edge function 功能,免费额度不敌,非常适合我们薅羊毛,写点自己的小应用、放点 demo,之类的。

    总结

    稍微盘一下,发现一年的量已经够了,甚至未必做得完……如果过完年找工作顺利,那几乎一定要留下不少坑明年再来填。所以先这样吧,日后有想法再调整。

    如果你对上面这些内容感兴趣,或者有别的内容想看,也欢迎留言给我。新的一年,我们一起加油。

  • 2023 Git 必备知识(一):常用团队规范

    2023 Git 必备知识(一):常用团队规范

    我一直以为,时至今日,Git 知识应该已经足够普及,常用操作大家都知道,应该不需要分享。没想到换过几份工作之后,发现还有很多同学不清楚、乱用;一些新出的 git 分享文也写得乱七八糟,槽点满满。于是我决定结合之前在 Code.fun 建立的 Git 规范,和分享过的常见操作整理出来,作为虎年兔年承上启下的文章,贡献给大家。

    Git 分享计划

    本系列计划分成三篇文章:

    Git 使用原则

    1. 保障分布式开发:每个人都在自己的分支上开发;可以随时切换不同分支。
    2. 保障历史记录有价值:只保留有价值的 commit,不必要的 commit 应该在合并前 squash。可以通过回溯 commit message,了解到某行代码的意图,做出合理推断。
    3. 减少未来操作成本:只保留一条历史树,不使用 merge 造成混乱的图谱。以便在发版时不因为和代码耽误时间。

    分支设计

    Code.fun 是一家小厂,采用敏捷开发模式,所以不需要维护太多分支。大体上,我们只维护两大类分支:发布分支:master、dev;开发分支:每个人根据需求切出自己的分支进行开发。

    • 正式版本代码放在 master 分支,并且公开发布上线。
    • 迭代中的代码合并到 dev 分支,可能也会提供 dev 环境给部分喜欢尝鲜的用户。
    • 迭代结束后,将 dev 合并回 master,并发布正式版。
    • 启动新迭代,产生新的 dev 分支。

    单线分支原则

    为了保证版本管理的有效性,我们应尽力保持 只有一条线 的版本历史。为此
    有以下注意事项:

    1. 保证本地 dev 与中心仓库一致。
    2. 开发时,从 dev 分支创建开发分支。
      • 如果需求较大、开发时间较长,建议大家经常 rebase,保持和 dev 同步。
    3. 合并前:
      1. 更新本地的 dev 分支,与中心仓库一致。
      2. 将开发分支 rebase 到最新 dev 分支,即在开发分支上,运行 git rebase dev
    4. 拉代码时,尽量使用 git pull --ff-only,避免出现 merge commit。

    开发规范

    1. 新需求启动时,需要创建一个分支进行开发。如果有多个参与者,可以根据实际情况,选择大家在同一个分支下进行开发,或者基于此分支创建更多的子分支进行开发。
    2. 分支名应该包含用户名,与分支名用 / 分隔,形如:{用户名}/{分支名称}
    3. 其中分支名称应该符合 {前缀}-{需求描述},如 feature-新功能
    4. 常见的前缀有:
      • feat(ure): 新功能
      • (bug)fix: 修复 bug
      • chore:构建过程或辅助工具的变更
      • docs: 文档的变更
      • style: 代码风格的变更
      • ref(actor): 重构
      • test: 测试的变更
      • ver(sion): 版本更新
      • text(ure): 文本的变更
      • deps: 依赖变更,即为适配依赖产生的变更
    5. 提交时,commit message 也需添加合适的前缀,如:feature: 支持点击
    6. 分支应随时推入公司仓库。
    7. 需求开发过程中,应尽早创建 PR。PR 完成前,加 [WIP] 前缀。
    8. 开发完成后,部署到测试环境自测。
      • 请结合各公司不同的基础设施,进行部署和自测。之前我厂主要是 k8s、GitHub Actions 等。
    9. 自测后,邀请产品同学体验,邀请测试同学测试。
    10. 体验+测试通过,请其他同事帮忙做 code review。
    11. 修复问题,code review 通过后,再次更新本地 dev 分支,然后使用 git rebase dev -i,将开发分支变基到最新 dev 分支,并 squash 掉价值较小的 commit,只保留有回顾价值的 commit。
    12. 接下来,建议引入自动化测试,进行回归测试。
    13. 使用 git push -f 将变基后的分支再次推入仓库,准备合并。
    14. 合并分支到 dev。此过程若在 GitHub 上操作,只可以使用“Squash and merge“或”Rebase and merge“,不可以使用“Create a merge commit”。如果只打算保留 一个 commit,就用”Squash“。
    15. 迭代周期结束后,合入 master,等待发版。合入后之前所有的开发分支均作废。

    可以说,Git 是现代化软件开发的基础,各种操作规范都建立在 Git 规范之上,比如 CI/CD、自动化测试、Code Review 等等。学会 Git,采用合理的 Git 流程对稳定发布有很大帮助,建议大家都学好 Git、选用简单有效的 Git 规范构建更好的团队。

    上面的规范不一定适应所有团队,但在我长期的开发实践中,这套规则很好的提升了开发效率、保证了代码质量,推荐给大家参考。

    如果你对上文有问题,或者对 Git 有不同理解,欢迎留言评论。

  • “爷爷再见”

    “爷爷再见”

    周三周四,我连续两天梦到奶奶,周五中午跟我老婆说了一声。下午传来消息,爷爷走了。当天晚上,爷爷奶奶一起来到梦中,周六也是如此。梦里的爷爷奶奶还是老样子,胖胖的,慈祥可亲。我给他们介绍我们住的地方,或者领他们出去玩,一如我以前期待很久的那样。我在梦里并不觉得他们已经走了。

    昨天是周日,把爷爷送去火葬,然后,晚上就没再梦到他们。也许,他们是真的走了吧。

    爷爷对我的影响非常之深。很小的时候,爷爷教会我“吾日三省吾身”,这六个字让我受益终身。我不仅日日自省,时时自省,还把这六个字用在 code review 上,收获意想不到的好效果。可惜我现在还没能把这几个字教会给孩子。

    爷爷一句一句教我背会了《满江红》,我第一次感受到什么是国恨家仇、家国情怀。他还试图教会我三字经百家姓声律启蒙这些,然而失败了,我背住的不多。可能他自己也觉得用处不大,所以没有执着。他带我读《上下五千年》,让我对整个中国史有了了解。爷爷很擅长下象棋,水平太高,我怎么也下不赢;他就开始带着我一起学下围棋,我学得很快,很快就超过了爷爷。上高中之前,我们最常对弈的就是围棋。

    爷爷也很喜欢学习,我们工作以后,虽然工作内容、工作形式他都很难理解,但仍然会向我们询问、探讨,给出他自己的理解。

    三观方面,爷爷对我影响很大,尤其是消费观和金钱观。他很喜欢泡澡,我一直很想带他去日本享受温泉,念叨了很多年,因为种种原因一直没能成行,拖着拖着,就拖得再也没有机会了。

    爷爷一生应该还是幸福美满的。他出生时是个小少爷,据说现在老家还有我们翟家胡同。小时候跟着曾祖父南下做生意,家里情况也不错,上了私塾,所以才会教我很多古文知识。读书到高二,因为社会变革没有继续,开始在建筑公司做工,之后被省设计院选拔走,开始土建工程师生涯。我爸兄妹几个也都不错,都有正经工作,正常退休。孙辈也挺好,大家都过得不错。

    希望爷爷在另一个世界跟奶奶相聚时,能够不留遗憾。

    再见,爷爷。

  • Chrome Extension MV3 已知兼容性问题与 Bug

    Chrome Extension MV3 已知兼容性问题与 Bug

    这几天回顾 Chrome Extension MV3,发现官方发布了一篇文章:Known issues when migrating to Manifest V3,准备结合我的经验,摘译过来分享给大家。建议大家还是要看一下原文,而且这篇文章也在不断更新,如果有新内容,也麻烦提醒我更新。目前版本是:2022-12-09,Chrome 108。

    这篇文章列举了已知的、影响开发者将插件迁移到 MV3 的重大问题。答题分为两部分:

    1. 兼容性问题。因为 MV3 的设计而产生的问题。
    2. Bug。纯粹没搞好。

    这篇文章是 Chromium issue 追踪器的子集,全部问题大家可以自行通过标签查找:平台 > 扩展

    新功能完成或者 bug 解决后,会随着稳定版发布。之后,对应的问题就会从这个页面里移除,所以,如果大家想知道问题变更的历史记录,可以去看: What’s New in Chrome Extensions

    兼容性

    【已修复】webRequest.onAuthRequired events

    普通用户安装的 MV3 扩展无法拦截事件。在 Chrome 108 中已修复。

    【已修复】Offscreen Documents API

    MV3 强制把 background page/script 改成 service worker,带来一个问题:以前的 background page 可以渲染页面,也就包含了完整的 DOM API,如今没有了,那么很多依赖 DOM 的功能也都做不到了。比如剪贴板、音乐播放、解析 HTML 等。所以新版本 Chrome 109 里增加了新的 Offscreen Documents API,方便用户使用。

    目前这个 API 的文档很简单,我用 Edge,目前还停留在 108 版本,也没能试用,回头体验了再分享。

    放宽扩展 Service worker 的生命时间

    目前扩展 Service worker 执行一段时间之后就会被终止掉,据我测试大约是 28 秒。未来这个时间长度会动态调整,以便 service worker 的功能能够稳定完成。预计 2023 年一季度开始测试此功能。

    用户脚本管理支持

    目前扩展不允许执行外部脚本,只能执行发布时已经打包进去的那些脚本。导致 GA、FB 这些平台 SDK 很难用,Showman 也一样。下一步,MV3 会提供一个管理工具,让用户授权一些特定代码和样式。

    预计也是 2023 年一季度开始测试。

    给 Storage API 扩容

    目前 Storage 的存储空间是 1MB,开发团队准备适当扩容,具体的数字还没想好。我对这个变化没啥期待,Storage 本来也就存点配置之类的信息,感觉 1M 能存很多了。

    Bugs

    【已修复】Service workers 在 webRequest 时间后不启动

    之前的版本中,MV3 扩展只会在安装后的很短时间里,能够接收到 Web Request API 事件,后面就接收不到了。如今,这个 bug 修复了,发布于 Chrome 107。

    (容我吐个槽,刚开始推广 MV3 的时候,这种 bug 不胜枚举。)

    沙箱页面 CSP 不能配置

    现在的沙箱页面 CSP 无法被用户自定义配置覆盖,会固定使用初始值。大约会在 2023 年一季度开始测试修复。


    总结

    看看这些设计导致的兼容性问题,和开发引入的质量 bug,当初他们有什么信心在 2023 年 1 月完成彻底迁移的?

    我还是那个观点:

    1. MV3 的设计有其合理之处,相对于 MV2 确实是进步
    2. MV3 整个 API 和文档的质量堪忧,给我们带来了大量不必要的工作量
    3. 插件变现很难,大家都用爱发电,这次强推 MV3 实在是不把开发者当人
    4. 希望新的一年里,MV3 能建设完全,并逐步升级

    如果你在开发插件的时候遇到问题,欢迎与我交流。