特色文章

上外网加速器

本款加速器采用自主研发极速引擎,顶级IDC集群,全线高端刀片服务器!为全球用户解决延迟、掉线、卡机等问题,让你游戏更爽快!国服加速永久免费!全球直连专线,全球游戏加速效果业界顶尖!支持油管,whatspp,line,instagram,twitter,脸书,奈菲

点击获取

[问与答] 自由职业者办理签证如何提供完税证明?

目前是自由职业者,接朋友找的开发。我看办理签证需要提供半年的资产证明,有几个疑问,请教下有相关经历的 V 友:

  1. 半年的银行流水,资金入账为工资收入和私人银行账号转账有区别吗?
  2. 资金要求是每月定时有稳定的入账,还是有一笔钱存放至少半年以上就可以?
  3. 个人如何报税?以提供近半年的完税证明(目前自己有找第三方缴纳社保和五险一金)
  4. 除了银行流水外,还需要公司开具收入证明吗?
  5. 如果找代缴公司,是需要把钱全部给这个公司,他们纳税和五险一金后,用公司账号转给我个人,实现整个流程上的“逼真”吗?这样感觉资金风险会很大

[路由器] 入手了个 J4125,i225v3,请问在哪有保姆级教程安装 ESXI 并装 openWRT 和 ikuai,还有 ubuntu 呢

买的是准系统 价格是 550.02

内存打算拆之前的笔记本的 8G 内存条

买了个 msata 128g 的,

esxi 地址找到了两个

一个是 https://sysin.org/blog/vmware-esxi-7-u3e-nuc-usb-nvme/

另一个是 https://www.right.com.cn/forum/forum.php?mod=viewthread&tid=7881507&highlight=Esxi%2B7.0&mobile=2
有几个问题

1.请问这两个都可以吗

2.看到 BILIBILI 上有个 J4125 的 ESXI 安装教程 但是网卡是 I210 的,其实可以直接安装就可以吗?

3.openWRT 想安装小宝的 istore ,感觉比较懒人,这也是可以的吗,必须要一起装 ikuai 和 openWRT 吗?光猫设置的桥接之后,我还需要额外注意哪些设置才会通网呢

[Kubernetes] 求 kubernetes 的轻量级替代品

工作中经常用到 k8s 部署微服务,感觉非常方便。

现在工作中需要批量部署并管理一些服务,比如部署 nginx ,redis 等基础的服务。但是不想用 k8s 。

有没有一种轻量级类型于 k8s 的工具。

需求:

  1. 像 k8s 一样能够方便自动部署服务。
  2. 不需要 k8s 复杂的网络,服务用宿主机的网络就行。
  3. 能够对服务进行健康检查,并且当服务挂了,自动拉起服务。
  4. 能够提供服务发现的功能,方便外部服务集成,比如被 prometheus 监控系统集成等等。
  5. 能够自动下发配置,类似于 k8s 的 configmap 。

[微信] 调用小程序 wx.downloadFile 接口,返回的回调是乱码

1.代码如图,下载链接 url 直接复制到浏览器是可以下载的

http://mmbiz.qpic.cn/mmbiz_png/x8pqcqEibv1gAImN1qksBWFib1VkQg5W7dibzekwfGbFhC86H8fcUyCBAsGqYAK55gjyzgmm2ZJrABXuq5pRqeM1Q/0?wx_fmt=png

2.但是在开发者工具上,调用 wx.downloadFile 后的回调都是乱码

http://mmbiz.qpic.cn/mmbiz_png/x8pqcqEibv1gAImN1qksBWFib1VkQg5W7d5aPYDD5RSGibo8VkvsYicHcEcpbzQfCRvIUKNnhtwdOUITpuX4Xj9PQQ/0?wx_fmt=png

3.调用真机调试,返回的又是这样一句话

http://mmbiz.qpic.cn/mmbiz_png/x8pqcqEibv1gAImN1qksBWFib1VkQg5W7dXKgvJk5Fuho36ibxtZSFpV3rUghlx7krkUHkHibXX5v0GDvwNUVsAEUA/0?wx_fmt=png

小程序后台下载域名也加了对应的网址,但回调还是这样,请问是什么原因呢?

犯蠢了,对应图片在这个链接里….
https://developers.weixin.qq.com/community/develop/doc/000882f300c6c8e0b55e829b051400

[健康] 不幸中的万幸-甲状腺癌

昨天晚上偶然间看到一篇 V 友的帖子,谈到了甲状腺癌,作为亲身经历者,谈谈这几个月的经历和感受,希望能给大家一些参考。

发现结节

