【实现注册的源码】【夸克手机查看网站源码】【C 模块化 源码】preact源码

时间:2024-12-28 10:09:51 来源:iapp拼图源码 分类:探索

1.计算机开发|Github上8个很棒的源码React项目
2.如何看待最近正式发布的 Web 全栈框架 Fresh?
3.详解|天猫搜索前端技术历代记
4.preact源码解析,从preact中理解react原理
5.畅谈React material-ui的源码样式方案
6.Preact(React)核心原理详解

preact源码

计算机开发|Github上8个很棒的React项目

       来自公众号:前端充电宝

       今天分享 Github 上 8 个很棒的 React 项目,旨在通过学习这些项目的源码源码,帮助大家更好地理解 React,源码并编写出更优雅的源码 React 代码!

       概览:

       1. React Tetris

       React Tetris 源码实现注册的源码是一个使用 React、Redux、源码Immutable 制作的源码俄罗斯方块游戏。它是源码一个适用于 React 学习者的练习项目,通过优化和打磨细节,源码可以提升开发者对 React 的源码掌握。项目介绍中包含作者的源码开发想法,提供中文资源,源码非常值得借鉴。源码

       Github:github.com/chvin/react...

       2. Kutt.it

       Kutt 是源码一个现代的 URL 缩短器,支持自定义域名。它集成 Node.js、Express、Passport、React、TypeScript、Next、Easy Peasy、styled-components、Recharts、PostgreSQL、Redis 夸克手机查看网站源码等技术,提供功能丰富的 URL 缩短服务。

       Github:github.com/thedevs-netw...

       3. Win in React

       通过这个项目,开发者使用 React、CSS (SCSS) 和 JS 等标准 Web 技术在浏览器中复制 Windows 桌面体验。该项目展示了在 Web 上重现操作系统的可能性。

       Github:github.com/blueedgetech...

       4. JoL-player

       JoL-player 是一个功能强大的 React 播放器,通过高质量的 React 组件、TypeScript 开发和完整的类型定义文件,提供国际化语言、强大的 API 和功能。支持 React +版本。

       Github:github.com/lgf/JoL-p...

       5. Take Note

       TakeNote 是一个 Web 笔记应用,提供搜索、多光标编辑、链接笔记、语法高亮、键盘快捷键等功能。它基于 TypeScript、React、Redux、Node、Express 等技术创建,支持本地存储和 zip 格式的下载。

       Github:github.com/taniarascia...

       6. Fiora

       Fiora 是一个基于 Node.js、React 和 socket.io 的聊天应用程序,支持添加好友、C 模块化 源码群聊、设置主题、消息提醒等,适用于 Windows / Linux / macOS 系统。

       Github:github.com/yinxin/fi...

       7. Todoist clone

       Todoist clone 是一个使用 create-react-app 构建的 Todoist 的简化版,包含 React(自定义 Hooks、context)、Firebase 和 React 测试库。项目使用 SCSS (CSS) 和 BEM 命名方法,旨在帮助开发者更好地理解 React。

       Github:github.com/karlhadwen/t...

       8. Jira Clone

       Jira Clone 是一个使用 React 开发的简化版 Jira 工具,提供交互式用户界面。它使用 React 以及 webpack、Node.js、ESLint、styled-components 和 cypress 构建,支持最新的 React 特性。

       Github:github.com/oldboyxx/jir...

