首页
Search
1
Linux 下 Bash 脚本 bad interpreter 报错的解决方法
69 阅读
2
Arch Linux 下解决 KDE Plasma Discover 的 Unable to load applications 错误
51 阅读
3
Arch Linux 下解决 KDE Plasma Discover 的 Unable to load applications 错误
42 阅读
4
如何在 Clash for Windows 上配置服务
40 阅读
5
如何在 IOS Shadowrocket 上配置服务
40 阅读
clash
服务器
javascript
全部
游戏资讯
登录
Search
加速器之家
累计撰写
1,061
篇文章
累计收到
0
条评论
首页
栏目
clash
服务器
javascript
全部
游戏资讯
页面
搜索到
1061
篇与
的结果
2024-09-10
RxJS Hooks and Suspense: The Ultimate Guide
(This post is also on medium)Why HooksStateful logic is unavoidable in any React project. In early days we used the state property in Class-Components to hold stateful values."This" isn't the wayBut quickly we realized that it is prone to lose track of states in "this" way. So we divided Components into stateful(smart) Components and stateless(dumb) Components. Stateful logic is delegated to parent stateful Components to keep most Components stateless.This does not solve the issue, just makes it less painful.Time travellingThen came the age of Redux(and MobX etc.). We started to put states into central stores which can be tracked with devtools and stuff.This does not solve the issue, just delegates it to outside stores.Introducing stores is acceptable for a full project but would be too bloated for developing reusable stateful Components.Get on the HookReact Hooks fills this gap by offering a mechanism that connects side-effects separately within the Component.For stateful logic it is like connecting to many mini-stores within the Component. Side-effect code with hooks is compact, reusable and testable.Hooks is an attempt to solve the issue. It is delicate and not perfect but it is the best we have so far.For more about hooks see the React Docs.Why RxJS in HooksSince React hooks opens a door of reusing side-effect logic within Components, it is tempting to reuse complicated asynchronous logic like remote data fetching, intricate animation or device input sequence interpretation.One of the most popular ways to manage complicated asynchronous logic is Reactive Programming, a language-independent declarative programming paradigm concerned with data streams and the propagation of change. RxJS, part of the ReactiveX(Reactive Extensions), is a JavaScript implementation of reactive programming.There are also libraries that focus only on a few specific asynchronous scenarios, like swr for remote data fetching. This is like comparing Redux Saga with Redux Observable. The knowledge you gain from learning how to use these libraries is not as transferable as RxJS and Reactive Programming.Yes there is a learning curve on RxJS but that is mostly a one-time conceptual thing. Don't be scared by the number of RxJS opertators. You most likely only need a few of them. Also see the Operator Decision Tree.Observable HooksWe first tried rxjs-hooks but quickly encountered some tricky TypeScript issues. We also think the useEventCallback is taking too much responsibilities which is a performance issue that is hard to fix due to rules of hooks.Unfortunately the project is not actively developed as the team has shifted focus to the redux-observable-like ayanami project.Ultimately we rethought the whole integration, redesigned API from the ground up and created observable-hooks for connecting RxJS Observable to React Components.A simple example(more on the docs):import React from 'react' import { useObservableState } from 'observable-hooks' import { timer } from 'rxjs' import { switchMap, mapTo, startWith } from 'rxjs/operators' const App = () => { const [isTyping, updateIsTyping] = useObservableState( event$ => event$.pipe( switchMap(() => timer(1000).pipe( mapTo(false), startWith(true) ) ) ), false ) return ( {isTyping ? 'Good you are typing.' : 'Why stop typing?'} ) }By decoupling states, events and Observables it no longer makes unused resources run idle.Logic lives in pure function which improves reusability and testability.See the docs for more about core concepts and API.Pomodoro Timer Example:SuspenseWith the experimental React Suspense asynchronous resources can be read declaratively like it has already been resolved.Since Suspense is just a mechanism it is possible to convert Observables into Suspense compatible resources (benefits of observable as data source).Observable-hooks offers ObservableResource to do the trick.// api.js import { ObservableResource } from 'observable-hooks' const postResource$$ = new Subject() export const postsResource = new ObservableResource(postResource$$.pipe( switchMap(id => fakePostsXHR(id)) )) export function fetchPosts(id) { postResource$$.next(id) }Resources are consumed with useObservableSuspense.// App.jsx import { useObservableSuspense } from 'observable-hooks' import { postsResource, fetchPosts } from './api' fetchPosts('crimx') function ProfilePage() { return ( ) } function ProfileTimeline() { // Try to read posts, although they might not have loaded yet const posts = useObservableSuspense(postsResource) return ( {posts.map(post => ( {post.text} ))} ) }ConclusionThe API of observable-hooks is really simple and flexible. Folks who love both React and RxJS I highly recommend you give it a try.What do you think? Please let us know by leaving a comment below!
2024年09月10日
2 阅读
0 评论
0 点赞
2024-09-10
自定义 Webpack Target
问题由于浏览器扩展有特殊的权限限制,许多前端的开发工具都无法直接派上用场,如之前我解决了热更新和分块自动填写到清单的问题。现在我们继续突破下个影响性能的问题:动态加载分块。Webpack 支持 import() 自动分块并异步加载,这对于大型应用来说是非常有用的功能。虽然浏览器扩展的源文件都在本地,但对于大型应用来说静态加载依然会浪费了不少内存。那么为什么浏览器扩展不支持异步加载呢?这就需要理解 Webpack 是怎么处理的。(如果只关心如何在浏览器扩展中使用,本文的内容已封装为 webpack-target-webextension 库。)JSONP当我们指定(或默认) Webpack Target 为 web 的时候,Webpack runtime 会以 JSONP 方式来加载异步块。那么什么是 JSONP?JSONP 常用于跨域动态获取数据。如 a.com 向 b.com 请求数据, 首先生成一个回调函数名,如 myCallback; 创建全局函数 myCallback 实现加载数据的逻辑; 以 myCallback 作为参数构造请求链接,如 https://b.com/data?callback=myCallback; 通过支持跨域的 标签发起请求,; 服务器将数据包裹到回调中返回, myCallback(...); 浏览器加载脚本,myCallback 的逻辑被执行。 沙箱这种方式为什么在浏览器扩展中会失效呢?我们都知道一些浏览器扩展可以对用户的网页进行修改,如美化或者去广告。这些修改是通过一种叫 content script 类型的脚本实现。每个 content script 可以在作者指定的时机被植入到页面上。虽然 content script 可以修改 DOM,但是 content script 本身是运行在隔离的沙箱环境中的。这个环境可以让 content script 访问部分浏览器扩展 API。所以当 Webpack 以 JSONP 方式加载异步块的时候, 中的回调会在用户的脚本环境中执行,而扩展环境中的接收回调只能默默等待到超时。不如来真的主流浏览器早早就支持了原生的 import() ,那么有没有可能,我们不让 Webpack 生成 JSONP 而直接使用原生的 import()? CRIMX 说 yes!在 Webpack 中,模块加载的逻辑通过 target 设置来调整。Webpack 4 中预设了几种常见的 target: Option Description async-node 用于类 Node.js 环境 electron-main 用于 Electron 主进程 electron-renderer 用于 Electron 渲染进程 electron-preload 用于 Electron 渲染进程 node 用于类 Node.js 环境 node-webkit 用于 NWebKit 环境 web 用于类浏览器环境 webworker 用于 WebWorker 很可惜这几种都不支持原生 import(),也不适用浏览器扩展。在 Webpack 5 的预览中明确提到了对 es2015 的支持,同时提供了新的 module 设置。但是离 Webpack 5 正式发布以及生态跟上可能还有一段时间。最后 target 还支持传入函数以自行实现逻辑。尽管 Webpack 的源码不是很好读,最后还是决定挑战一下,自定义实现一个针对浏览器扩展的 target。其实很简单首先通过文档找到判断上面预设环境的位置。通过参考 web 的配置可以找到 JSONP 的实现在 JsonpMainTemplatePlugin.js 中。其中异步块的加载分了三种方式,正常的,预加载的以及预读取的,对应 和 的 preload 和 prefetch。全部改成 import() 即可。其中注意计算块的路径,由于在 content script 中相对路径会根据当前页面计算,而我们需要根据扩展根来算路径。所以函数 jsonpScriptSrc 改为if (needChunkOnDemandLoadingCode(chunk)) { extraCode.push( '', '// script path function', 'function webextScriptSrc(chunkId) {', Template.indent([ `var publicPath =${mainTemplate.requireFn}.p`, `var scriptSrcPath = publicPath +${getScriptSrcPath( hash, chunk, 'chunkId' )};`, `if (!publicPath || !publicPath.includes('://')) { return (typeof chrome === 'undefined' ? browser : chrome).runtime.getURL( scriptSrcPath ); } else { return scriptSrcPath; }` ]), '}' ) }从而利用 runtime.getURL 来计算扩展资源路径。小坑可以通过 publicPath 来控制根路径。注意去除 @babel/plugin-syntax-dynamic-import 等插件以免 import() 被转换掉。Webpack 一些设置的默认值依赖 target 来判断,所以需要手动设置:module.exports = { resolve: { mainFields: ['browser', 'module', 'main'], aliasFields: ['browser'] }, output: { globalObject: 'window' } }完整修改见这里。
2024年09月10日
4 阅读
0 评论
0 点赞
2024-09-10
梦幻西游群雄第五赛季天元组决赛:天湾竞技破敌奇招
2024群雄逐鹿第五赛季天元组决赛回顾:天湾竞技轻松拿下王者之师2024群雄逐鹿第五赛季天元组决赛在天湾竞技和王者之师之间展开。王者之师虽然在禁选阶段试图干扰天湾竞技的阵容选择,但被其反将一军,轻松拿下比赛胜利。一、封五庄抓点杀,王者之师计谋落空在禁选环节中,王者之师被禁化生、地府,天湾竞技被禁化生、五庄。从禁选情况来看,王者之师大概率知道天湾竞技会禁地府上九黎,便想通过禁用五庄的方式,倒逼天湾竞技上“双封体系”阵容应战。不过,这一策略被天湾竞技识破,反而是王者之师被将了一军。进入比赛后,双方阵容如下:天湾竞技(双封点杀):九黎、盘丝、女儿、地府、化生。 王者之师(双封面伤):九黎、化生、神木、五庄、女儿。从阵容方面来看,双方阵容控制能力很足,但由于王者之师拿到了全场一速、三速,在控制能力要强于天湾竞技。不过,由于天湾竞技携带了地府,所以在抓机会能力上比王者之师略胜一筹。二、比赛回顾比赛前期,天湾竞技靠着阵法大克优势,牢牢压制王者之师的进攻节奏。比赛第2回合时,王者之师的九黎城就被天湾竞技压倒,输出能力大打折扣。比赛第8回合,王者之师刚刚用逆境解除九黎城身上的小死亡,女儿村就身中大死亡,被天湾竞技当前回合压倒,整体节奏非常差。比赛第12、14回合时,王者之师的女儿村再度被天湾竞技压制。不过,王者之师靠着神佑和“163”,暂时稳住了节奏。但对于天湾竞技来说,只要保证九黎城出手,就可以轻松打出优势。比赛第16回合,天湾竞技九黎城再度出手,靠着一波极高的面伤,成功压倒王者之师女儿村,彻底打断对手控制节奏。比赛第25回合,天湾竞技抓到机会,靠着九黎城灵宝打出爆炸伤害,将王者之师逼上绝路。随后,天湾竞技果断拉出谛听,仅用3个回合就完成清场,拿下比赛胜利。三、小结总的来说,王者之师在本场比赛最大的失误就是阵容预判。毕竟,禁五庄的想法意在破坏“女儿、五庄”组成的双封体系,逼迫天湾竞技上国标。但他们没想到的是,天湾竞技不仅使用盘丝替代五庄,还上地府玩点杀,再加上阵法大克的情况,使其比赛节奏被全面压制,轻松拿下比赛。
2024年09月10日
4 阅读
0 评论
0 点赞
2024-09-10
命运Steam平均玩家数量下降74%创新低
Bungie《命运2》近30天Steam平均在线玩家数量创下新低,下降了74%。据SteamDB数据,过去30天,《命运2》的平均在线玩家数量仅有32497人。与此同时,在资料片“终焉之形”发布时,该游戏的月度平均玩家数量为12.3万人。这意味着,仅仅三个月后,就有超过9万名玩家流失了。尽管“终焉之形”资料片吸引了大量付费玩家,但是,它的玩家数量下降幅度是三个资料片中最大的。这是一个令人担忧的趋势,因为在“邪姬魅影”资料片发布三个月后,该游戏的平均在线玩家数量超过了6万人,而“光陨”资料片也是同样的情况,三个月后平均在线玩家数量超过了6.2万人。这意味着,“终焉之形”资料片上线三个月后的数据下降了一半。Bungie公司近年来一直在经历困难,今年8月,该公司进行了大规模裁员,解雇了220名员工,去年也有100名员工被裁。这一系列裁员背后的原因是Bungie公司沉迷于宣传意识形态,而不是专注于游戏开发。此外,有报道称《马拉松》重启版开发不顺利,被内部推迟到2025年。据网友爆料,Bungie《马拉松》游戏总监非常正确,曾在出境时标出代词“he/him”,而前总监因为女员工举报性骚扰被解雇。
2024年09月10日
10 阅读
0 评论
0 点赞
2024-09-10
战锤:星际战士2创下Steam在线峰值超过22万的纪录
《战锤40K:星际战士2》发售后在线峰值大幅超越抢先体验期间,达到了22万5690人,成为首发最成功的《战锤40K》游戏。该游戏的在线峰值超过了Steam上每一款《战锤40K》游戏的在线记录,包括《全面战争:战锤3》。玩家认为这再次证明了“老派单人游戏”(战役+合作+多人模式)仍然有很大的市场,而游戏厂商却未能理解玩家的需求。此外,《战锤40K:星际战士2》的更新路线图也已经公布。
2024年09月10日
5 阅读
0 评论
0 点赞
1
...
111
112
113
...
213