去年八月公司体检,发现右侧甲状腺结节,3*2mm ,体检中心说你这还小,问题不大,做好定期复查就行,于是没太放在心上。今年三月份,咽部突然有异物感,10 多天都没有好转,心里慌了,担心是不是结节长大了?好在几天后,异物感好转,加上疫情原因,就没有去医院,最终不了了之。

只是咽炎?

时间一晃来到了今年六月初,咽部又突发异物感,这次没有犹豫了,直接去了医院,挂了甲乳科的主任号,主任很淡定的说,你这个结节肯定不会引起咽部异物感的,做个甲状腺彩超看看具体情况吧,顺便让我去耳鼻喉科看看,于是等 B 超的间隙,挂了耳鼻喉科的号找医生看了下,确诊咽炎,虚惊一场。然而半小时后的 B 超却给了我当头一棒。

彩超结果

做 B 超时心情还是很忐忑的,担心结节长大,心怦怦跳的厉害,医生让我放松。几分钟后拿到报告,右侧 2.4*3.5mm 结节,没长大多少,但是 ACR TI-RADS:5 级,结节实质钙化,顿时预感不妙。回到门诊给主任看了单子,主任又是很淡定的说:“你这个不太好啊,小伙子,我就不兜圈子了,你这个 50%-90%是癌,基本就是了,不过你这个结节不大,穿刺检验没啥意义,我建议直接切了吧!分级这么高,早晚都得切,一般愈后很好的,你考虑下吧。”,虽然还没有最终确认,但是主任的一番话还是让我脑子嗡嗡作响,对于癌症这个词,熟悉而又遥远,我还年轻,才 32 岁哎,虽然对甲状腺癌早有耳闻,也知道前几年被移除重症重疾范围,但是真落到自己头上,这一刻还是绝望的。

决定手术

和家人简单说了下病情,老婆建议遵医嘱,听医生的,手术切掉吧。于是联系医生安排床位,一周左右,医院反馈可以办住院了。
三岁的儿子看我收拾了大包小包准备出门,问我去哪儿,我说爸爸出个差,一个星期就回来了,你乖乖在家听话。儿子没说啥,仰着头眼睛直直的看着我,关上门的那一刻,我的眼泪不争气了。老婆陪我办理了入院手续就让她回家了,手术安排在第三天,前两天就是做些抽血,尿检以及 CT ,就像那位 V 友说的,我感觉我是整个病区最精神的小伙,完全不像是一个患癌患者,不过最终也证明了这确实就是纸老虎。在医院里,心态往往就淡定了,在等待手术的期间,工作也没拉下,在病床上还改了几个 BUG ,有一瞬间,真的以为自己在出差,手术前一天,医生告知了很多,大概就是这个癌,愈后很好,基本不会影响寿命,然后签了一大推单子。

手术确诊

手术安排在当天第一台,一大早护士就叮嘱我换好手术服,空腹,排好大小便。整个住院期间,最紧张就是此刻在病房等待手术室来接我,焦虑又紧张。大概 7 点半多一点,手术室护士和护工推着板床来接我了,确认完身份后,我躺在上去。去往手术室的路上,天花板和灯光在眼前飞速划过,不停变换,就像人生的一场幻灯片,而我从未看过。手术方式选择的传统开放手术,相较于腔镜,各有优势,缺点就是疤痕在颈部不美观。整个手术过程,全麻的体验是最神奇的,我记得刚和麻醉医生说完一句话,就直接断片了,等我醒来已经是 3 小时后了,医生说手术很成功,术中快速病理显示乳头状癌,右侧切除,并进行了淋巴清扫,也未发现癌细胞转移,真是不幸中的万幸。推出手术室的那一刻,我下意识的摸了摸裆部,哦,还好没插尿管。

术后恢复

术后回病房,上了监护仪,在各种点滴药物的加持下,尿意很快袭来,也不知道是麻醉的副作用还是在床上的原因,用尿壶死活尿不出来,膀胱涨的跟石头一样,老婆看我难受,用热毛巾帮我敷了下膀胱部位,在意念的加持下,终于尿了出来,那一瞬间,舒服到都忘了脖子上的伤口。由于气管插管导致喉咙咳嗽的厉害,伤口都有一种崩了的感觉。当天晚饭喝的粥,咽部疼痛导致吞咽困难,没吃下多少,躺在病床上,一夜无眠,麻醉的副作用导致脑子清醒无不,想了很多,也看开了很多。术后第二天,整个人的感觉就好很多了,除了脖子不能乱动,依旧是大瓶小瓶的点滴,引流管引出来大概 20ml 血水,医生说低于 10ml 就能出院了。第三天,可以很明显地感知自己的身体在好转,下床小便都没啥问题。到了第四天,引流管已经没多少血水了,吃饭吞咽也没啥大问题,医生安排明天出院。

