阅读视图

发现新文章,点击刷新页面。

如何轻松创建并托管你的 GitHub Pages 站点 (无服务器静态应用)


创建一个 GitHub Pages 站点是一个简单的过程,可以免费为你的个人、项目或组织创建网站/博客。按照此指南开始。

步骤 1:创建 GitHub 仓库

  • 登录你的 GitHub 账户。
  • 点击“新建”来创建仓库。
  • 对于个人站点,命名为 .github.io。
  • 对于项目站点,使用任何有效的名称。

步骤 2:添加你的站点文件

使用以下命令克隆仓库到本地机器:

git clone https://github.com/<username>/<repository-name>.git

创建一个 index.html 文件,包含你想要的内容。这里是一个例子:

<!DOCTYPE html>  
<title>我的 GitHub 页面</title>
<h1>欢迎访问我的站点</h1>
<p>这是我的第一个 GitHub Pages 站点。</p>

或者,你可以使用 README.md(Markdown)作为首页。

## 我的 Github 页面
### 欢迎访问我的站点
THis is my first Github Pages site.

将你的更改提交并推送到 GitHub:

git add .
git commit -m "Initial commit"
git push origin main
how-to-setup-github-pages-static-apps 如何轻松创建并托管你的 GitHub Pages 站点 (无服务器静态应用) Github 学习笔记 小技巧 程序设计 网站信息与统计 计算机 计算机

Github 上启用 Github Pages 的步骤

步骤 3:启用 GitHub Pages

  • 转到你的仓库设置。
  • 在侧边栏点击“Pages”。
  • 在“源”下选择分支(例如,main)和文件夹(如果适用)。
  • 点击“保存”。

步骤 4:查看你的站点

  • 对于个人站点:访问 https://<username>.github.io/。
  • 对于项目站点:访问 https://<username>.github.io/<repository-name>/。

步骤 5:自定义你的站点

要添加主题,请转到 Pages 设置并选择“选择一个主题”。

你还可以上传额外的 HTML、CSS 和 JavaScript 文件以进行进一步的自定义。

为什么 GitHub Pages 是“无服务器静态应用” / Serverless Apps

GitHub Pages 作为无服务器静态应用运行,因为它们直接向用户提供预构建的静态 HTML、CSS 和 JavaScript 文件,而不依赖后端服务器或运行时动态内容生成。相反,这些文件托管在 GitHub 的全球内容分发网络(CDN)上,确保快速有效的交付。

优点:

  • GitHub 提供的免费托管。
  • 不需要服务器维护。
  • 由于 CDN 分布,加载速度快。
  • 简化了静态站点的部署和扩展。

缺点:

  • 仅限于静态内容;不支持像数据库这样的服务器端功能。
  • 高级工作流的自定义需要技术知识。
  • 依赖于 GitHub 的基础设施。

GitHub Pages 的总结

GitHub Pages 是一个令人赞叹的免费托管网站的工具。只需几步,你就可以为你的项目、作品集或个人使用创建一个站点。通过利用无服务器模型,你可以构建轻量、高效且维护最小的站点。

英文:How to Setup and Create GitHub Pages (Serverless Static Apps)

本文一共 587 个汉字, 你数一下对不对.
如何轻松创建并托管你的 GitHub Pages 站点 (无服务器静态应用). (AMP 移动加速版本)

扫描二维码,分享本文到微信朋友圈
75a5a60b9cac61e5c8c71a96e17f2d9c 如何轻松创建并托管你的 GitHub Pages 站点 (无服务器静态应用) Github 学习笔记 小技巧 程序设计 网站信息与统计 计算机 计算机
The post 如何轻松创建并托管你的 GitHub Pages 站点 (无服务器静态应用) first appeared on 小赖子的英国生活和资讯.

相关文章:

  1. 英国房子的EPC节能报告(Energe/Efficiency Performance Certificate) EPC (Energe/Efficiency Performance Certificate) 是英国房子的节能报告, 法律上规定, 每个房子都必须要有一个EPC报告, 报告的有效期为十年. 房东在把房子出租或者想卖房的时候, 这个EPC就必须有效, 在一些情况下 比如出租房子的时候, 这个EPC报告还必须符合一些最低标准, 比如房子必须满足 F档(类似及格线)...
  2. 按揭贷款(房贷,车贷) 每月还贷计算器 去年给银行借了17万英镑 买了20万7500英镑的房子, 25年还清. 前2年是定率 Fix Rate 的合同 (年利率2.49%). 每个月大概是还 700多英镑. 有很多种还贷的计算方式, 定率/每月固定 是比较常用的. 简单来说就是 每个月交的钱是...
  3. 最好的发财策略就是忘记它 在群里我和 @nationalpark 说到我用STEEM换了3000多个 YOYOW的时候我还有点沾沾自喜, 谁知道他一针见血: 听说你是steem换的我顿时心理平衡了 才突然想起来, 我半个月前是拿 500 个 STEEM 换了 将近3300个YOYOW. 今天 STEEM的价格8美元,...
  4. 智能手机 HTC One M9 使用测评 虽然我对手机要求不高, 远远没有像追求VPS服务器一样, 但是怎么算来两年内换了四个手机, 先是三星 S4 用了一年多, 然后 Nokia Lumia 635 Windows Phone, 后来又是 BLU, 半年多前换了...
  5. 英国TESCO超市有偿回收瓶子 前不久, 英国剑桥 Bar Hill 的的 TESCO乐购超市推出了一个回收瓶子的机器, 这机器就在超市入入口出. 只需要把瓶子放进去, 机器自动识别, 然后每个瓶子10P也就是相当于1块人民币. 完成后会给个小票, 买东西可以拿来当折扣用. 如果嫌麻烦, 在回收完成还可以选择捐给慈善机构. 机器非常人性化,...
  6. 面试刷题更像是一种服从性测试 在许多求职者看来,面试中的刷题环节似乎是对技术能力的直接考察。然而,从另一个角度来看,这一过程或许更像是一场服从性测试。 想象一下,当一个公司要求候选人解决复杂的算法问题或设计一个系统架构时,真正的目的并不仅仅是判断候选人是否能完成这项任务。许多时候,公司更关心的是你是否愿意花时间和精力去迎合他们的流程和标准。 为什么这样说呢?从实际工作中来看,绝大多数岗位并不需要员工每天都在解决高难度的算法问题或从零设计分布式系统。相反,工作中的任务更偏向于理解业务逻辑、维护现有系统以及团队协作。那么,为什么刷题依然是很多公司青睐的筛选方式? 答案或许在于,刷题能有效筛选出那些愿意投入大量时间准备,并在面试中展现高度配合精神的候选人。这种配合精神,是公司希望在未来的工作中看到的品质。一旦你通过了这些测试,公司就会认为你是一个值得信赖的员工,一个能遵从流程、适应规则并在需要时投入额外努力的人。 还有就是以前说的:面试刷力扣是大公司过滤的成本较低的方法之一:为啥有名的IT公司的程序员面试都这么难?,可以过滤掉大部分 False Positive,当然也有可能过滤掉人才(胜任工作的求职者)。不过对于大厂来说,招进来一个False Positive的损害要远远比错过一个False Negative大。 此外,随着AI技术的飞速发展,刷题的技术价值正在逐渐降低。像ChatGPT这样的AI工具,已经可以轻松解决LeetCode或Codeforces上的许多高难度问题,并给出清晰的解题过程。这表明,算法题不再是人类独有的技术优势,而是可以被高效地自动化处理的任务。这种变化进一步凸显了刷题在实际工作中的局限性,因为日常工作更多依赖于沟通、业务理解和对系统的长期维护,而不是短时间内解决某个抽象问题。 OpenAI推出o3大语言AI模型。 Codeforces 评分:2727——相当于全球人类程序员编码竞赛中,排名第 175 位。...
  7. 英国 NatWest 银行推出 Reward Current Account 用来交水电费等帐单可以省钱 英国 NatWest 银行推出 Reward Current Account 银行帐号, 每个月需要交会费 3 英镑, 一年则需要36英镑 并不便宜, 但是好处是 只要通过该帐号以 Direct...
  8. 离开 NPower – 在英国选择便宜的电气公司 extraenergy 在彻底离开 谢菲尔得的那一天 和房东一起读了 电表, 公寓里只用电 没有媒气 所以做饭也用电 特别贵. 虽然在 13年底装了 两个电表. 白天一个 晚上 12点到早上7点另一个表, 所以两个计费....

Sui 区块链编程: 通过 NodeJs/Javascript 函数获取 Gas 费用


在区块链开发的世界中,理解和管理gas费用对于优化交易至关重要。Sui作为一个相对较新但功能强大的区块链平台,有其独特的方式来处理gas价格。让我们来探讨如何使用Node.js和JavaScript获取Sui的gas价格。

Sui中的Gas理解

在区块链语境中,gas指的是执行交易或智能合约所需的费用。在Sui中,gas以MIST计量,其中1个SUI等于10^9个MIST。这意味着gas价格通常以每个交易或操作的MIST来报价。

获取Gas价格

这里有一个简单的异步函数来从Sui节点获取当前的gas价格:

const QUICKNODE_URL = "https://sui-mainnet-endpoint.blockvision.org"; // 你可以使用你自己的节点。

async function getGasPrice() {
    try {
      const response = await axios.post(QUICKNODE_URL, {
        method: "suix_getReferenceGasPrice",
        jsonrpc: "2.0",
        id: 1,
        params: [],
      });
      return parseFloat(response.data.result);
    } catch (error) {
      console.error("获取gas价格时发生错误:", error);
      return null;
    }
}

代码解析

  • axios.post: 我们使用axios向Sui RPC节点发送HTTP POST请求(假设QUICKNODE_URL在其他地方已定义为正确的URL)。
  • 方法和JSON-RPC: 使用 suix_getReferenceGasPrice 方法查询gas价格。采用JSON-RPC 2.0协议进行通信。
  • 错误处理: 如果获取gas价格时发生错误,会记录错误,并返回null以表示失败。

使用函数

你可以在异步上下文中调用这个函数:

(async () => {
  const gasPrice = await getGasPrice();
  if (gasPrice !== null) {
    console.log(`当前gas价格: ${gasPrice} MIST`);
  } else {
    console.log("无法获取gas价格。");
  }
})();

重要说明:

  • MIST: 返回的gas价格是以MIST计量的。为了实际应用,你可能需要将它转换为SUI以增加可读性,使用 gasPrice / 10^9。
  • QuickNode URL: 你需要用你实际的RPC节点URL替换QUICKNODE_URL。如果你不使用QuickNode,你可以连接到任何支持此RPC方法的Sui节点。
  • 异步特性: 记住,区块链交互本质上是异步的,因此使用async/await来处理promise。

获取Sui区块链Gas费用/价格的结论

使用Node.js获取Sui中的gas价格是直接的,但需要理解区块链gas机制的细微差别以及JSON-RPC通讯。这个代码片段可以作为开发者开始将gas价格检查整合到他们的Sui区块链应用中的起点,确保他们能够有效管理交易成本。

英文:Sui Blockchain Programming: Get the Gas Fee via NodeJs/Javascript Function