如何看待最近正式发布的 Web 全栈框架 Fresh?

       Fresh 是由 Deno 作者推出的一款 Web 全栈框架,最近正式发布了 1.0 版本并支持了生产环境。它在 Github 上热度较高,适合深入研究。以下从框架定位、上手体验、优劣势评估和源码实现四个方面介绍 Fresh 框架。

       Fresh 定位为 Web 全栈框架,与 Next.js 和 Remix 相似,仿九牛网源码具有 Deno 的优势,内置测试工具和支持 blogs.com/zhaojietec/p/.html

       ã€€ã€€ä¸è¿‡éœ€è¦æ³¨æ„çš„是,目前为止,UIExplorer在Android下有一个bug,IOS下没有问题,通过google可以找到了解决办法。/facebook/react-native/issues/

       ã€€ã€€åŽŸå› æ˜¯ï¼Œjs代码和android原生代码不同步,通过build.gradle可以看到android下的引用的reactNative核心库为,而js代码版本已经更新到了。

       ã€€ã€€è§£å†³çš„办法有2个,一个是使用git工具(如smartGit),将js代码恢复到之前的版本,另一个办法是重新编译reactNative的核心库,编译核心库需要ndk,在mac下没有问题,在windows编译会出错。编译reactNative核心库,对UIExplorer下注释掉的依赖项进行修改即可,编译速度较慢 需要在线下载第三方依赖库。

       ã€€ã€€dependencies {

       ã€€ã€€compile fileTree(dir: 'libs', include: ['*.jar'])

       ã€€ã€€compile 'com.android.support:appcompat-v7:.0.1'

       ã€€ã€€// Depend on pre-built React Native//compile 'com.facebook.react:react-native:0..+'

       ã€€ã€€// Depend on React Native source.

       ã€€ã€€// This is useful for testing your changes when working on React Native.

       ã€€ã€€compile project(':ReactAndroid')

       ã€€ã€€}

       ã€€ã€€ç”±äºŽwindows下无法编译,所以这里提供编译好的aar文件,修改UIExplorer build.gradle中的依赖项就可以了。至于如何引入aar文件,可以自行搜索。当然mac下同样也可以用这个aar,可以省去不少麻烦。

pnpm+workspace+changesets构建你的monorepo工程

       pnpm+workspace+changesets构建你的monorepo工程什么是monorepo?

       什么是monorepo?以及和multirepo的区别是什么?

       关于这些问题,在之前的一篇介绍lerna的文章中已经详细介绍过,感兴趣的同学可以再回顾下。

       简而言之,monorepo就是把多个工程放到一个git仓库中进行管理,因此他们可以共享同一套构建流程、代码规范也可以做到统一,特别是如果存在模块间的相互引用的情况,查看代码、修改bug、调试等会更加方便。

什么是pnpm?

       pnpm是新一代的包管理工具,号称是最先进的包管理器。按照官网说法,可以实现节约磁盘空间并提升安装速度和创建非扁平化的node_modules文件夹两大目标,具体原理可以参考pnpm官网。

       pnpm提出了workspace的概念,内置了对monorepo的支持,那么为什么要用pnpm取代之前的lerna呢?

       这里我总结了以下几点原因:

       lerna已经不再维护,后续有任何问题社区无法及时响应

       pnpm装包效率更高,并且可以节约更多磁盘空间

       pnpm本身就预置了对monorepo的支持,不需要再额外第三方包的支持

       onemorething,就是好奇心了?

如何使用pnpm来搭建menorepo工程安装pnpm$?npm?install?-g?pnpm v7版本的pnpm安装使用需要node版本至少大于v..0,所以在安装之前首先需要检查下node版本。

工程初始化

       为了便于后续的多个易语言源码程序演示,先在工程根目录下新建packages目录,并且在packages目录下创建pkg1和pkg2两个工程,分别进到pkg1和pkg2两个目录下,执行npminit命令,初始化两个工程,package.json中的name字段分别叫做@qftjs/menorepo1和@qftjs/monorepo2(PS:@qftjs是提前在npm上创建好的组织,没有的话需要提前创建)。

       为了防止根目录被发布出去,需要设置工程工程个目录下package.json配置文件的private字段为true。

       为了实现一个完整的例子,这里我使用了father-build对模块进行打包,father-build是基于rollup进行的一层封装,使用起来更加便捷。

       在pkg1和pkg2的src目录下个创建一个index.ts文件:

//?pkg1/src/index.tsimport?pkg2?from?'@qftjs/monorepo2';function?fun2()?{ ?pkg2();?console.log('I?am?package?1');}export?default?fun2;//?pkg2/src/index.tsfunction?fun2()?{ ?console.log('I?am?package?2');}export?default?fun2;

       分别在pkg1和pkg2下新增.fatherrc.ts和tsconfig.ts配置文件。