出院回家

出院当天,我让老婆去隔壁家乐福超市买了个奥特曼玩具作为出差回家给儿子的礼物。打开家门的那一刻,我把玩具递给他,他开心的忽略了我脖子上的纱布,我也很开心他没看到,这一刻,身体健康才是他们最大的靠山。

最后的总结

  • 住院检查加手术总费用大约 13000 元,医保报销 9000 多,自费 3000 多,因为医保卡有余额直接支付了,没有产生额外费用。
  • 手术没有选择更美观的腔镜,原因是担心手术行程远,影响术后恢复,其实都一样,大老爷们也不在乎脖子上的疤痕,所以选择了传统的开放式手术。
  • 由于甲状腺癌是轻症了,支付宝相护宝衍生产品-健康福重疾 1 号,理赔了 2W ,这里不得不点赞阳光保险的理赔流程,周一提交的审核,周五就打款了,堪称神速。
  • 目前术后一个半月左右,身体无任何异常,头脑清醒,精力旺盛,每天两片优甲乐,短期内需要一个月去医院查一次甲功,清淡饮食,戒烟戒酒,戒咖啡,戒熬夜。唯一担心的是左侧,医生说年轻人有复发风险,不过,我不怕了。

这次运气是差了点,挨了一刀,但是通过这一遭,带来了更多的感悟和思考,我觉得又是幸运的,身体才是革命的本钱啊!

[酷工作] [远程全职] 初级产品经理/月薪 15-25K RMB

  • 投递方式点击该链接投递 投递时请选择初级产品经理
  • 关于 Brix : 点击了解 Brix
  • 薪资范围 :月薪 15-25K RMB
  • 工作形式 :远程工作模式+签署正式劳动合同+缴纳社保福利
  • 岗位介绍 :Brix Labs 内部 B 端工具类产品团队

在这个岗位,您需要做

  • 善于洞察并挖掘求职者和企业雇主在招聘环节中的各种诉求,并应用到产品功能的策划中;
  • 撰写产品需求文档,协调设计和研发的配合与支持,推动产品的开发、测试等过程;
  • 分析产品运营情况,能够根据数据变动和用户反馈为产品进行优化迭代。

需要您有

  • 本科及以上学历,1-2 年互联网产品经验,具备 B 端产品经验者优先;
  • 逻辑清晰、数据敏感,擅长把握用户心理,对于新事物有基础的拆解和判断能力;
  • 良好的沟通能力和项目管理能力,能带领各合作方共同解决问题、按时推动项目上线。

[分享发现] 给 GitHub 设置了 Two-factor authentication,添加 fallback SMS number 时发现不支持 +86 号码

虽然我近期用 Microsoft Authenticator app 给 GitHub 设置了两步验证,但是最近还是提醒我好几次说要添加更多安全方法,于是我就添加了 Security keys ,在我准备添加手机号接收验证码短信时却在 select 组件中找好久没找到 +86 的号码前缀,ohhhhh ,原来是不支持啊。

github fallback sms

github two factor authentication

为什么不支持?

以下是支持的列表

United States +1
Aland Islands +358
Algeria +213
Angola +244
Anguilla +1264
Australia +61
Austria +43
Bahamas +1
Bahrain +973
Bangladesh +880
Belarus +375
Belgium +32
Benin +229
Bolivia +591
Bosnia and Herzegovina +387
Brunei +673
Bulgaria +359
Burundi +257
Cambodia +855
Canada +1
Cape Verde +238
Cayman Islands +1345
Christmas Island +61
Cocos +61
Congo, Dem Rep +243
Croatia +385
Cyprus +357
Czech Republic +420
Denmark +45
Dominica +1767
Dominican Republic +1
Ecuador +593
Equatorial Guinea +240
Estonia +372
Finland/Aland Islands +358
France +33
Gambia +220
Georgia +995
Germany +49
Ghana +233
Gibraltar +350
Greece +30
Guatemala +502
Guyana +592
Hungary +36
Iceland +354
Indonesia +62
India +91
Ireland +353
Israel +972
Italy +39
Ivory Coast +225
Jamaica +1876
Japan +81
Jordan +962
Kazakhstan +7
Kuwait +965
Latvia +371
Libya +218
Liechtenstein +423
Lithuania +370
Luxembourg +352
Madagascar +261
Malawi +265
Malaysia +60
Maldives +960
Mali +223
Malta +356
Mauritius +230
Mexico +52
Monaco +377
Montenegro +382
Montserrat +1664
Mozambique +258
Namibia +264
Netherlands +31
Netherlands Antilles +599
New Zealand +64
Nigeria +234
Norway +47
Philippines +63
Poland +48
Portugal +351
Qatar +974
Romania +40
Rwanda +250
Senegal +221
Serbia +381
Seychelles +248
Singapore +65
Slovakia +421
Slovenia +386
South Africa +27
South Korea +82
Spain +34
Sri Lanka +94
St Lucia +1758
Sudan +249
Sweden +46
Switzerland +41
Taiwan +886
Tanzania +255
Togo +228
Trinidad and Tobago +1868
Turks and Caicos Islands +1649
Uganda +256
United Arab Emirates +971
United Kingdom +44
United States +1
Uzbekistan +998
Venezuela +58