Sui 区块链编程

本文一共 496 个汉字, 你数一下对不对.
Sui 区块链编程: 通过 NodeJs/Javascript 函数获取 Gas 费用. (AMP 移动加速版本)

扫描二维码,分享本文到微信朋友圈
75a5a60b9cac61e5c8c71a96e17f2d9c Sui 区块链编程: 通过 NodeJs/Javascript 函数获取 Gas 费用 Javascript Node Js Sui 加密货币 区块链 程序设计 计算机 计算机
The post Sui 区块链编程: 通过 NodeJs/Javascript 函数获取 Gas 费用 first appeared on 小赖子的英国生活和资讯.

相关文章:

  1. 油管视频/Youtube Premium会员的好处: 用了就回不去了 从前年开始,我成为了 YouTube 会员,不过中间时断时续,因为觉得价格有点贵。在英国,YouTube 家庭会员每月费用是 19.99 英镑(可供五位家人共享),而个人会员则是每月 12.99 英镑。去年回国前,我暂停了一段时间的会员服务,但回到英国后发现自己已经离不开 YouTube 会员了。 成为会员的最大好处就是没有广告。最初,YouTube 是没有广告的,但随着平台上视频数量激增,广告也逐渐多了起来。如今,YouTube 已然是长视频的王者,谷歌当年的收购绝对算得上是一次非常成功的商业决策,足以写进教材。随着视频数量越来越多,用户一辈子也看不完平台上的内容,所需的服务器资源也水涨船高。因此,谷歌插入广告确实无可厚非。然而,从最开始的一两个广告,到如今非会员用户每隔五分钟就得忍受一次广告,用户体验确实大打折扣。 会员的另一个好处是可以下载视频,不过并不是直接下载为视频文件.mp4,而是保存在设备上。这样一来,可以提前下载好音乐或视频,开车时就无需耗费流量了。 此外,YouTube...
  2. TikTok未能出售: 流量“难民”涌入小红书, 能否接得住? 最近,随着TikTok因监管压力未能在1月19日前完成出售事宜,大量的内容创作者和用户正在寻找新的平台安置自己的内容生态和社交网络。这一波流量转移,意外地将小红书(RedNotes)推向了风口浪尖。打开小红书,推荐页面中已经充满了国外用户的身影,甚至有用户戏称“小红书变成了‘国际版种草机’”。然而,这一流量迁徙带来的热闹背后,蕴藏着深刻的挑战和机会。 不过,由于美国新政府很快就要上台了,特朗普对抖音是比较友好的,所以目前这种局面可能会迎来新的转机。拜登政府上台后,政策方向可能会与特朗普有所不同,尤其是在针对中国企业的态度上,可能会采取更加审慎的评估方式,而不是简单的封杀或施压。 对于TikTok而言,这或许意味着缓冲的机会。一方面,拜登政府可能会重新审视TikTok在美国的安全问题,并尝试通过更为温和的方式解决争议,比如进一步完善数据监管和用户隐私保护,而非直接推动出售或下架。另一方面,如果政策有所松动,TikTok也许能够在国际市场重新站稳脚跟,挽回部分因政策不确定性流失的用户和广告商。 不过,这种转机并非完全没有挑战。TikTok必须快速适应美国监管层面可能提出的新要求,比如建立更加透明的数据管理流程、确保服务器本地化、以及加强对算法和内容分发的自我监督。此外,TikTok还需要修复此前因封杀风险导致的品牌信任危机,重新赢得用户和合作伙伴的信赖。 对于小红书来说,这也可能是一个需要重新评估全球化策略的时刻。如果TikTok因政策调整成功稳定住国际市场,那么这波流量“难民”可能会逐渐回归,甚至减少在小红书上的活跃度。这要求小红书在短期内快速吸引这些用户,并通过强化社区黏性和内容多样化,尽可能锁住这批流量。同时,小红书也需要未雨绸缪,为可能到来的用户流失准备应对策略。 无论TikTok是否会迎来转机,这场流量的争夺战都表明,在全球化的竞争中,灵活应变、长期规划和技术实力才是赢得用户和市场的关键因素。 外来流量与用户画像的冲突 小红书一直以其独特的社区氛围闻名,聚焦于生活方式、种草推荐和用户亲身体验分享,目标用户以中国年轻女性为主。随着大量国际用户的涌入,这一平台的内容调性可能面临巨大的冲击。很多本地用户已经开始抱怨,算法推荐的内容逐渐变得“陌生”,甚至暴露了个人的兴趣偏好。这种文化差异和用户需求的差异,可能会对小红书社区的核心黏性带来挑战。 不过,对于小红书来说,国际流量的到来也可能是一种绝佳的扩展契机。如果能够妥善应对文化融合问题,同时优化算法和内容分发策略,小红书完全有机会成为全球用户的内容分享平台,撬动TikTok留下的空白市场。 连夜招募的“英文审核”反映了什么? 面对流量的猛增,小红书显然已经嗅到了机会。平台据称正在连夜招募英文审核团队,足见其对全球化的重视和危机意识。审核机制的建立是平台内容生态的重要一环,尤其是当国外用户涌入时,如何维持内容的合法性、合规性和调性,将决定小红书能否将这波流量真正留住。 目前来看,这种快速扩展反映了小红书的敏捷反应能力,但从长期来看,审核机制的完善需要时间,语言和文化隔阂可能会导致内容质量在短期内下降。同时,海外用户的内容生产习惯与中国用户不同,是否能够在算法推荐和审核效率之间找到平衡,也是一个值得关注的问题。 小红书的变现模式是否支撑得住? 流量增长对于任何平台来说都是一次巨大的红利,但能否将流量转化为收入才是真正的考验。小红书的商业模式以种草电商为核心,通过“内容+电商”的闭环完成流量变现。然而,国际市场中用户的购买力、消费习惯以及对本土化商品的接受程度,都可能成为变现过程中的障碍。 国际用户的涌入如果只是短期行为,或者消费习惯难以转化为实际的电商订单,那么平台即便流量激增,也很难转化为长期收益。相比之下,TikTok的变现模式更依赖广告,而小红书的广告收入占比相对较低。如果能够快速调整策略,比如增加短视频广告位或推出国际版电商模块,小红书或许能在全球市场中占得一席之地。...
  3. 剑桥网红餐厅 The Ivy Cambridge Brasserie 上周刚过40岁生日,媳妇带我去剑桥的一家网红餐厅——The Ivy Cambridge Brasserie。这家餐厅是朋友推荐的,和那家Trinity一样很有名,可惜我们在剑桥待了近10年才知道。 The Ivy Cambridge Brasserie 是剑桥市中心一家备受欢迎的网红餐厅,位于历史悠久的 Trinity Street。餐厅设计时尚典雅,融合了现代与经典元素,为食客提供了一个舒适而奢华的用餐环境。这里的菜单丰富多样,覆盖全天用餐,从早餐到晚餐以及下午茶,提供英式经典美食如松露鸡肉派、英式早餐等,也有一些国际风味的菜肴。得天独厚的位置和独特的氛围使得 The Ivy Cambridge Brasserie...
  4. 负电价活久见: 安装Octopus智能电表省电费甚至赚钱 前几周我的电气公司 Octopus 终于来装智能电表了(Smart Meter),虽然是免费安装的,但是排队排了有两三年了吧。因为之前一直写邮件催的时候就老是说 Not Ready。 收到邮件说可以安装智能电表我还是相当开心和期待的,因为已经听说这玩意好,但是还是得亲身体验一下。工程师来安装大概不到2小时,其中需要停电闸一会儿,重新接下线。装好后,给了个小册子,自动切换到了 Agile 的电价,也就是每半小时的电价都不一样,提前一天可以在手机App和网站上查得。 正好在原来的电价计费合同快要结束前2天换到了智能电表计价 Octopus Agile方式,但是系统还是扣了我75英镑 Exit Fee (提前合同结束得交违约费),不过我一个电话打过去,公司很爽快就给我退了。...
  5. 按揭贷款(房贷,车贷) 每月还贷计算器 去年给银行借了17万英镑 买了20万7500英镑的房子, 25年还清. 前2年是定率 Fix Rate 的合同 (年利率2.49%). 每个月大概是还 700多英镑. 有很多种还贷的计算方式, 定率/每月固定 是比较常用的. 简单来说就是 每个月交的钱是...
  6. 你给SteemIt中文微信群拖后腿了么? 这年头不缺算法, 就缺数据. 这两天花了很多时间在整API上, 整完之后自己用了一下还觉得真是挺方便的. 今天就突然想看一看自己是否给大家拖后腿了, 于是调用每日中文区微信群排行榜单的API, 刷刷拿着 NodeJs 练手: 1 2 3 4 5 6...
  7. ACM题解系列之 – 最小堆栈 (Min Stack) 没事刷刷题能防止老年痴呆, 而且也能让你随时处于最佳状态, 随时都可以炒老板鱿鱼另谋高就. 题目: 设计一个堆栈(Stack)使 push, pop, 和取最小 min 操作时间复杂度都是 O(1). 这题的难点就是在于怎么样用O(1)常数时间复杂度来取得堆栈里的最小值. class MinStack {...
  8. HPZ800服务器主板太老不支持超过2TB的大硬盘 我家里一直用的是HPZ800服务器, 很吵, 很老, 虽然这台服务器已经有十年之久(我在EBAY上买来用了五年多了), 但是即使放到今天, 这服务器速度依旧很快, 很稳定. 由于服务器用的是ECC较验内存, 所以基本上不重启关机. HPZ800主机有两个硬核CPU – 因特志强 X5650 – 每个CPU是12核....

Sui区块链编程: 获取最新块高度(NodeJs/Javascript函数 Latest Block Number/Height)


获取最新区块号(高度)是开发人员在去中心化系统中常见的任务。如果你正在使用 Sui 区块链,并希望通过 Node.js 和 JavaScript 获取最新的区块高度,以下是一个简单的实现方法。

Sui 是一个高性能、可扩展的区块链,以低延迟和创新架构而闻名。与 Sui 的交互需要利用其 API,这些 API 允许开发人员无缝查询区块链数据并与智能合约交互。首先,确保你已在计算机上设置了 Node.js 环境并安装了必要的依赖项。

了解 Sui 区块链:Sui区块链简介

首先,创建一个新的 Node.js 项目。你可以使用以下命令初始化项目:

mkdir sui-block-height
cd sui-block-height
npm init -y

接下来,安装 Axios 库,它通常用于在Node.js中发起 HTTP 请求。我们将用它从 Sui 区块链 API 获取数据:

npm install axios

现在,创建一个名为 getLatestBlock.js 的文件,并在你喜欢的代码编辑器中打开。在这个脚本中,我们将编写一个函数来获取最新的区块高度。Sui 区块链提供了一个 RPC 端点,允许你查询其状态。这个端点是获取区块数据的关键。

以下是代码:

const axios = require('axios');

// Sui RPC 端点 - 如果使用特定网络,请替换为实际端点 
const SUI_RPC_URL = 'https://fullnode.sui.io/v1';

async function getLatestBlockHeight() {
    try {
        // 向 Sui RPC 端点发送 POST 请求
        const response = await axios.post(SUI_RPC_URL, {
            jsonrpc: '2.0',
            id: 1,
            method: 'sui_getLatestCheckpointSequenceNumber',
            params: []
        });
        if (response.data && response.data.result !== undefined) {  
            console.log(`最新区块高度: ${response.data.result}`);  
            return response.data.result;  
        } else {  
            throw new Error('响应结构异常');  
        }  
    } catch (error) {  
        console.error('获取区块高度失败:', error.message);  
        throw error;  
    }  
}

// 运行函数
getLatestBlockHeight().catch((err) => {
    console.error('Failed to fetch the block height:', err);
});

Node.js 代码解析

  • Axios 请求:我们使用 Axios 向 Sui RPC 端点发送 POST 请求。方法 sui_getLatestCheckpointSequenceNumber 用于获取区块链上的最新区块号(或检查点序列号)。
  • 错误处理:正确的错误处理可以确保网络错误或响应格式异常被记录,便于调试。
  • 日志记录:函数将最新的区块高度输出到控制台,这对于快速测试或调试非常有用。

在运行脚本之前,确保 Sui RPC 端点正确且可访问。示例中提供的 URL 指向 Sui 主网的全节点端点。如果你使用的是测试网或本地实例,请将 SUI_RPC_URL 变量替换为合适的端点。

运行脚本的命令:

node getLatestBlock.js

如果设置正确,你应该在控制台中看到打印的最新区块高度。此函数可以轻松集成到更大的应用程序中,或通过修改 RPC 方法和参数来适应其他区块链数据的获取需求。

实时交互区块链数据是构建去中心化应用程序的关键技能。借助 Sui 区块链强大的 API 和 Node.js 的简单性,你可以快速获取最新区块高度,并将此信息用于各种用途,例如监控网络、更新用户界面或触发应用程序中的特定操作。

随着 Sui 生态系统的发展,及时关注其文档和最佳实践可以确保你的集成高效且可靠。

英文:NodeJs/Javascript Function to Get the Latest Block Number (Height) on the Sui Blockchain

Sui 区块链编程

本文一共 729 个汉字, 你数一下对不对.
Sui区块链编程: 获取最新块高度(NodeJs/Javascript函数 Latest Block Number/Height). (AMP 移动加速版本)

扫描二维码,分享本文到微信朋友圈
75a5a60b9cac61e5c8c71a96e17f2d9c Sui区块链编程: 获取最新块高度(NodeJs/Javascript函数 Latest Block Number/Height) Javascript Node Js Sui 区块链 学习笔记 小技巧 程序设计 计算机
The post Sui区块链编程: 获取最新块高度(NodeJs/Javascript函数 Latest Block Number/Height) first appeared on 小赖子的英国生活和资讯.

相关文章:

  1. 油管视频/Youtube Premium会员的好处: 用了就回不去了 从前年开始,我成为了 YouTube 会员,不过中间时断时续,因为觉得价格有点贵。在英国,YouTube 家庭会员每月费用是 19.99 英镑(可供五位家人共享),而个人会员则是每月 12.99 英镑。去年回国前,我暂停了一段时间的会员服务,但回到英国后发现自己已经离不开 YouTube 会员了。 成为会员的最大好处就是没有广告。最初,YouTube 是没有广告的,但随着平台上视频数量激增,广告也逐渐多了起来。如今,YouTube 已然是长视频的王者,谷歌当年的收购绝对算得上是一次非常成功的商业决策,足以写进教材。随着视频数量越来越多,用户一辈子也看不完平台上的内容,所需的服务器资源也水涨船高。因此,谷歌插入广告确实无可厚非。然而,从最开始的一两个广告,到如今非会员用户每隔五分钟就得忍受一次广告,用户体验确实大打折扣。 会员的另一个好处是可以下载视频,不过并不是直接下载为视频文件.mp4,而是保存在设备上。这样一来,可以提前下载好音乐或视频,开车时就无需耗费流量了。 此外,YouTube...
  2. 负电价活久见: 安装Octopus智能电表省电费甚至赚钱 前几周我的电气公司 Octopus 终于来装智能电表了(Smart Meter),虽然是免费安装的,但是排队排了有两三年了吧。因为之前一直写邮件催的时候就老是说 Not Ready。 收到邮件说可以安装智能电表我还是相当开心和期待的,因为已经听说这玩意好,但是还是得亲身体验一下。工程师来安装大概不到2小时,其中需要停电闸一会儿,重新接下线。装好后,给了个小册子,自动切换到了 Agile 的电价,也就是每半小时的电价都不一样,提前一天可以在手机App和网站上查得。 正好在原来的电价计费合同快要结束前2天换到了智能电表计价 Octopus Agile方式,但是系统还是扣了我75英镑 Exit Fee (提前合同结束得交违约费),不过我一个电话打过去,公司很爽快就给我退了。...
  3. 测测你的幸运 – Linux Fortune-Teller LINUX 下有很好很好玩的命令,之前已经介绍过: figlet, rig, curl. 现在推荐另一个 命令 fortune 是用来随机显示一段(句)话的.fortune 在英文里就是幸运的意思. 这个命令可以不需要 参数 如果没有 可以通过 apt-get...
  4. HPZ800服务器主板太老不支持超过2TB的大硬盘 我家里一直用的是HPZ800服务器, 很吵, 很老, 虽然这台服务器已经有十年之久(我在EBAY上买来用了五年多了), 但是即使放到今天, 这服务器速度依旧很快, 很稳定. 由于服务器用的是ECC较验内存, 所以基本上不重启关机. HPZ800主机有两个硬核CPU – 因特志强 X5650 – 每个CPU是12核....
  5. 按揭贷款(房贷,车贷) 每月还贷计算器 去年给银行借了17万英镑 买了20万7500英镑的房子, 25年还清. 前2年是定率 Fix Rate 的合同 (年利率2.49%). 每个月大概是还 700多英镑. 有很多种还贷的计算方式, 定率/每月固定 是比较常用的. 简单来说就是 每个月交的钱是...
  6. 给孩子零花钱培养孩子正确的金钱观价值观 两个娃已经不知不觉7岁8岁了. 媳妇和我商量一下决定给孩子每人每周5英镑的零花钱(Pocket Money). 这样他们慢慢的就有自己的小积蓄备将来不时之需: 比如朋友聚会生日啥的需要准备礼物. 同时, 我们决定不再给孩子买零食(薯片啥的). 孩子一天好几餐, 晚上睡觉前还得吃零食, 我们就多买了很多水果面包, 健康的食物多吃一些总不是啥坏事. 孩子可以用这些零钱买自己想要的东西, 我们也不再过问. 孩子有自己的决定权. 第一周的时候,...
  7. 剑桥网红餐厅 The Ivy Cambridge Brasserie 上周刚过40岁生日,媳妇带我去剑桥的一家网红餐厅——The Ivy Cambridge Brasserie。这家餐厅是朋友推荐的,和那家Trinity一样很有名,可惜我们在剑桥待了近10年才知道。 The Ivy Cambridge Brasserie 是剑桥市中心一家备受欢迎的网红餐厅,位于历史悠久的 Trinity Street。餐厅设计时尚典雅,融合了现代与经典元素,为食客提供了一个舒适而奢华的用餐环境。这里的菜单丰富多样,覆盖全天用餐,从早餐到晚餐以及下午茶,提供英式经典美食如松露鸡肉派、英式早餐等,也有一些国际风味的菜肴。得天独厚的位置和独特的氛围使得 The Ivy Cambridge Brasserie...
  8. Pi币简介: 这真的是区块链上的虚拟货币么? 前几年就听说有一个币叫Pi,但又有听说这币就是屎币不靠谱,说是手机装个APP就能挖。 Pi币(Pi Network)是一种由移动应用程序推广的加密货币项目,据称其目标是让普通人能够通过手机“挖矿”来获得加密货币。以下是对Pi币的详细介绍: Pi币的特点与工作机制 挖矿方式 Pi币的挖矿与传统的工作量证明(PoW,如比特币)不同,它通过一款手机应用完成。用户每天登录应用,点击“挖矿”按钮,即可开始“挖矿”。这种机制主要是为了降低参与的技术门槛和硬件成本。 共识机制 Pi币声称使用的是一种基于“Stellar Consensus Protocol”(SCP,恒星共识协议)的机制。这种共识机制并不像比特币或以太坊那样依赖大量计算能力,而是依赖信任图谱,即用户间的信任关系来达成共识。 无需耗费算力 Pi币的挖矿并不依赖用户手机的计算资源,因此不会显著增加电池消耗或数据使用。这与其他加密货币的能耗问题形成了鲜明对比。 网络层级 先锋(Pioneer):普通用户,每天签到获得Pi币。 贡献者(Contributor):构建信任图谱,通过邀请新用户加入。...

编程: NodeJs/Javascript 函数检查Tron/波场区块链上的交易是否已确认(TronGrid API)


我们想知道给定的交易是否已经在 Tron/波场 区块链上确认,这可以通过 TronGrid API 轻松实现。

tron-blockchain 编程: NodeJs/Javascript 函数检查Tron/波场区块链上的交易是否已确认(TronGrid API) Javascript 区块链 波场 (TRON) 程序设计

tron-blockchain

为了确保交易在Tron/波场区块链上被确认,验证逻辑应关注交易的状态,这表明交易是否已被 Tron 虚拟机(TVM)成功处理。以下是正确的验证方法:

检查 receipt.result

验证交易成功的主要标志是 receipt.result 字段。值为 “SUCCESS” 表明交易已成功处理且无任何错误。

确认区块号

交易仅在被包含进一个区块后才算确认。确保 transactionInfo.blockNumber 已定义且与预期的区块一致。

考虑额外的指标

某些交易可能不会生成 net_usage,但可能会产生 net_fee。检查诸如 net_feenet_usage 的任何资源使用情况,可以让验证逻辑更加全面和完全可靠。

避免过早确认

确保交易不再是挂起状态,并已成功广播到网络中。

验证逻辑

以下是处理各种边界情况的逻辑:

const isConfirmed = transactionInfo =>
  transactionInfo.blockNumber !== undefined && // 确保交易已包含在区块中 
  transactionInfo.receipt && // Receipt is present
  (
    transactionInfo.receipt.result === 'SUCCESS' || // 明确的成功结果
    transactionInfo.receipt.net_usage > 0 || // 使用了资源
    transactionInfo.receipt.net_fee > 0 // 产生了费用
  );

代码解释:

  • transactionInfo.blockNumber:确保交易已成为区块链的一部分。
  • transactionInfo.receipt.result:确认交易执行的状态。
  • transactionInfo.receipt.net_usage / transactionInfo.receipt.net_fee:验证资源的使用情况,确保交易对链上状态有实际影响。

最佳实践:

  • 监控交易事件:使用 TronGrid 的事件订阅功能,实时跟踪交易的确认状态。
  • 增加确认等待:等待多个区块确认,以减少链重组导致交易无效的风险。
  • 记录并处理错误:如果交易失败,请检查 contractResult 和 logs 中的错误详情。

这种方法可确保 Tron 系统中的交易确认过程稳健可靠。

完整的 JavaScript函数代码用于验证波场区块链上的交易

以下是一个基于 Node.js(JavaScript)的函数,它可以通过 TronGrid API 确认或验证 Tron 区块链上的交易。此函数需要使用 axios 库来执行 HTTPS API 调用。

const axios = require('axios');

async function isTransactionConfirmed(transactionID, appKey) {
    try {
        const response = await axios.post(
            'https://api.trongrid.io/walletsolidity/gettransactioninfobyid',
            { value: transactionID },
            {
                headers: {
                    'accept': 'application/json',
                    'content-type': 'application/json',
                    'TRON-PRO-API-KEY': appKey
                }
            }
        );
  
        const transactionInfo = response.data;
        const isSuccess = (transactionInfo.receipt && transactionInfo.receipt.result === 'SUCCESS') || ((transactionInfo.blockNumber !== undefined) && (transactionInfo.receipt.net_usage > 0 || (transactionInfo.receipt.net_fee > 0)));
        const blockNumber = transactionInfo.blockNumber;
        
        console.log(`BlockNumber ${blockNumber}, ${JSON.stringify(transactionInfo)} Transaction ID: ${transactionID} - Status: ${isSuccess ? 'Confirmed' : 'Failed'}`);
        if (!isSuccess) {
            console.log(JSON.stringify(transactionInfo));
        }
        return {
          "ok": isSuccess, 
          "block": blockNumber
        };
    } catch (error) {
        console.error('Error verifying transaction:', error);
        throw error;
    }
}

英文:NodeJs/Javascript Function to Check if a Transaction is Confirmed on Tron Blockchain via TronGrid API

区块链技术

本文一共 540 个汉字, 你数一下对不对.
编程: NodeJs/Javascript 函数检查Tron/波场区块链上的交易是否已确认(TronGrid API). (AMP 移动加速版本)

扫描二维码,分享本文到微信朋友圈
75a5a60b9cac61e5c8c71a96e17f2d9c 编程: NodeJs/Javascript 函数检查Tron/波场区块链上的交易是否已确认(TronGrid API) Javascript 区块链 波场 (TRON) 程序设计
The post 编程: NodeJs/Javascript 函数检查Tron/波场区块链上的交易是否已确认(TronGrid API) first appeared on 小赖子的英国生活和资讯.

相关文章:

  1. 给孩子零花钱培养孩子正确的金钱观价值观 两个娃已经不知不觉7岁8岁了. 媳妇和我商量一下决定给孩子每人每周5英镑的零花钱(Pocket Money). 这样他们慢慢的就有自己的小积蓄备将来不时之需: 比如朋友聚会生日啥的需要准备礼物. 同时, 我们决定不再给孩子买零食(薯片啥的). 孩子一天好几餐, 晚上睡觉前还得吃零食, 我们就多买了很多水果面包, 健康的食物多吃一些总不是啥坏事. 孩子可以用这些零钱买自己想要的东西, 我们也不再过问. 孩子有自己的决定权. 第一周的时候,...
  2. 剑桥网红餐厅 The Ivy Cambridge Brasserie 上周刚过40岁生日,媳妇带我去剑桥的一家网红餐厅——The Ivy Cambridge Brasserie。这家餐厅是朋友推荐的,和那家Trinity一样很有名,可惜我们在剑桥待了近10年才知道。 The Ivy Cambridge Brasserie 是剑桥市中心一家备受欢迎的网红餐厅,位于历史悠久的 Trinity Street。餐厅设计时尚典雅,融合了现代与经典元素,为食客提供了一个舒适而奢华的用餐环境。这里的菜单丰富多样,覆盖全天用餐,从早餐到晚餐以及下午茶,提供英式经典美食如松露鸡肉派、英式早餐等,也有一些国际风味的菜肴。得天独厚的位置和独特的氛围使得 The Ivy Cambridge Brasserie...
  3. 负电价活久见: 安装Octopus智能电表省电费甚至赚钱 前几周我的电气公司 Octopus 终于来装智能电表了(Smart Meter),虽然是免费安装的,但是排队排了有两三年了吧。因为之前一直写邮件催的时候就老是说 Not Ready。 收到邮件说可以安装智能电表我还是相当开心和期待的,因为已经听说这玩意好,但是还是得亲身体验一下。工程师来安装大概不到2小时,其中需要停电闸一会儿,重新接下线。装好后,给了个小册子,自动切换到了 Agile 的电价,也就是每半小时的电价都不一样,提前一天可以在手机App和网站上查得。 正好在原来的电价计费合同快要结束前2天换到了智能电表计价 Octopus Agile方式,但是系统还是扣了我75英镑 Exit Fee (提前合同结束得交违约费),不过我一个电话打过去,公司很爽快就给我退了。...
  4. 测测你的幸运 – Linux Fortune-Teller LINUX 下有很好很好玩的命令,之前已经介绍过: figlet, rig, curl. 现在推荐另一个 命令 fortune 是用来随机显示一段(句)话的.fortune 在英文里就是幸运的意思. 这个命令可以不需要 参数 如果没有 可以通过 apt-get...
  5. HPZ800服务器主板太老不支持超过2TB的大硬盘 我家里一直用的是HPZ800服务器, 很吵, 很老, 虽然这台服务器已经有十年之久(我在EBAY上买来用了五年多了), 但是即使放到今天, 这服务器速度依旧很快, 很稳定. 由于服务器用的是ECC较验内存, 所以基本上不重启关机. HPZ800主机有两个硬核CPU – 因特志强 X5650 – 每个CPU是12核....
  6. ChatGPT-4 使用 Math Wolfram 插件解决数学脑筋急转弯问题 这篇文章, 我们看一个简单的数学问题(脑筋急转弯), 并用 Python 解决它. 我们看一下LLM(大型语言模型): ChatGPT3.5和ChatGPT4. 通过 ChatGPT-Plus 订阅(目前每月 20 美元 + VAT增值税), 我们可以启用...
  7. 按揭贷款(房贷,车贷) 每月还贷计算器 去年给银行借了17万英镑 买了20万7500英镑的房子, 25年还清. 前2年是定率 Fix Rate 的合同 (年利率2.49%). 每个月大概是还 700多英镑. 有很多种还贷的计算方式, 定率/每月固定 是比较常用的. 简单来说就是 每个月交的钱是...
  8. 智能手机 HTC One M9 使用测评 虽然我对手机要求不高, 远远没有像追求VPS服务器一样, 但是怎么算来两年内换了四个手机, 先是三星 S4 用了一年多, 然后 Nokia Lumia 635 Windows Phone, 后来又是 BLU, 半年多前换了...

如何强制pnpm通过git HTTP安装npm包

某个版本之前都是通过HTTP安装托管在git源上的npm包的,然而似乎某个版本开始就有可能采取SSH连接的方式。然而,SSH需要SSH Key才可以连接到git源(仅以Github为例),这样的策略会导致在一些CI上无法安装依赖(例如Vercel),得到这样的错误: 这个问题碰到很久了。观察发现在安装时,会随机地从HTTP或Git拉取包,所以每一次安装依赖以后,Git包的来源都可能发生变化。所以之前都是反复安装然后最终得到从加载的结果时再上传。是的,很粗暴。 今天终于想彻底地修一下这个问题。机缘巧合找到了这么一篇GIST,引用如下: 试了一下果然管用,爽到。 当然也可能是正好随机到codeload了?有待观察。 所以我之前又翻文档又翻文档试图找到一个config或者cli option来解决问题实在走错路了,

来源

基于P站(Poloniex)的广度优先搜索算法来获得任意两种币的兑换价格


币圈的P站是Poloniex,前几年被孙宇晨收购了,它是一个交易所。我很久之前用过Poloniex,当时对其印象并不是很好。

不过,现在我对其好感增加,因为币安买下的coinmarketcap免费的接口就很多限制。

官方文档),这个接口的频率限制是一秒200次,很慷慨了。