//?.fatherrc.tsexport?default?{ ?target:?'node',?cjs:?{ ?type:?'babel',?lazy:?true?},?disableTypeCheck:?false,};//?tsconfig.ts{ ?"include":?["src",?"types",?"test"],?"compilerOptions":?{ "target":?"es5","module":?"esnext","lib":?["dom",?"esnext"],"importHelpers":?true,"declaration":?true,"sourceMap":?true,"rootDir":?"./","strict":?true,"noImplicitAny":?true,"strictNullChecks":?true,"strictFunctionTypes":?true,"strictPropertyInitialization":?true,"noImplicitThis":?true,"alwaysStrict":?true,"noUnusedLocals":?true,"noUnusedParameters":?true,"noImplicitReturns":?true,"noFallthroughCasesInSwitch":?true,"moduleResolution":?"node","baseUrl":?"./","paths":?{ ?"*":?["src/*",?"node_modules/*"]},"jsx":?"react","esModuleInterop":?true?}}

       全局安装father-build:

$?pnpm?i?-Dw?father-build

       最后在pkg1和pkg2下的package.json文件中增加一条script:

{ ?"scripts":?{ "build":?"father-build"?}}

       这样在pkg1或者pkg2下执行build命令就会将各子包的ts代码打包成js代码输出至lib目录下。

       要想启动pnpm的workspace功能,需要工程根目录下存在pnpm-workspace.yaml配置文件,并且在pnpm-workspace.yaml中指定工作空间的目录。比如这里我们所有的子包都是放在packages目录下,因此修改pnpm-workspace.yaml内容如下:

packages:?-?'packages/*'

       初始化完毕后的工程目录结构如下:

.├──?README.md├──?package.json├──?packages│├──?pkg1││├──?package.json││├──?src│││└──?index.ts││└──?tsconfig.json│└──?pkg2│├──?package.json│├──?src││└──?index.ts│└──?tsconfig.json├──?pnpm-workspace.yaml└──?tsconfig.root.json安装依赖包

       使用pnpm安装依赖包一般分以下几种情况:

       全局的公共依赖包,比如打包涉及到的rollup、typescript等

       pnpm提供了-w,--workspace-root参数,可以将依赖包安装到工程的根目录下,作为所有?package的公共依赖。

       比如:

$?pnpm?install?react?-w

       如果是一个开发依赖的话,可以加上-D参数,表示这是一个开发依赖,会装到pacakage.json中的devDependencies中,比如:

//?pkg1/src/index.tsimport?pkg2?from?'@qftjs/monorepo2';function?fun2()?{ ?pkg2();?console.log('I?am?package?1');}export?default?fun2;0

       给某个package单独安装指定依赖

       pnpm提供了--filter参数,可以用来对特定的package进行某些操作。

       因此,如果想给pkg1安装一个依赖包,比如axios,可以进行如下操作:

//?pkg1/src/index.tsimport?pkg2?from?'@qftjs/monorepo2';function?fun2()?{ ?pkg2();?console.log('I?am?package?1');}export?default?fun2;1

       需要注意的是,--filter参数跟着的是package下的package.json的name字段,并不是目录名。

       关于--filter操作其实还是很丰富的,比如执行pkg1下的scripts脚本:

//?pkg1/src/index.tsimport?pkg2?from?'@qftjs/monorepo2';function?fun2()?{ ?pkg2();?console.log('I?am?package?1');}export?default?fun2;2

       filter后面除了可以指定具体的包名,还可以跟着匹配规则来指定对匹配上规则的包进行操作,比如:

//?pkg1/src/index.tsimport?pkg2?from?'@qftjs/monorepo2';function?fun2()?{ ?pkg2();?console.log('I?am?package?1');}export?default?fun2;3

       此命令会执行所有package下的build命令。具体的用法可以参考filter文档。

       模块之间的相互依赖

       最后一种就是我们在开发时经常遇到的场景,比如pkg1中将pkg2作为依赖进行安装。

       基于pnpm提供的workspace:协议,可以方便的在packages内部进行互相引用。比如在pkg1中引用pkg2:

//?pkg1/src/index.tsimport?pkg2?from?'@qftjs/monorepo2';function?fun2()?{ ?pkg2();?console.log('I?am?package?1');}export?default?fun2;4

       此时我们查看pkg1的package.json,可以看到dependencies字段中多了对@qftjs/monorepo2的引用,以workspace:开头,后面跟着具体的版本号。