[程序员] TypeScript 全搞定: Monorepo 的痛苦和收获


😊 这是我们团队的第一篇技术分享文章,由 原文 翻译而来。欢迎大家拍砖。

开场

我一直有一个 monorepo 的梦想。

我在 Airbnb 工作时接触到 monorepo ,但仅用于前端。 因为对 JavaScript 生态系统的热爱和「快乐」的 TypeScript 开发经验,从大约三年前开始,我尝试在前端和后端使用同一种语言。 这样对于招聘来说还不错,但对于开发来说并没有那么好,因为我们的项目仍然分散在多个仓库中。

💡 在「快乐」这个词周围有引号,因为 TypeScript 确实给我带来了很多乐趣和惊喜,但它也让我有时会想「这怎么能行不通」。

常言道,「重构项目的最佳方式是开始一个新项目」。因此,大约一年前当我开始创业时,我决定使用一个彻底的 monorepo 策略:将前端和后端项目,甚至是数据库 schema ,都放到一个仓库中。

在本文中,我不会比较 monorepo 和 polyrepo ,因为这都是哲学。我将专注于项目构建和演化历程,并假设你熟悉 JS/TS 生态。

最终结果可在 GitHub 上查看。

为什么是 TypeScript ?

坦率地说,我是 JavaScript 和 TypeScript 的粉丝。它的灵活性和严谨性可以和谐共处,这点很让人喜欢:你可以回退到 unknownany(尽管我们在我们的代码库中禁止了任何形式的 any),或者使用超严格的 lint 规则集来统一整个团队的代码风格。

在之前,当我们谈论「全栈」的概念时,我们通常会想象至少有两种编程语言和生态:一种用于前端,一种用于后端。

有一天,我突然意识到它可以更简单:Node.js 足够快(相信我,在大多数情况下代码质量比运行速度更重要),TypeScript 足够成熟(在大型前端项目中运行良好),以及 monorepo 的概念已经被一堆著名的团队( React 、Babel 等)实践了——那为什么不把从前端到后端的所有代码组合在一起呢?这可以让工程师在一个仓库中完成工作而无需切换上下文,并用(几乎)仅一种语言实现完整的功能。

选择包管理器

作为一名开发人员,和往常一样,我迫不及待地想开始写代码。 但这一次情况有所不同。

包管理器的选择对于 monorepo 中的开发体验至关重要。

🔨 太长不看版:我们选择了 lerna 和 pnpm 。

惯性带来的痛苦

那是 2021 年 7 月。自然地,我开始尝试 yarn@1.x,因为之前已经使用了很长时间。Yarn 速度不错,但很快我就遇到了 Yarn Workspaces 的几个问题。例如,未正确提升依赖项,大量 issues 被标记为「fixed in modern」,并都将用户引导至 v2 (berry)。

「 OK ,好的,我现在就去升级。」我不再纠结于 v1 ,并开始尝试迁移。但是 berry 的长篇 迁移指南 把我吓到了,在几次失败的尝试后我便放弃了。

我只是想要它能正常工作

于是关于包管理器的研究开始了。在简单试用后,我被 pnpm 完全吸引:与 yarn 一样快,原生的 monorepo 支持,类似于 npm 的命令,硬链接等。最重要的是,它可以正常工作。作为一个只想要开发产品但不想开发包管理器的程序员,我只是想添加一些依赖项并启动项目,而「不需要也不想要知道」包管理器是如何工作的或任何其他 fancy 的概念。

基于同样的想法,我们选择了一个老朋友 lerna 来执行跨包命令和发布 workspace packages 。