https://api.poloniex.com/markets/price

能返回所有交易配对,比如这样的:

[
    {
        "symbol": "BTS_BTC",
        "price": "0.0000000186",
        "time": 1731852313035,
        "dailyChange": "-0.0462",
        "ts": 1731852313054
    },
    {
        "symbol": "DASH_BTC",
        "price": "0.000317",
        "time": 1731848096481,
        "dailyChange": "0.0063",
        "ts": 1731848096489
    },
    ... ...
]

这个JSON返回的结构是一个数组,每个元素是个结构体,也就是一个币价的具体配对信息,我们可以看成是一条边Edge两个顶点Vertice,这样就是一个图结构(带权图 Weighted Graph,权值就是兑换价格),虽然给的是单边,但其实是个双向的,比如USD_BTC得值可以反过来推得BTC到USD的价格。我们可以设计一个算法,从币价A到币价B,可以通过BFS广度优先搜索算法来获取价格。比如有配对A_B、B_C、C_D我们就可以获得A_D的值。

深度优先搜索算法DFS也可以,不过这个算法会返回找到的第一条路径,并不能保证是最短的,最短的确实是最准确的,因为链也长,转换精度就会下降。

当然,可能存在多条路径,最理想的状态是把这些路径都求出来,取个平均啥的,不过这样就得暴力搜索所有的路径了,算法时间复杂度就会比较高。

