Deno with jupiter (opens in a new tab)
Deno core 的 jupiter,很是牛逼,在 jupiter 执行 js/ts 代码
能够做 python 环境的各种事情,比如画图表
又一个新的 (opens in a new tab)前端框架、工具链
在 backstory (opens in a new tab) 中作者提到目前的前端开发的体验并不好,nue 是为了解决 JS engineer 和 UX developer 之间的割裂,一套新的开发框架
支持 bun、node 环境;支持 SSR;基于 HTML 模版语法(类 Vue)...
Nue JS 个人感觉更像是 JS lib;Nue tools 相关生态工具链;Nuemark 语法,类似 markdown,更聚焦内容
源码 (opens in a new tab)看起来还不多,很强
chrome devtool override request (opens in a new tab)
能够直接在 devtool 中直接 mock 接口数据了!非常好用
具体哪个版本更新的不知道
CSS tricks 渐变动画边框效果 (opens in a new tab)
收藏下
react dev inspector (opens in a new tab)
挺有意思的一个 react 工具,能够在 dev 的时候通过页面点击直接打开编辑器,定位到所在组件的源码
通常我们会找这个元素对应的 class,然后在源码中搜...
实现思路:
- 构建时:通过 babel 插件,在 jsx 转译前就加上一些自定义属性(比如文件相对路径),然后通过一个包裹组件进行快捷键的监听;同时定义文件目录,最终拼接完整路径
- 寻找 fiber 节点的 name
- fetch 到 dev server:在 dev server 的处理中,增加一些自己的逻辑,来打开编辑器
- 打开编辑器:直接是参考的 CRA 的 react-dev-utils (opens in a new tab),通过 shell 直接获得当前正在运行的编辑器,然后直接 spawn 进程唤起(比如
code <path>
前端 monorepo 之殇 (opens in a new tab)
monorepo 的爽点:不走“发包”的流程来以“包”(package)的单位来复用代码
连环构建 & 依赖拓扑,build 是依赖其他子包时,通过依赖图分析(有向无环图),保证构建任务顺序正确
产物引入 & 源码引入:
- dev 过程,极慢的 HMR
- 源码引入,修改构建器的 resolve 逻辑,直接打到源码即可,也有一定问题
- 高度一致的构建环境
- 收敛自定义构建行为, 中间包想在编译时做点事情, 比如替换掉
process.env.NODE__ENV
几乎不可能了- 开发生产的不一致, 发包后的产物挂掉浑然不知
- 为什么不直接放弃 monorepo 而使用源码文件夹呢。。。
文章还讨论了幻影依赖,去除重复包,一包一版本、版本号管理等令人头疼的多包管理问题
BTW 作者目前是我司员工(专业搞 monorepo 的,牛逼!)
来了解一下 yarn 的 pnp (opens in a new tab)(Plug'n'Play)。注意只有 v2 开始有,npm 默认安装的都是 v1 的 yarn(不知道为什么
yarn set version stable
yarn install
更新Plug and Play (opens in a new tab) 是什么?中文翻译过来叫“即插即用”。。
如果需要升级到
>1
的版本 TODO
字节跳动前端工程化 (opens in a new tab)
什么是前端工程化:开发效率、代码质量、代码复用性、自动化流程、团队协作、...
文章介绍了 monorepo、rspack、微前端、web 构建分析工具
what is JWT (opens in a new tab)
几年前做过电商项目的 API 接口,在用户鉴权这块用到了 JWT token 的方式,近期工作上又有类似的场景,来做个回顾吧
A JWT is a mechanism to verify the owner of some JSON data. It’s an encoded, URL-safe string that can contain an unlimited amount of data (unlike a cookie) and is cryptographically signed.
When a server receives a JWT, it can guarantee the data it contains can be trusted because it’s signed by the source. No middleman can modify a JWT once it’s sent.
不要用 JWT 作为 session token:一个原因是本身的功能比较丰富,容易出错;第二个是因为 JWT 在一个 session 结束后不能直接移除,因为他自包含(self-contained)没有一个中心的控制地来让他失效;而且这个 token 的长度相对很大,作为 cookie 会增加请求的载荷。所以不合适
用 JWT 作为 API 的鉴权:
如何让一个 JWT token 失效:一个暴力的方法是直接把服务端的 secret 换掉,那全部的 JWT 都失效了;还有利用
iat
这个 token 创建的时间,自动会存为 token 的这个属性,然后可以通过服务端的比较,来决定是否让其失效;还可以自定义一些属性/黑白名单的机制(需要存储)如何在 cookie 中安全的存储 JWT(client):client 拿到 JWT,最好是存在 HttpOnly cookie (opens in a new tab)(MDN (opens in a new tab)),不会被 js 访问到(
Set-Cookie: =“[; “=“] [; expires=“][; domain=“] [; path=“][; secure][; HttpOnly]
,例如:Set-Cookie: id=a3fWa; Expires=Thu, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly
)可以不需要服务端存储,解析 jwt 已经足够安全
通过 JWT 跨服务鉴权:无需两边共享 session,只需要各自解析即可(同一 secret)
react-loadable (opens in a new tab)
读了下 readme,写的真的算是非常清晰的文档了(包括 API DOC),讲清楚了为什么要做组件粒度的 loadable(拆包)而不是路由(页面)维度的,以及丰富特性的 API
BTW,这和
react.lazy
(opens in a new tab),loadable/components (opens in a new tab) 这些库之间到底用啥呢loadable/components 给出了比较 (opens in a new tab):
- react lazy 是官方结合 Suspense 的 code splitting 方案,如果已经使用了,用就完事
@loadable/component
提供了更完整的 ssr 方案,ssr 首选;并支持动态路径的import()
- react-loadable:与 webpack 4+ 和 babel 7+ 不兼容了,也很久不维护了,不太推荐目前使用
关于前端是否需要对登录密码加密 (opens in a new tab)
文章分析的挺到位的,在 HTTPS 的前提下前端是否需要加密一些字段,真的是探讨很多的问题
对于这个问题的结论是:「在 client 加密(非对称)或是 hash,确实能增加安全性」
- HTTPS 因为各种原因失效的时候,攻击者无法拿到明文的密码
- 在 Server 端,没有人知道使用者的明文密码
- 明文密码不会被记录到各种 log 中(前端接口失败的上报)
一些大公司(银行)做了
很多人喜欢在各个平台用同一套账号/密码,如果被泄漏了,还挺危险
至于成本(ROI)
我自己認為一位優秀的工程師不能只給得出最佳實踐,而是必須針對有限資源的狀況之下,給出各種不同的解法,因此這篇討論的問題不是毫無意義的。把這個問題整理過一輪之後,自然而然就會出現許多成本不同,效益也不同的解法。 这段说的挺好
最后摘录下结论:
- 一定要首选用 HTTPS
- 可以使用 presskeys (opens in a new tab)
- 如果你想要用很安全的方式驗證密碼,並且確保在 Server 端不會處理到明文密碼,請參考 SRP(Secure Remote Password) (opens in a new tab)協定,或是留言裡面讀者 yoyo930021 提到的 OPAQUE (opens in a new tab)
- 上述没有资源的话,给密码加 hash or 加密能增加安全性,但会带来额外成本
- 如果是对字段安全有极高要求的业务,再去实践吧,还是取决于 ROI
我们需要 HTTP3 (opens in a new tab)
TCP 不再适合:效率问题,将网页视为耽搁文件
QUIC:与 TLS 深度集成,HTTPS 仅对数据进行加密,QUIC with TLS 会对协议大部分内容加密,更加安全,效率性能提升,更快的连接握手
React18 带来的类型变化 (opens in a new tab)
在公司内部看到的技术分享,做一些摘录总结
现象:升级到 React18 之后,
React.FC
的 Props 不带children
属性了React18 背后的原因:
React.FC
移除了 props 里隐式提供的children
类型ReactNode
类型中移除了{}
CRA 的这个 PR 中,移除了模版代码的
React.FC
(一度被 TS 新接触者认为是最佳时间),是有好处的,因为 FC 这个类型多多少少有点问题
默认带有隐式
children
不太好支持泛型组件
const GenericComponent: React.FC</* ??? */> = <T>(props: GenericComponentProps<T>) => {/*...*/}
component as namespace pattern 不太好做
<Select> <Select.Item /> </Select>
一旦定义成 FC,要扩展就不太行了
当然 FC 也有好处:
- 提供了明确的返回值类型约束(不允许返回
undefined
,object
之类的)具体 React18 带来的类型上的 breaking changes (opens in a new tab) 主要就是这些
补充:
JSX.Element
vsReact.ReactNode
vsReact.ReactElement
ReactElement
是React.createElement
(17 之后是 jsx)的返回
JSX.Element
基本是ReactElement
,就是 type 和 props 都是 any,更加宽松,同样 JSX 实际是一个 namespace,各个库可以覆盖declare global { namespace JSX { interface Element extends React.ReactElement<any, any> {} } }
ReactNode
虚拟 DOM 的表示方式,是 class 组件 render 函数和函数组件的返回值,因此它是组件所有可能返回值的集合。它除了可以是 ReactElement,还可以是 string, number, undefined,....
一个 JS 库 memoize-one (opens in a new tab)
技术文档看到有使用这个库,看看是做啥的
作用:记忆一个函数,当入参和上一次相同的时候,直接返回上一次结果(缓存),否则重新计算。具体例子可以看 readme
看到一些代码挺有意思:
ponyfill,之前也遇到过,按需使用 polyfill
// Number.isNaN as it is not supported in IE11 so conditionally using ponyfill // Using Number.isNaN where possible as it is ~10% faster const safeIsNaN = Number.isNaN || function ponyfill(value: unknown): boolean { // // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN#polyfill // NaN is the only value in JavaScript which is not equal to itself. return typeof value === "number" && value !== value; };
回到这个功能的场景,连续相同重复输入的时候才能使用缓存结果优化,类似 LRU,并且每次计算都是幂等且无副作用的。这种场景会有哪些呢?
而且内部会 cache 上一次的函数参数,感觉可能会导致内存不释放。。不过可以手动调用
clear()
方法
Discord 服务从 Go 切换到 Rust (opens in a new tab)
文章是 Discord 的 Blog,介绍了他们的 Read States 服务(非常高并发,用户每次进入 Discord 都会读一次,查询已经读过的 channel 和 message)从 Go 切换到 Rust 的过程,解决了 Go 强制 2min 的一次 GC 所带来的服务端耗时(latency)尖刺(spikes),以及全面性能的提升。
Rust 无 GC(借用特性,对比 Go stop the world)的情况下,能够很好的处理 LRU 缓存丢弃的数据(立即释放内存)
Discord 也是一家非常拥抱前沿技术的公司,50 多个工程师,承载了 250+ million users
ahooks useMemorizedFn (opens in a new tab)
WIP
无聊的问题:JS 如何判断一个变量是 async function
某天刷 B 站看到一个视频在讲这个,居然还是个面试题
直接上方法吧:
- 通过
Symbol.toStringTag
(opens in a new tab) 可以设置一个类的 toString 后的 tagasync 函数的这个 tag 值即为
AsyncFunction
,数组的是Array
,null
是Null
let a = async () => {}; Object.prototype.toString.call(a); // '[object AsyncFunction]'
单独设置 Class 的 toStringTag
class ValidatorClass { get [Symbol.toStringTag]() { return "Validator"; } }
- 评论区也有
func instanceof (async () => {}).constructor
的方法let a = async () => {}; a.__proto__ === (async () => {}).constructor.prototype; // true
CSS open-props (opens in a new tab)
又一个比较火的 CSS 原子化框架,用的是原子性的 CSS variable,官网提供的预设场景还是挺丰富的
BTW 官网的那些渐变色挺好看