ℹ️ 现在 pnpm 有一个 -w 选项可以在 workspace 根目录中运行命令,同时使用 --filter 可以进行过滤。 因此,你可能可以用专注于发布的 CLI 来替换 lerna 。

定义包职责

一开始很难清楚地确定每个包的最终职责。所以根据现状来制定最佳方案即可,并始终记住可以在开发过程中进行重构。

我们的 初始结构 有四个包:

  • core:后端单体服务。
  • phrases:i18n key → 短语资源。
  • schemas:数据库和共享的 TypeScript schemas 。
  • ui:一个与 core 交互的 web SPA 。

全栈的技术栈

由于我们正在拥抱 JavaScript 生态系统并使用 TypeScript 作为我们的主要编程语言,所以很多选择都很简单(基于我的个人偏好 😊):

  • koajs 用于后端服务 (core):在 express 中使用 async/await 有一段艰难的体验,所以我决定使用有原生支持的框架。
  • i18next/react-i18next 用于 i18n (phrases/ui):喜欢它的简单 API 和良好的 TypeScript 支持。
  • react 用于 SPA (ui):只是个人喜好。

那 schemas 呢?

这里仍然缺少一些东西:数据库选型和 schema <> TypeScript 类型定义之间的映射。

「通用的」与「武断的」

我尝试了两种流行的方法:

  • 使用 ORM (并伴随许多装饰器)。
  • 使用像 Knex.js 这样的 query 生成器。

但在之前的开发过程中,两者都产生了一些奇怪的感觉:

  • 对于 ORM:我不喜欢装饰器,并且数据库的另一个抽象层会导致团队的学习成本增加和更多不确定性。
  • 对于 query 生成器:就像在编写带有一些限制的 SQL (以一种好的方式),但它不是真正的 SQL 。 因此,我们需要在许多场景中使用 .raw() 进行原始 query 。

然后我看到了这篇文章:「停止使用 Knex.js:使用 SQL 查询生成器是一种反模式」。 标题看起来很激进,但内容很棒。 它强烈地提醒我「 SQL 是一种编程语言」,我意识到可以直接编写 SQL (就像 CSS 那样,我怎么就忘记了这件事!)来利用原生语言和数据库特性,而不是添加另一层抽象来损失一些能力。

总之,我决定「武断地」使用 Postgres 和 Slonik(一个开源 Postgres 客户端),正如文章所述:

…the benefit of allowing user to choose between the different database dialects is marginal and the overhead of developing for multiple databases at once is significant.

SQL <> TypeScript

直接编写 SQL 的另一个优势是我们可以轻松地将其用作 TypeScript 类型定义的 single source of truth 。 我编写了一个 代码生成器 来将 SQL schemas 转换为在后端使用的 TypeScript 代码,结果看起来还不错:

// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. import { OidcClientMetadata } from '../foundations'; export type OidcClient = { clientId: string; metadata: OidcClientMetadata; createdAt: number;
};
// ...

如果需要,我们甚至可以将 jsonb 与 TypeScript 类型连接起来,并在后端服务中处理类型验证。

🤔 为什么不使用 TypeScript 作为 SSOT ?

这是曾想到的一个方案。 一开始听起来很吸引人,但 SQL 可以精确地描述数据库 schemas 并保持一个方向的工作流(参见下一节),而不是使用 TypeScript ,然后「转译回」 SQL

结果

最终的依赖结构如下所示:

Dependency architecture

你可能会注意到它是一个单向图,这极大地帮助我们保持了清晰的架构以及随着项目的增长而扩展的能力;同时,代码(基本上)都使用 TypeScript 编写。

开发体验

由于这部分内容比较偏技术细节,感兴趣的伙计可以移步 原文 的 Dev experience 章节查看。

结束语

我们的团队已经在这种方法下开发了一年,并对此非常满意。访问我们的 GitHub 仓库 以查看该项目的最新状态。总结一下:

不爽的地方

  • 需要熟悉 JS/TS 生态
  • 需要选择合适的包管理器
  • 需要一些额外的一次性设置

收获

  • 在一个仓库中开发和维护整个项目
  • 简化编码技能要求
  • 共享代码风格、schemas 、phrases 和 utilities
  • 提高沟通效率

    • 不再有类似的问题:API 定义是什么?
    • 所有工程师都在使用同一种编程语言进行沟通
  • 轻松的 CI/CD

    • 使用相同的工具链进行构建、测试和发布

这篇文章还有几个主题没有涉及:如何从头开始设置仓库、添加新包、利用 GitHub Actions 进行 CI/CD 等。限于篇幅在此先不展开,如果有感兴趣或未来想看到的内容欢迎留言讨论。