以下是BFS广度优先算法的代码,Javascript的,可以用于网页前端或者NodeJs后端,甚至是CloudFlare Serverless Worker或者是其它无服务框架:Azure Function、AWS Lambda等。

const fetch = require('node-fetch');

async function getTicker(a, b) {
  try {
    const response = await fetch('https://api.poloniex.com/markets/price');
    const data = await response.json();

    // 创建一个哈希表来存储代币对及其价格
    const pairMap = new Map();

    // 使用直接对及其反向对填充哈希表
    for (const { symbol, price } of data) {
      const [base, quote] = symbol.split('_').map(token => token.toLowerCase());
      if (!pairMap.has(base)) pairMap.set(base, new Map());
      if (!pairMap.has(quote)) pairMap.set(quote, new Map());
      
      pairMap.get(base).set(quote, parseFloat(price));
      pairMap.get(quote).set(base, 1 / parseFloat(price)); // 添加反向边
    }

    // 将 token 转换为小写
    a = a.toLowerCase();
    b = b.toLowerCase();

    // BFS 查找从 a 到 b 的转换率
    const queue = [[a, 1]]; // 从初始代币和兑换率 1 开始
    const visited = new Set([a]);

    while (queue.length > 0) {
      const [currentToken, currentRate] = queue.shift();

      if (currentToken === b) return currentRate;

      // Check connected tokens
      for (const [nextToken, rate] of (pairMap.get(currentToken) || new Map())) {
        if (!visited.has(nextToken)) {
          visited.add(nextToken);
          queue.push([nextToken, currentRate * rate]);
        }
      }
    }

    // 如果未找到路径,则返回 null
    return null;
  } catch (error) {
    console.error("获取或处理数据时出错:", error);
    return null;
  }
}

// Example usage:
(async () => {
  const rate = await getTicker('btc', 'trx');
  console.log('BTC 到 TRX 的兑换率:', rate);
})();