//?pkg1/src/index.tsimport?pkg2?from?'@qftjs/monorepo2';function?fun2()?{ ?pkg2();?console.log('I?am?package?1');}export?default?fun2;5

       在设置依赖版本的时候推荐用workspace:*,这样就可以保持依赖的版本是工作空间里最新版本,不需要每次手动更新依赖版本。

       当pnpmpublish的时候,会自动将package.json中的workspace修正为对应的版本号。

只允许pnpm

       当在项目中使用pnpm时,如果不希望用户使用yarn或者npm安装依赖,可以将下面的这个preinstall脚本添加到工程根目录下的package.json中:

//?pkg1/src/index.tsimport?pkg2?from?'@qftjs/monorepo2';function?fun2()?{ ?pkg2();?console.log('I?am?package?1');}export?default?fun2;6

       preinstall脚本会在install之前执行,现在,只要有人运行npminstall或yarninstall,就会调用only-allow去限制只允许使用pnpm安装依赖。

Release工作流

       在workspace中对包版本管理是一个非常复杂的工作,遗憾的是pnpm没有提供内置的解决方案,一部分开源项目在自己的项目中自己实现了一套包版本的管理机制,比如Vue3、Vite等。

       pnpm推荐了两个开源的版本控制工具:

       changesets

       rush

       这里我采用了changesets来做依赖包的管理。选用changesets的主要原因还是文档更加清晰一些,个人感觉上手比较容易。

       按照changesets文档介绍的,changesets主要是做了两件事:

       Changesetsholdtwokeybitsofinformation:aversiontype(followingsemver),andchangeinformationtobeaddedtoachangelog.

       简而言之就是管理包的version和生成changelog。

配置changesets

       安装

//?pkg1/src/index.tsimport?pkg2?from?'@qftjs/monorepo2';function?fun2()?{ ?pkg2();?console.log('I?am?package?1');}export?default?fun2;7

       初始化

//?pkg1/src/index.tsimport?pkg2?from?'@qftjs/monorepo2';function?fun2()?{ ?pkg2();?console.log('I?am?package?1');}export?default?fun2;8

       执行完初始化命令后,会在工程的根目录下生成.changeset目录,其中的config.json作为默认的changeset的配置文件。

       修改配置文件如下:

//?pkg1/src/index.tsimport?pkg2?from?'@qftjs/monorepo2';function?fun2()?{ ?pkg2();?console.log('I?am?package?1');}export?default?fun2;9

       说明如下:

       changelog:changelog生成方式

       commit:不要让changeset在publish的时候帮我们做gitadd

       linked:配置哪些包要共享版本

       access:公私有安全设定,内网建议restricted,开源使用public

       baseBranch:项目主分支

       updateInternalDependencies:确保某包依赖的包发生upgrade,该包也要发生versionupgrade的衡量单位(量级)

       ignore:不需要变动version的包

       ___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH:在每次version变动时一定无理由patch抬升依赖他的那些包的版本,防止陷入major优先的未更新问题

如何使用changesets

       一个包一般分如下几个步骤:

       为了便于统一管理所有包的发布过程,在工程根目录下的pacakge.json的scripts中增加如下几条脚本:

       编译阶段,生成构建产物

//?pkg2/src/index.tsfunction?fun2()?{ ?console.log('I?am?package?2');}export?default?fun2;0

       清理构建产物和node_modules

//?pkg2/src/index.tsfunction?fun2()?{ ?console.log('I?am?package?2');}export?default?fun2;1

       执行changeset,开始交互式填写变更集,这个命令会将你的包全部列出来,然后选择你要更改发布的包

//?pkg2/src/index.tsfunction?fun2()?{ ?console.log('I?am?package?2');}export?default?fun2;2

       执行changesetversion,修改发布包的版本

//?pkg2/src/index.tsfunction?fun2()?{ ?console.log('I?am?package?2');}export?default?fun2;3

       这里需要注意的是,版本的选择一共有三种类型,分别是patch、minor和major,严格遵循semver规范。

       这里还有个细节,如果我不想直接发release版本,而是想先发一个带tag的prerelease版本呢(比如beta或者rc版本)?

       这里提供了两种方式:

       手工调整

       这种方法最简单粗暴,但是比较容易犯错。

       首先需要修改包的版本号:

//?pkg2/src/index.tsfunction?fun2()?{ ?console.log('I?am?package?2');}export?default?fun2;4

       然后运行:

//?pkg2/src/index.tsfunction?fun2()?{ ?console.log('I?am?package?2');}export?default?fun2;5

       注意发包的时候不要忘记加上--tag参数。

       通过changeset提供的Prereleases模式

       利用官方提供的Prereleases模式,通过preenter<tag>命令进入先进入pre模式。

       常见的tag如下所示:

名称功能alpha是内部测试版,一般不向外部发布,会有很多Bug,一般只有测试人员使用beta也是测试版,这个阶段的版本会一直加入新的功能。在Alpha版之后推出rcReleaseCandidate)系统平台上就是发行候选版本。RC版不会再加入新的功能了,主要着重于除错//?pkg2/src/index.tsfunction?fun2()?{ ?console.log('I?am?package?2');}export?default?fun2;6

       之后在此模式下的changesetpublish均将默认走beta环境,下面在此模式下任意的进行你的开发,举一个例子如下:

//?pkg2/src/index.tsfunction?fun2()?{ ?console.log('I?am?package?2');}export?default?fun2;7

       完成版本发布之后,退出Prereleases模式:

//?pkg2/src/index.tsfunction?fun2()?{ ?console.log('I?am?package?2');}export?default?fun2;8

       构建产物后发版本

//?pkg2/src/index.tsfunction?fun2()?{ ?console.log('I?am?package?2');}export?default?fun2;9规范代码提交

       代码提交规范对于团队或者公司来说是非常重要的,养成良好的代码提交规范可以方便回溯,有助于对本次提交进行review,如果单纯的只是要求团队成员遵循某些代码提交规范,是很难形成强制约束的,现在我们就尝试通过工具来约束代码提交规范。

使用commitizen规范commit提交格式

       commitizen的作用主要是为了生成标准化的commitmessage,符合Angular规范。

       一个标准化的commitmessage应该包含三个部分:Header、Body和Footer,其中的Header是必须的,Body和Footer可以选填。

//?.fatherrc.tsexport?default?{ ?target:?'node',?cjs:?{ ?type:?'babel',?lazy:?true?},?disableTypeCheck:?false,};0

       Header部分由三个字段组成:type(必需)、scope(可选)、subject(必需)

       Typetype必须是下面的其中之一:

       feat:增加新功能

       fix:修复bug

       docs:只改动了文档相关的内容

       style:不影响代码含义的改动,例如去掉空格、改变缩进、增删分号

       refactor:代码重构时使用,既不是新增功能也不是代码的bud修复

       perf:提高性能的修改

       test:添加或修改测试代码

       build:构建工具或者外部依赖包的修改,比如更新依赖包的版本

       ci:持续集成的配置文件或者脚本的修改

       chore:杂项,其他不需要修改源代码或不需要修改测试代码的修改

       revert:撤销某次提交

       scope

       用于说明本次提交的影响范围。scope依据项目而定,例如在业务项目中可以依据菜单或者功能模块划分,如果是组件库开发,则可以依据组件划分。

       subject

       主题包含对更改的简洁描述:

       注意三点:

       使用祈使语气,现在时,比如使用"change"而不是"changed"或者”changes“

       第一个字母不要大写

       末尾不要以.结尾

       Body

       主要包含对主题的进一步描述,同样的,应该使用祈使语气,包含本次修改的动机并将其与之前的行为进行对比。

       Footer

       包含此次提交有关重大更改的信息,引用此次提交关闭的issue地址,如果代码的提交是不兼容变更或关闭缺陷,则Footer必需,否则可以省略。

       使用方法:

commitizen和cz-conventional-changelog

       如果需要在项目中使用commitizen生成符合AngularJS规范的提交说明,还需要安装cz-conventional-changelog适配器。

//?.fatherrc.tsexport?default?{ ?target:?'node',?cjs:?{ ?type:?'babel',?lazy:?true?},?disableTypeCheck:?false,};1

       工程根目录下的package.json中增加一条脚本:

//?.fatherrc.tsexport?default?{ ?target:?'node',?cjs:?{ ?type:?'babel',?lazy:?true?},?disableTypeCheck:?false,};2

       接下来就可以使用$pnpmcommit来代替$gitcommit进行代码提交了,看到下面的效果就表示已经安装成功了。

commitlint&&husky

       前面我们提到,通过commitizen&&c