代码的一些简单说明:

  • API 数据提取:从 P站 API 提取数据并将响应解析为 JSON。
  • 映射对:以每个代币作为键创建一个映射,其中值是它可以直接转换为的另一个代币映射,以及兑换率。
  • 双向映射:通过反转反向转换的价格来存储直接对和反向对。
  • 广度优先搜索:使用队列遍历从 a 到 b 的路径。对于每个代币,都会检查其邻居(可转换代币)。如果找到 b,该函数将返回累积率;如果没有,则继续,直到所有选项都用尽。
  • 处理无路径:如果未找到转换路径,则函数返回 null。

如果有多组兑换,我们可以改成传入一个数组,这样就不用多次调用P站的API了。

const fetch = require('node-fetch');

async function getToken(pairs) {
  try {
    const response = await fetch('https://api.poloniex.com/markets/price');
    const data = await response.json();

    // 创建一个哈希表来存储代币对及其价格
    const pairMap = new Map();

    // 使用直接对及其反向对填充哈希表
    for (const { symbol, price } of data) {
      const [base, quote] = symbol.split('_').map(token => token.toLowerCase());
      if (!pairMap.has(base)) pairMap.set(base, new Map());
      if (!pairMap.has(quote)) pairMap.set(quote, new Map());
      
      pairMap.get(base).set(quote, parseFloat(price));
      pairMap.get(quote).set(base, 1 / parseFloat(price)); // 添加一条反向边
    }

    // 使用 BFS 查找单个对的转换率的辅助函数
    const findConversionRate = (a, b) => {
      a = a.toLowerCase();
      b = b.toLowerCase();
      
      if (a === b) return 1; // 直接转换

      const queue = [[a, 1]];
      const visited = new Set([a]);

      while (queue.length > 0) {
        const [currentToken, currentRate] = queue.shift(); // 出队列

        if (currentToken === b) return currentRate;

        for (const [nextToken, rate] of (pairMap.get(currentToken) || new Map())) {
          if (!visited.has(nextToken)) {
            visited.add(nextToken);
            queue.push([nextToken, currentRate * rate]);
          }
        }
      }

      return null; // 路径没找到
    };

    // 迭代列表并查找转换率
    const results = pairs.map(([a, b]) => findConversionRate(a, b));
    return results;
  } catch (error) {
    console.error("Error fetching or processing data:", error);
    return pairs.map(() => null); // 如果有错误,则返回每对的 null
  }
}

// Example usage:
(async () => {
  const conversionRates = await getToken([['btc', 'trx'], ['usd', 'steem']]);
  console.log('兑换结果:', conversionRates);
})();

简单的代码说明:

  • 参数更新:getToken 现在接受成对的元组数组,其中每个元组代表一对 [a, b]。
  • 辅助函数:findConversionRate 处理每对的转换,实现与以前相同的 BFS 方法。
  • 映射每对:函数迭代数组里的每个配对币,应用 findConversionRate 计算转换率,并将结果存储在数组中。
  • 错误处理:如果出现 API 或处理错误,则返回一个空值数组,与输入数组的长度匹配。

这个修改后的函数现在可以接受一个数组,并在一次Poloniex API调用中返回数组里每个配对的兑换率。

英文:Crypto Token Exchange Rate Computation Based on Breadth First Search Algorithm on Poloniex API

区块链技术

Crypto虚拟货币交易所

交易所跑路啦

本文一共 1127 个汉字, 你数一下对不对.
基于P站(Poloniex)的广度优先搜索算法来获得任意两种币的兑换价格. (AMP 移动加速版本)

扫描二维码,分享本文到微信朋友圈
75a5a60b9cac61e5c8c71a96e17f2d9c 基于P站(Poloniex)的广度优先搜索算法来获得任意两种币的兑换价格 Javascript Poloniex P站 交易所 Crypto Exchanges 加密货币 区块链 比特币 BTC 程序设计 算法 编程 计算机 计算机 软件工程
The post 基于P站(Poloniex)的广度优先搜索算法来获得任意两种币的兑换价格 first appeared on 小赖子的英国生活和资讯.

相关文章:

  1. HPZ800服务器主板太老不支持超过2TB的大硬盘 我家里一直用的是HPZ800服务器, 很吵, 很老, 虽然这台服务器已经有十年之久(我在EBAY上买来用了五年多了), 但是即使放到今天, 这服务器速度依旧很快, 很稳定. 由于服务器用的是ECC较验内存, 所以基本上不重启关机. HPZ800主机有两个硬核CPU – 因特志强 X5650 – 每个CPU是12核....
  2. 给孩子零花钱培养孩子正确的金钱观价值观 两个娃已经不知不觉7岁8岁了. 媳妇和我商量一下决定给孩子每人每周5英镑的零花钱(Pocket Money). 这样他们慢慢的就有自己的小积蓄备将来不时之需: 比如朋友聚会生日啥的需要准备礼物. 同时, 我们决定不再给孩子买零食(薯片啥的). 孩子一天好几餐, 晚上睡觉前还得吃零食, 我们就多买了很多水果面包, 健康的食物多吃一些总不是啥坏事. 孩子可以用这些零钱买自己想要的东西, 我们也不再过问. 孩子有自己的决定权. 第一周的时候,...
  3. 测测你的幸运 – Linux Fortune-Teller LINUX 下有很好很好玩的命令,之前已经介绍过: figlet, rig, curl. 现在推荐另一个 命令 fortune 是用来随机显示一段(句)话的.fortune 在英文里就是幸运的意思. 这个命令可以不需要 参数 如果没有 可以通过 apt-get...
  4. 负电价活久见: 安装Octopus智能电表省电费甚至赚钱 前几周我的电气公司 Octopus 终于来装智能电表了(Smart Meter),虽然是免费安装的,但是排队排了有两三年了吧。因为之前一直写邮件催的时候就老是说 Not Ready。 收到邮件说可以安装智能电表我还是相当开心和期待的,因为已经听说这玩意好,但是还是得亲身体验一下。工程师来安装大概不到2小时,其中需要停电闸一会儿,重新接下线。装好后,给了个小册子,自动切换到了 Agile 的电价,也就是每半小时的电价都不一样,提前一天可以在手机App和网站上查得。 正好在原来的电价计费合同快要结束前2天换到了智能电表计价 Octopus Agile方式,但是系统还是扣了我75英镑 Exit Fee (提前合同结束得交违约费),不过我一个电话打过去,公司很爽快就给我退了。...
  5. ChatGPT-4 使用 Math Wolfram 插件解决数学脑筋急转弯问题 这篇文章, 我们看一个简单的数学问题(脑筋急转弯), 并用 Python 解决它. 我们看一下LLM(大型语言模型): ChatGPT3.5和ChatGPT4. 通过 ChatGPT-Plus 订阅(目前每月 20 美元 + VAT增值税), 我们可以启用...
  6. 微软面试题: 三角形的面积是多少? 据说是一个印度人杀入微软最后的面试, 面试官给了这么一道小学数学几何题: 这哥门也有疑问 可是最后还是坚持 答案 30 (底 X 高 / 2) 不存在 这是个陷井: 这个直角三角形是不存在的. 两个小直角三角形的勾股定理:...
  7. 给STEEM中文微信群加了个机器人 之前说到我的公众号 justyyuk 可以查询几种虚拟货币的实时价钱, 但是有点不方便, 因为很多朋友在群里聊天得切换到公众号, 这下好了, 今天往STEEM中文微信群(还有编程群)加了个机器人, 在聊天的时候想了解价钱就直接输入货币代号即可, 如: 既方便自己, 又能方便别人(省事, 价格信息会同时显示给其它成员). 注: 这机器人不是我做的, 只是我拉进来的,...
  8. Javascript 中 sleep 函数实现 Javascript 中并没有 built-in 的 sleep 函数支持, 在 async/await/Promise 的支持之前, 我们可以用 busy-waiting 的方式来模拟: 1 2 3...

后面试时代与 AI 刷题

一、引言

七月的时候,我写了一篇文章《AI 编程助手测评:GitHub Copilot vs 豆包 MarsCode》,推荐了后者。

豆包 MarsCode 团队最近就邀请我,试用他们的新功能"代码练习",它专门用来准备面试和刷题。

试用以后,我有很多想法。

我觉得,AI 会改变程序员的面试,以后是 AI 刷题的后面试时代

二、面试的 LeetCode 刷题

现在的程序员面试,一般都有算法解题。

为了准备面试,大家都会去刷算法题,最常见的就是使用 LeetCode 题库。

LeetCode 是世界最流行的算法题库。它源自美国,专门收集各种面试算法题,目前已经超过了3000道,不少是互联网大厂的真题。

很多同学坚持不懈,每天投入几个小时,做里面的题目,训练自己的算法能力。一般来说,至少要刷200题,面试才较有把握。

(图片说明:上图是某个老外的刷题统计面板,他一年365天,每天都在刷题,一共刷了1500题。)

三、AI 颠覆 LeetCode

生成式 AI 出现后,越来越多的人发现,有了 AI,人肉刷题似乎不那么必要了。

今年(2024)8月份,一位美国网友在 Reddit 论坛发了这样一个帖子。

他说,自己写了一个脚本,让 AI 自动求解 LeetCode 算法题,一天之内做了633道题目,正确率达到了86%,成本只要9美元。

这个帖子引起了巨大反响。

既然 AI 可以提示正确答案,为什么不参考 AI 来准备面试呢? 何必坚持苦思冥想、徒手 LeetCode 刷题。

四、AI 助手的解题能力

我们完全可以跟着 AI 刷题,做到事半功倍。

我选一道 LeetCode 题目,展示一下这是多么简单的事情。


你是一个 JavaScript 程序员,请补充完成下面的函数。

要求是输入一个代表罗马数字的字符串(比如"IX"),该函数会返回对应的阿拉伯数字(比如9)。

 /**
  * @param {string} s 
  * @return {number} 
  */ 

var romanToInt = function(s) {


};

选择上面这道题,主要是因为它很短,便于展示。而且,这道题的难度不大,但需要考虑多种情况,很适合用在初级面试。

我选择的 AI 工具,就是 VS Code 编辑器的豆包 MarsCode 插件,它是免费的。

在 VS Code 代码编辑器里,从左边栏打开该插件(如果未安装,可以在插件市场搜索"MarsCode")。然后,在对话框输入题目。

稍等片刻,AI 就会给出答案以及代码解释。

哪个地方看不懂,就向 AI 询问。

这节省多少时间啊,大大加快了刷题速度。

五、后面试时代

可以看到,AI 能够快速解决面试算法问题,那么,基于算法解题的面试模式,是不是应该有所改变了?

现在的互联网大厂,都允许工作中使用 AI 模型,面试再要求"徒手解题",已经有点过时了。

AI 将越来越普及,如果未来的面试不使用 AI,就好像不使用 IDE 编辑器一样不合理,应该允许程序员在面试中使用日常工具。

我的想法是,面试的考察重点可能会改变,从让面试者解题,变成让面试者解释和审查 AI 生成的代码。

面试时,给你一段 AI 生成的解题代码,让你解释这段代码,并且修正里面的错误和没有考虑到的地方。

这样做有很多好处:(1)更贴近程序员的实际工作模式;(2)能看出程序员的代码阅读和理解能力;(3)难以事前准备或作弊;(4)更能反映一个人的协作能力;(5)也适用于偏向阅读代码而不是编写代码的岗位,比如项目经理、架构师等等。

这可以称为"基于 AI 的后面试时代",即面试从考察编码解题能力,演变到考察代码的审查理解能力。

六、AI 陪练功能

现在已经有很多工具,为面试提供 AI 辅助训练。

豆包 MarsCode 的"代码练习"就是一个最新的尝试。我用了以后,觉得对准备面试、有效刷题真的有帮助,可以训练自己与 AI 协同编程。

它是一个基于云 IDE 的专门页面,内置了上百道字节跳动的面试真题

所有相关操作都集中在这个页面上,只要有浏览器就可以使用,刷题全过程不必切换页面,大大方便了使用:选题、解题、调试、AI 对话......

而且,它是免费的,大家现在就可以试试看:进入豆包 MarsCode 官网,点击顶部菜单的"代码练习",就可以进入。

这个页面是云 IDE,不需要任何安装,打开后直接在浏览器使用。

默认状态下,页面分成四栏。左侧是面试真题的目录,目前有100道,以后还会不断增加。选中一道题目,点击后可以看到具体内容。

页面右侧是代码框和 AI 框。

在代码框,需要首先选择你的编程语言,共有8种可选(Python、JavaScript、Go、C++、C、Java、Rust、TypeScript),上图是 JavaScript。然后,输入解题代码,再点击顶部的运行按钮,就可以看到运行结果。

在 AI 框,则是三个预设选项,点击后就可以让 AI 提示思路、代码、检查代码。下方还有对话框,用来跟 AI 对话。

一般来说,拿到题目后,(1)先点击"需要一点思路提示",让 AI 帮助你理解题目。(2)再点击"给我一些代码提示吧",让 AI 给出初步代码。(3)你修改和完善代码,再点击"帮我检查一下代码",看看会不会报错。

此外,这个页面还集成了 IDE 功能,比如语法检查和代码调试。随着代码键入,会自动给出用法提示(下图)。

这样的"代码练习",堪称面试刷题的利器,我觉得,面试指导书籍和辅导班可能都不需要了,以后都会被淘汰。

七、总结

AI 改变软件行业,也必然改变程序员的面试求职。

AI 刷题是未来的趋势,善用者将更容易通过面试,拿到心仪的 offer。

但是,需要提醒的是,AI 只是工具,生成的代码不一定正确和安全,而且项目之中也不应该有黑箱。

正确的做法是,使用 AI 但不依赖,思路比答案更重要,只有理解了每一行代码,才能接受它的结果。我们使用 AI 的首要目的,永远是提升自己的能力,而不是让 AI 替代我们,代码的最后责任人的不是 AI,而是你。

(完)

文档信息

  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证
  • 发表日期: 2024年10月10日

买不到就自己做!「困ります」ボタンDIY记录

最近刷小红书的时候老是看到这个。正好雪先生@yuki 去日本现充,就拜托他去DAISO看看有没有机会碰到。然而雪先生去的DAISO都没有… 然后一天晚上(11点半)雪先生给我发这个照片: 给你图 你看看来做个适配手机的 非常环保减塑 那既然都这么说了,为了地球母亲!开干! 技术选型很简单。既然要节能减排,那么就将它贯彻到底,在保障开发体验的前提下怎么小怎么来。自然动辄几百K包体的React是不必考虑了,

来源

使用 PNPM 的情况下,Jest 解决 ESM 依赖库的报错问题

环境

  • NX
  • PNPM
  • lodash-es
  • Jest

从 karma 转移到 Jest 遇到了如下报错

主要原因是 “node_modules” 文件夹中 ESM(ECMAScript Modules) 库不被 Jest 支持。

鉴于 Jest ESM 支持还在几乎不可用的试验阶段,而目前我主要是在公司项目上迁移到 Jest。所以本文主要采用 transformIgnorePatternsmoduleNameMapper 两种配置来解决这个问题。

11c629a593c4c8484b6cb8ca44d6aa5f.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Test suite failed to runJest encountered an unexpected tokenJest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.By default "node_modules" folder is ignored by transformers.Here's what you can do:    • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.    • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript    • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.    • If you need a custom transformation specify a "transform" option in your config.    • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.You'll find more details and examples of these config options in the docs:https://jestjs.io/docs/configurationFor information about custom transformations, see:https://jestjs.io/docs/code-transformation

以下配置主要以 lodash-es 作为参考。

transformIgnorePatterns

官方文档的解释是:正则表达式模式字符串的数组,在转换之前与所有源文件路径匹配。如果文件路径与任何模式匹配,则不会对其进行转换。
transformIgnorePatterns 用于指定在进行代码转换时应该忽略的文件或文件夹。

而在 NX 默认的 Jest 配置中,配置为 node_modules/(?!.*\\.mjs$)
这个正则表达式的含义是,匹配以 node_modules/ 开头的文件夹路径,但排除那些以 .mjs 为扩展名的文件夹路径。?! 是一个否定预查,表示不匹配这样的文件夹路径。

1
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],

以上配置意思就是将会把以 .mjs 为扩展名的文件从 ESM 转换为 CommonJS,以支持 Jest。

添加转换 lodash-es

顺便支持一下 PNPM

1
2
3
4
5
6
7
const esModules = ['.*\\.mjs$', 'lodash-es'].join('|');export default {    ...    transformIgnorePatterns: [`node_modules/(?!.pnpm|${esModules})`],    ...}

转换后 failed 数量从 15 减少到 11,但是这么做会有一个转换的过程会有额外的支出,需要 51s。不过第一次转换完后貌似就会缓存然后就不用转换了。

ef4e6aeef369b021b707664f9c03549a.png

支出更少的方法 moduleNameMapper

这种方法需要库本身有对应的 CommonJS,就不需要转换了。可以跑到 12s

1
2
3
4
5
6
7
export default {    ...    moduleNameMapper: {        '^lodash-es$': 'lodash',    },  ...}

e87d8ad99b64c8f836a8c1777ec217bf.png

最终配置参考如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* eslint-disable */const esModules = ['.*\\.mjs$'].join('|');export default {  displayName: 'pc',  preset: '../../jest.preset.js',  setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],  coverageDirectory: '../../coverage/apps/pc',  moduleNameMapper: {    '^lodash-es$': 'lodash',  },  transform: {    '^.+\\.(ts|mjs|js|html)$': [      'jest-preset-angular',      {        tsconfig: '<rootDir>/tsconfig.spec.json',        stringifyContentPathRegex: '\\.(html|svg)$',      },    ],  },  transformIgnorePatterns: [`node_modules/(?!.pnpm|${esModules})`],  snapshotSerializers: [    'jest-preset-angular/build/serializers/no-ng-attributes',    'jest-preset-angular/build/serializers/ng-snapshot',    'jest-preset-angular/build/serializers/html-comment',  ],};

参考

  1. Jest setup "SyntaxError: Unexpected token export"
  2. Configuring Jest · Jest
  3. ECMAScript Modules · Jest
  4. Configuring Jest · Jest

【前端十万个为什么】V0

为什么用 Composition API

c2f54277b2fb37d52596daa96202d926.png

  1. 使逻辑分离更容易:使用可组合函数可以将组件的逻辑分解为多个较小的部分,不再限制于 Options API 中组织代码,更容易重用有状态逻辑。
  2. 灵活性和代码重用性:可以提取和重用共享逻辑,分离关注点,使代码更加模块化和易于维护。
  3. 实现组件的复用和组合:将逻辑拆分为可重用的部分,使用可组合函数组合组件,避免重复编写代码,提高代码的重用性,减少重复和不一致性的风险。
  4. 更好的可读性和可理解性:每个可组合函数封装了特定方面的行为、方便推理和测试、有助于团队合作,使代码结构化和有组织。
  5. 更好的类型推断:使用变量和标准 JavaScript 函数处理组件逻辑。更容易在使用静态类型系统(如 TypeScript)构建大型 Vue 应用程序时进行类型推断

为什么解构 Proxy 会失去效应性

等待补坑

为什么 Vue 中解构 props 会失去响应性

在 Vue 3 中,当你解构 props 时,可能会丧失响应性。这意味着对 props 的更改不会触发组件的更新。

原因是 Vue 的响应性系统依赖 Proxy 来跟踪对象属性的更改。当组件接收到一个对象作为 props 时,Vue 会为该对象的每个属性设置响应性的 getter 和 setter。这使得 Vue 能够检测属性何时更改并相应地更新组件。

当你解构对象 props 时,实际上是创建了一个不再具有响应性的新对象。Vue 为原始对象创建的响应性 getter 和 setter 不会转移到新对象上。

参考

  1. Vue3 如果解构 props 会失去起响应性导致 setup 里一堆 pros.xxx 怎么办? - 这似谁的小鹿的回答 - 知乎
  2. Vue Tip: Destructure Props in Composition API Without Losing …
  3. How To Destructure Props In Vue 3 Without Losing Reactivity | by Nicky Christensen | Medium

为什么 Vue 项目很少用 RxJS

一句话解释

这是因为 Vue 希望成为一个轻量且灵活的框架,允许开发者选择他们喜欢的工具和库。虽然 RxJS 是一个强大的响应式编程库,但 Vue 采用了不同的方法,提供了自己的响应式系统。

详情点

  • 设计理念不同:Vue 注重简单和直观,便于响应式编程;而 RxJS 功能更强、更复杂,适合异步和事件驱动编程。
  • 库的大小与复杂性:RxJS 库大且学习曲线陡,若作为 Vue 的默认依赖,会增加框架大小和开发复杂性,与 Vue 的轻量和灵活理念不符。
  • 灵活性:Vue 设计为灵活且适应不同的项目需求。不将自己绑定到特定的响应式库(如 RxJS),允许开发人员选择最适合他们需求的工具和库。这种灵活性使开发人员能够无缝地将 RxJS 或其他任何库集成到 Vue 项目中。
  • 学习曲线:Vue 拥有平缓的学习曲线,特别是对于初级开发。通过提供自己的响应式系统,Vue 可以提供更简单、更渐进的学习体验。

参考

  1. Introduction to VueJS and RxJS - This Dot Labs
  2. Integrating RxJS with Vue.js | DigitalOcean
  3. Reactive Programming: The Good and the Bad | goodguydaniel.com
  4. A better practice to implement HTTP client in Vue with RxJS for enterprise Apps | by Pawel Woltschkow | Medium
  5. You might not want Rxjs

JavaScript 总结、比较 V2

Promise 与 RxJS Observables 的区别

Promise

  • Promise 是 JavaScript 中内置的,不需要任何额外的库。
  • Promise 表示可能现在或将来可用的单个值。
  • Promise 是急切的,也就是说一旦 Promise 被解析,.then()回调会立即执行。
  • Promise 只能发出单个值。
  • Promise 非常适合处理产生单个结果的简单异步操作。

RxJS Observables

  • Observables 是 RxJS 库的一部分,需要额外安装依赖。
  • Observable 表示可以随时间发出的值流。
  • Observable 是惰性的,也就是说在订阅之前不会执行任何操作。
  • Observable 可以发出多个值,包括零个或多个值。
  • 可以使用各种 RxJS 操作符对 Observable 进行转换和组合,以创建新的定制流。
  • Observable 非常适合处理复杂的异步操作,例如实时数据流或事件驱动编程。

参考

  1. JavaScript Theory: Promise vs Observable - Medium
  2. angular - What is the difference between Promises and Observables? - Stack Overflow
  3. JavaScript Promises vs. RxJS Observables

模版语法的简单实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const name = 'Nexmoe';const message = 'My name is {{name}} and I\'m {{getAge(20)}} years old.';function getAge(age) {  return age;}const replacedMessage = message.replace(/\{\{(.*?)\}\}/g, (match, variableOrFunction) => {  const trimmedValue = variableOrFunction.trim();  if (trimmedValue.includes('(')) {  // 如果占位符包含括号,则表示为带参数的函数替换    const [functionName, ...args] = trimmedValue.split(/\(|\)/).filter(Boolean);    const func = eval(functionName);    return func(...args);  } else {  // 否则为变量替换    return eval(trimmedValue);  }});onsole.log(replacedMessage);

先检查占位符中是否包含括号,如果包含括号,则表示是一个带参数的函数调用。使用split方法和正则表达式来解析函数名和参数,并将其存储在functionNameargs变量中。然后,使用eval函数将函数名转换为实际的函数对象,并使用扩展运算符 (...) 将参数作为参数列表传递给函数。函数执行后,将返回值作为替换后的字符串返回。

如果占位符不包含括号,则表示是一个变量。直接使用eval函数将变量名转换为实际的变量值,并返回其值作为替换后的字符串。

⚠️ 注意:使用eval函数执行代码具有一定的安全风险,因为它可以执行任意的 JavaScript 代码。有相当多的建议建议不使用eval。准备过段时间研究研究不用eval的方法。

MVVM 是什么

MVVM 代表 Model-View-ViewModel,在 MVVM 中,Model 表示应用程序的数据和业务逻辑,View 表示用户界面,ViewModel 充当 Model 和 View 之间的中介。

模型(Model)

  • 模型代表应用程序中的数据和业务逻辑。
  • 它可以是从服务器获取的数据、本地存储的数据或通过其他方式获取的数据。
  • 模型通常实现了一些方法来操作、存储和管理数据。
  • 对应的是组件中的 data、props 属性。

视图(View)

  • 视图是用户界面的可见部分。
  • 它负责展示数据给用户,并接收用户的交互操作。
  • 在 Vue.js 中,视图通常由 Vue 组件表示,可以包含 HTML 模板和样式。

视图模型(ViewModel)

  • 视图模型是连接模型和视图的中间层。
  • 视图模型通常包含了与视图相关的数据、计算属性和方法,以及与模型交互的逻辑。
  • 通过双向绑定(data-binding)将视图和模型连接起来。当模型中的数据发生变化时,视图会自动更新。通过 DOM 事件监听,当用户在视图中输入数据或进行其他交互操作时,视图模型会自动更新模型中的数据。

优势

  • 分离关注点:将数据逻辑与视图逻辑分离,使代码更易于维护和测试。
  • 提高开发效率:通过双向数据绑定和声明式编程风格,减少了手动操作 DOM 的代码量。
  • 可重用性:通过组件化的方式,视图和视图模型可以在不同的应用程序中进行复用。
  • 响应式更新:当模型中的数据发生变化时,视图自动更新,提供了更好的用户体验。

参考

  1. 为什么尤雨溪尤大说 VUE 没有完全遵循 MVVM? - 知乎
  2. Vue 的 MVVM 思想(包含三个常见面试题) - 掘金
  3. MVC,MVP 和 MVVM 的图示 - 阮一峰的网络日志
  4. Getting Started - vue.js
  5. Comparing Vue.js to new JavaScript frameworks - LogRocket Blog

MVC 是什么

MVC 这个概念已经存在很久了,用了这么多年,今天了解一下概念做个总结。

MVC(Model-View-Controller)设计模式将应用程序中的对象分为三个角色:模型(Model)、视图(View)和控制器(Controller)。该模式不仅定义了对象在应用程序中的角色,还定义了对象之间的通信方式。每种类型的对象都通过抽象边界与其他类型的对象分离,并在这些边界上与其他类型的对象进行通信。应用程序中某种 MVC 类型的对象的集合有时被称为层,例如模型层。

848723f97c7a1b862e10abe0445da348.png

模型(Model)

  • 封装应用程序特定的数据,并定义操作和处理数据的逻辑。
  • 可以表示应用程序中的实体,如游戏中的角色或地址簿中的联系人。
  • 可以与其他模型对象建立关联,形成对象图。
  • 应该存储应用程序的持久状态数据。
  • 不应与呈现数据和用户界面相关的视图对象直接连接。

视图(View)

  • 用户可见的对象,负责显示数据和响应用户操作。
  • 知道如何绘制自身,并可以与用户进行交互。
  • 通常通过控制器对象从模型对象中获取数据进行展示和编辑。
  • 在 MVC 应用程序中与模型对象解耦,提供一致性和重用性。

控制器(Controller)

  • 充当视图对象和模型对象之间的中介。
  • 负责处理用户操作,并将其传递给模型层进行数据处理和更新。
  • 可以执行应用程序的设置和协调任务,管理其他对象的生命周期。
  • 在模型对象发生变化时,将新的模型数据传递给视图对象进行显示。

优势

  • 提供良好的应用程序设计,使对象更具可重用性和接口定义明确性。
  • 支持应用程序的可扩展性,易于添加新功能和模块。
  • 分离关注点,使代码更易于维护和测试。
  • 应用程序的模型层、视图层和控制层之间保持了清晰的分离,实现了代码的结构化和职责的明确划分,从而提高了应用程序的可维护性和可扩展性。

参考

  1. https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html

为什么 Bun 这么快

JavaScriptCore 引擎

Bun 使用 JavaScriptCore 引擎,这是 Safari 浏览器使用的引擎,而不是基于 Chromium 的浏览器和 Node.js 使用的 V8 引擎。JavaScriptCore 引擎经过了针对更快启动时间的优化,这有助于 Bun 的速度。

性能分析和优化

大量的性能优化。Bun 的初衷就是要快。[2]

Zig 语言

Bun 利用 Zig 语言进行低级内存控制和消除隐藏控制流。Zig 的设计原则注重性能,通过利用 Zig,Bun 可以实现更好的内存管理和控制,从而提高速度 [2]

参考

  1. Bun 1.0 | Bun Blog
  2. A first look at Bun: is it really 3x faster than Node.js and Deno? - DEV Community

动画 PNG(APNG) 转 GIF 并无限循环

今天在网上找了些 PNG 格式的动态表情包我是不会告诉你是我是在 LINE 偷的表情包的,于是了解到是 APNG 这种格式。由于微信和 QQ 不支持 APNG,所以就把 APNG 转为 GIF 了,在使用 APNG 转换成 GIF 后,发现在微信上只能播放一次,就产生了如何批量修改 GIF 的循环次数的问题。

所以准备简单介绍一下 APNG。并提供了一个在线工具,可以将 APNG 批量转换为 GIF,但是该工具不能实现无限循环。所以分享了一个批量修改 GIF 循环次数的方法,使用了 Node.js 和批处理脚本两种不同的实现方式。方便 Node 开发者和使用 Windows 的普通用户直接批量处理。

APNG 是什么?

APNG(Animated Portable Network Graphics)是 PNG 的位图动画扩展,可以实现 PNG 格式的动态图片效果。APNG 相比于 GIF 在图片质量和细节表现方面更有优势,而且随着越来越多的浏览器对 APNG 的支持,它有望成为下一代动态图的标准之一。主要有以下区别:

  1. 图片质量:GIF 最多支持 256 种颜色,并且不支持 Alpha 透明通道,这导致 GIF 在色彩丰富的图片和含有半透明效果的图片上质量较差。而 APNG 可以支持更高质量的图片,包括更多的颜色和 Alpha 透明通道,使得动画效果更加细腻。

  2. 构成原理:APNG 和 GIF 都是由多帧构成的动画,但是 APNG 的构成原理允许超自然向下兼容。APNG 的第一帧是标准的 PNG 图片,即使浏览器不认识 APNG 后面的动画数据,也可以无障碍显示第一帧。而如果浏览器支持 APNG,就可以播放后面的帧,实现动画效果。

  3. 浏览器支持:从 Chrome 59 开始,Chrome 浏览器开始支持 APNG,使得大部分浏览器都能显示 APNG 动画。唯独 IE 浏览器不支持 APNG。

更多内容请参考:https://xtaolink.cn/268.html

APNG 批量转 GIF

该工具可以批量将 APNG 转为 GIF,不过不能无限循环。

https://cdkm.com/cn/png-to-gif

批量修改 GIF 为无限循环

bat(普通用户请使用该方法)

下面是使用批处理脚本(.bat)来实现相同的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@echo offsetlocal enabledelayedexpansionset "directoryPath=C:\path\to\directory"for /r "%directoryPath%" %%f in (*.gif) do (    echo Modifying %%~nxf    call :modifyGif "%%f")exit /b:modifyGifset "filePath=%~1"set /p data=<"%filePath%"set "index=!data:~0,16!"set "modifiedData=!data:~0,16!!data:~16,1!!data:~17,1!!data:~19!"echo.!modifiedData!>"%filePath%"exit /b

请将C:\path\to\directory替换为实际的目录路径。将上述代码保存为.bat文件,双击运行即可。脚本将遍历指定目录下的所有.gif文件,并对其进行修改。

请注意,批处理脚本的功能相对有限,无法直接读取二进制文件。上述脚本通过读取文件的第一行来模拟读取文件内容。在修改文件时,它直接将修改后的数据写入文件,而不进行二进制操作。这种方法可能不适用于所有情况,尤其是处理大型文件时可能会有性能问题。如果需要更复杂的二进制文件处理,请考虑使用其他编程语言或工具来实现。

Node(Nexmoe 使用的该方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
const fs = require('fs');const path = require('path');function unlimitedGifRepetitions(path) {  const data = fs.readFileSync(path);  const index = data.indexOf(Buffer.from([0x21, 0xFF, 0x0B]));  if (index < 0) {    throw new Error(`Cannot find Gif Application Extension in ${path}`);  }  data[index + 16] = 255;  data[index + 17] = 255;  return data;}function batchModifyGifFilesInDirectory(directoryPath) {  fs.readdir(directoryPath, (err, files) => {    if (err) {      console.error('Error reading directory:', err);      return;    }    files.forEach(file => {      const filePath = path.join(directoryPath, file);      const fileExtension = path.extname(file);      if (fileExtension === '.gif') {        try {          const modifiedData = unlimitedGifRepetitions(filePath);          fs.writeFileSync(filePath, modifiedData);          console.log(`Modified ${file}`);        } catch (error) {          console.error(`Error modifying ${file}:`, error);        }      }    });  });}const directoryPath = './path/to/directory';batchModifyGifFilesInDirectory(directoryPath);

请注意,上述代码使用了 Node.js 的文件系统模块(fs)来读取和写入文件。此外,需要将./path/to/directory替换为实际的目录路径。在执行该脚本之前,请确保已经安装了 Node.js。

该脚本将批量遍历指定目录下的所有文件,并对后缀名为.gif的文件调用unlimitedGifRepetitions函数进行修改。修改后的数据将写回原始文件。在控制台输出中,你可以看到每个已修改的文件的信息或任何出现的错误信息。

更多内容参考:https://www.b612.me/golang/232.html

更好的工具

这个批处理工具可以将多个 APNG 文件批量转换为 GIF 文件,并且可以对转换后的 GIF 文件批量设置为无限循环。

https://github.com/nexmoe/batch-apng2gif

累积布局偏移优化 CLS 完全指南

什么是布局偏移

一个十几秒的短视频解释清楚。

更详细的解释是:布局偏移指的是在网页上发生突然变化时,页面中的内容位置发生意外移动的现象。这种情况常常让人感到困扰,因为它会导致阅读中断或误操作。布局偏移通常是由于资源异步加载或动态添加到页面上的 DOM 元素导致的。可能的原因包括具有未知尺寸的图像或视频、字体与其备用字体渲染大小不同,或者第三方广告或小部件动态调整大小。

难受的是,网站在开发过程中的功能通常与用户体验有很大不同。个性化或第三方内容在开发中的行为通常与生产环境中不同,测试图像通常已经存在于开发者的浏览器缓存中,本地运行的 API 调用通常非常快,延迟几乎不可察觉。

什么是 CLS

累积布局偏移 CLS(Cumulative Layout Shift)是一个指标。

是对页面整个生命周期中发生的每个意外布局变化的最大布局变化分数的度量。

CLS 通过测量实际用户遇到布局偏移的频率来帮助解决布局偏移问题。它可以帮助开发者了解布局偏移在真实用户中发生的情况,从而采取相应的措施进行修复。

为什么要优化 CLS

布局偏移是一个非常影响用户体验的问题,通过上面那一个简短的视频也能理解。

布局偏移通常会导致意外点击、页面方向的迷失,最终导致用户受挫。用户往往不会逗留太久。有时也会使用户不按照预计的产品流程走。

通常优化好布局偏移能够很好的提高用户粘性、用户停留时间等指标。

Yahoo! JAPAN News 通过降低 CLS 0.2 分,得到如下成果。

如何降低 CLS

图片等媒体元素占位

在图像、视频等媒体资源元素中始终包含宽度和高度大小属性。或用 CSS 中的 min-heightaspect-ratio 或类似的方式保留所需的空间。

aspect-ratio

可以用来直接指定当前元素的比例。

https://developer.mozilla.org/zh-CN/docs/Web/CSS/aspect-ratio

对浏览器的支持:

padding-bottom

如果考虑浏览器支持问题仍然可以考虑使用目前一个被广泛接受的基解决方案 “Padding-Top Hack”。这个解决方案需要一个父元素和一个绝对型的子元素。然后计算出长宽比的百分比来设置为 padding-top。例如:

1
2
3
<div class="container">  <img class="media" src="..." alt="..."></div>
1
2
3
4
5
6
7
8
9
10
.container {  position: relative;  width: 100%;  padding-top: 56.25%; /* 16:9 Aspect Ratio */}.media {  position: absolute;  top: 0;}

使用不易产生偏移的 CSS

其中 transfrom 表现很好,以下举几个例子。
用例可以在这里找到:https://play.tailwindcss.com/26PxFA6UVI

zoom VS transform: scale

zoom 会撑大页面并向右偏移时,transform: scale 只是在原地放大。

margin VS transform: translate

margin 造成父元素变大,transform: translate 只是让当前元素移动。

border VS box-shadow

border 会撑起父元素,而 box-shadow 并不会。

小心你的懒加载

懒加载会引起布局的偏移,如果你在有懒加载长列表的里进行跳转,请小心!
无动画进行跳转,能够一定程度上避免该问题。

小心使用 transition: all

在页面首次加载或者跳转页面时,transition: all 可能会导致元素的 padding 等从参数为 0 开始渲染,照成页面的抖动。

这都是痛:
Commit:表格以及友情链接图标抖动
Commit:修复导航栏抖动问题

标签顺序导致的偏移问题

由于在移动端上优先展示主要内容,因此侧边栏的 markup 位于主要内容的后面;而在更大的屏幕上,则通过设置 CSS order 的方式进行排序,将主要内容移到中间(即第二列),伪代码如下:

1
2
3
4
5
6
7
8
9
export default function MainLayout(props) {  return (    <Container>      <Main className={css`@media screen and (min-width: breakpoint) { order: 0 }`} />      <Left className={css`@media screen and (min-width: breakpoint) { order: -1 }`} />      <Right className={css`@media screen and (min-width: breakpoint) { order: 1 }`} />    </Container>  )}

浏览器在首次绘制时并没有完整解析 DOM、只知道 <Main /> 的存在、但不知道 <Left /> 或者 <Right /> 的存在,才因此将 <Main /> 渲染进第一列而不是第二列;直到第二次绘制时,浏览器才将 <Main /> 渲染进第二列、将 <Left /> 渲染进第一列。

Chrome 并不是一次完整解析 HTML 的,在以下两种情况下,Chrome 会暂停解析、开始渲染和绘制:

  1. Chrome 解析器在读取了 65535 字节的 HTML 后暂停
  2. Chrome 在遇到 <script> 标签后,会继续读取约 50 个「Token」之后暂停

详细了解请看:优化博客的累计布局偏移(CLS)问题

网页跳转与前进后退缓存

默认情况下,所有浏览器都使用 bfcache,但由于各种原因,有些站点不适合使用 bfcache。有关如何测试和识别阻止 bfcache 使用的任何问题的更多详细信息,请阅读 bfcache 文章

在你离开后,bfcache 将页面保存在浏览器内存中很短的一段时间,所以如果你返回它们,那么它们将完全恢复为你离开时的样子。这意味着完全加载的页面立即可用,而不会出现任何变化。

现在的 SPA 应用也能很轻易的保证路由跳转页面布局的一致性。记住始终保持你的目录和导航栏在页面的固定位置。

字体

在下载和渲染网络字体之前,通常有两种处理方式:

  1. 使用网络字体替代备用字体(FOUT——未样式化文本的闪烁)。
  2. 使用备用字体显示“不可见”文本,直到网络字体可用并且文本可见(FOIT——不可见文本的闪烁)。

着两种方式都可能导致布局变化。即使文本是不可见的,它仍然使用备用字体进行布局。这意味着使用该字体的文本块以及周围的内容在网络字体加载时会发生布局变化,与 FOUT 的可见字体完全相同。

以下方法可以帮助你最小化这种问题:

  1. 使用 font-display: optional 可以避免重新布局,因为只有在初始布局时网络字体可用时才会使用它。
  2. 使用匹配度高的备用字体。例如,使用 font-family: "Google Sans", sans-serif; 将确保在加载"Google Sans"字体时使用浏览器的无衬线备用字体。如果只使用 font-family: "Google Sans" 而不指定备用字体,将使用默认字体,而在 Chrome 上默认字体是"Times",它是比默认无衬线字体的匹配度更差。
  3. 使用新的 size-adjustascent-overridedescent-overrideline-gap-override API 来尽量减小备用字体和网络字体之间的大小差异,详细信息请参阅“Improved font fallbacks”文章。
  4. 使用 Font Loading API 可以减少获取所需字体的时间。
  5. 使用 <link rel=preload> 尽早加载关键的网络字体。预加载的字体有更高的机会达到首次绘制,这样就不会发生布局变化。
  6. 阅读有关字体最佳实践的“Best practices for fonts”文章。

使用真正的骨架屏

骨架屏好坏示例

测量 CLS 分数

生产阶段

实验阶段

Lighthouse in DevTools

能够针对移动设备和桌面设备生成网页的实际性能报告,并能够提供关于如何改进相应网页的建议。

在本地开发期间从 DevTools 运行 Lighthouse 非常方便。

PageSpeed Insights

应该就是在线版的 Lighthouse。

Performance in DevTools

性能选项卡在 Chrome 的 DevTools 配置文件的所有页面行为在一段时间内记录。时间轴上会出现一个标记为“Experience”的图层,突出显示布局的变化和发生变化的元素。

Web Vitals extension

最好将 Web vital 扩展视为查找性能问题的抽查工具,而不是全面的调试工具——这是 Chrome 的 DevTools 中的性能选项卡的工作。

结语

作为一个对自己项目有较高要求的人,平常几乎都会接触到布局偏移优化或者 Lighthouse,只不过之前自己瞎折腾的时候还没有 CLS 这个概念,现在算是对 CLS 有了较为清晰的概念了。
CLS 作为一个非常基础的优化指标,在用户体验上非常重要,任何项目都应该针对 CLS 做优化。

如有勘误,请及时指出,感谢!

参考

  1. https://web.dev/cls/
  2. https://web.dev/optimize-cls
  3. https://developers.google.com/publisher-tag/guides/minimize-layout-shift
  4. https://web.dev/yahoo-japan-news/
  5. https://addyosmani.com/blog/infinite-scroll-without-layout-shifts/
  6. https://blog.skk.moe/post/fix-blog-cls/
  7. https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio

记peerDependency引发的多副本问题

你现在有一个包含许多软件包的单体仓库。你的公用组件包引入了一个第三方组件包(假设是antd),你的两个客户端包和也引入了antd,当然也引入了公用组件包。你在中使用了第三方组件包中的一个Context的Provider(假设你在做一个多端的React应用),你把代码在包下的这个Context的Consumer嵌套在这个Provider的下边。正常来讲,这个Consumer应当能够读到Provider提供的Context值。bug出现了,这个Provider并没能读到Context的值,就好像它的父级根本没有Provider一样。然而同样的代码在中就跑的通,这是为什么呢? 今天这篇文章将会讲述一件由pnpm的依赖解析机制引发的问题。pnpm解决了安装npm包的许多痛点,然而其一些安装策略有可能会导致一些奇怪的行为,并且一时间很难发现。如果你还不知道pnpm是啥,

来源

两年以后,与React道别

Photo by Alex Kubsch on Unsplash 雪猫社从来都少不了折腾。 先是雪先生要求加的表情包FacePack,然后又为了精确统计浏览量连了GA桑的API。之后,因为小图片不能放大看,又加了点击放大图片(Sakurairo里面更喜欢叫灯箱)的simple-img-modal,还为了显示EXIF加了EXIF读取功能。而驱动这些的,自然是前端脚本。 最开始雪猫社的这些附加组件都使用了React作为框架,现在回头看,这并不是一个很匹配我们的使用场景的选择,最直接地体现在React框架给我们带来的重达100kb的额外脚本上。这个大小的脚本会严重地拖慢我们的脚本解析速度,带来性能影响。但其实这也是当时无奈的折中之选:与React 16.x同期的Vue 2.6.x 包大小也要90多近100KB,虽然比React可能小20/30k左右,

来源

❌