深入解读ahooks

简介: 本文适合对打造工具函数库感兴趣的小伙伴阅读。

一、前言


本文基于开源项目:

https://github.com/alibaba/hooks

https://ahooks.js.org/guide/

https://github.com/lerna/lerna

image.png

 

   广东靓仔在看ahooks项目代码的时候发现了一些有意思的东西,这里分享下。


二、ahooks是什么


   ahooks是一套高质量可靠的 React Hooks 库


具有以下特性:

  • 易学易用
  • 支持 SSR
  • 对输入输出函数做了特殊处理,且避免闭包问题
  • 包含大量提炼自业务的高级 Hooks
  • 包含丰富的基础 Hooks
  • 使用 TypeScript 构建,提供完整的类型定义文件

安装:

$ npm install --save ahooks
# or
$ yarn add ahooks


使用:

import { useRequest } from 'ahooks';


三、项目目录


广东靓仔把ahooks的项目代码目录截了个图,如下所示:

image.png


看到这个目录,有种亲切的感觉,经过粗略的查看,跟dumi脚手架有点相似,经过求证,确定是使用dumi搭建的。


目录讲解:

+-- config                 // 项目配置
+-- docs                   // 组件库文档目录  
|  +-- guide               // 组件库文档其他路由
|  +-- index.en-US.md      // 组件库文档首页(英文)
|  +-- index.zh-CN.md      // 组件库文档首页(中文)
+-- packages               // lerna包
|  +-- hooks               // 子包hooks
|  +-- use-url-state       // 子包use-url-state
+-- webpack.common.js      // webpack配置文件
+-- gulpfile.js            // 自动化构建工具配置
+-- lerna.json             // 把各个小功能拆分成独立的npm库


看到这里我们先来温习下dumi相关知识。


四、dumi


dumi是为组件开发场景而生的文档工具。

dumi经常与father搭配使用,father 负责构建,而 dumi 负责组件开发及组件文档生成。


安装使用:

$ npx @umijs/create-dumi-lib        # 初始化一个文档模式的组件库开发脚手架
# or
$ yarn create @umijs/dumi-lib
$ npx @umijs/create-dumi-lib --site # 初始化一个站点模式的组件库开发脚手架
# or
$ yarn create @umijs/dumi-lib --site


效果如下:

image.png

image.png


篇幅有限,这里稍微提下:

1、菜单目录,我们可以通过在config配置navs、menus

2、dumi配置中en-US 是默认语言,如果需要中文创建一个带 zh-CN locale 后缀的同名 Markdown 文件即可。


更多的dumi相关知识可以前往官方文档查看:

https://d.umijs.org/guide


五、hooks


回到ahooks中,从项目目录中可以看到hooks文件是整个工具库的核心


+-- hooks 
|  +-- src               // 子包hooks的源码目录
|  +-- gulpfile.js       // 自动化构建配置
|  +-- package.json      
|  +-- tsconfig.json     // ts配置
|  +-- webpack.config.js // webpack配置
|  +-- yarn.lock         // 锁定版本


在查看源代码的过程中,广东靓仔看到了lodash的影子,推荐一下lodash

下面我们来看看这个hooks具体内容。


tsconfig.json


{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "rootDir": "src"
  }
}


利用extends属性从根目录的tsconfig.json配置文件里继承配置。

compilerOptions指定src文件目录(用于输出),用于控制输出目录结构


webpack.config.js


const merge = require('webpack-merge');
const common = require('../../webpack.common.js');
const path = require('path');
module.exports = merge(common, {
  entry: './es/index.js', // 入口模块的文件相对路径
  output: { // 输出到的目录
    filename: 'ahooks.js',
    library: 'ahooks',
    path: path.resolve(__dirname, './dist'),
  },
});


 webpack.common.js 公共配置文件  -- 抽离出公共的部分  通过merge进行合并

代码裁剪下,方便理解:


module.exports = merge(common, config);


webpack.common.js


里面没有什么特殊的,打包的时候,ahooks不想把react打到bundle中,所以使用了如下配置:


externals: [
    {
      react: 'React',
    },
  ],


gulpfile.js


const commonConfig = require('../../gulpfile');
exports.default = commonConfig.default;


ahooks使用了gulp自动化构建工具增强工作流程


gulpfile配置

const gulp = require('gulp');
const babel = require('gulp-babel');
const ts = require('gulp-typescript');
const del = require('del');
gulp.task('clean', async function () {
 ...
});
gulp.task('cjs', function () {
   ...
});
gulp.task('es', function () {
   ...
});
gulp.task('declaration', function () {
  ...
});
gulp.task('copyReadme', async function () {
   ...
});
exports.default = gulp.series('clean', 'cjs', 'es', 'declaration', 'copyReadme');


可以看到使用了gulp的series()clean、cjs、es、declaration、copyReadme组合成更大的操作,然后依次执行


clean里面调用了del类似于rimraf删除当前工作目录


cjs使用gulp-typescript编译 TypeScript 文件流


declaration生成相应的 .d.ts 文件


copyReadme创建一个用于将 hooks文件的元数据对象写入到文件系统的流


lerna.json

ahooks使用了lerna集中了子包在同一个站点中。

Lerna 是一个工具,可以优化使用 git 和 npm 管理多包存储库的工作流程。

广东靓仔把package.json里面关于lerna剪切了下来,如下:


"scripts": {
    "bootstrap": "lerna bootstrap",
    "clean": "lerna clean --yes",
    "build": "lerna run build",
    "pub": "yarn run build && lerna publish",
    "pub:beta": "yarn run build && lerna publish --dist-tag beta"
  },


Lerna 中的两个主要命令是lerna bootstraplerna publish

bootstrap将 repo 中的依赖项链接在一起。publish将帮助发布任何更新的包。

ahooks的lerna配置如下:


{
  "version": "3.1.9",
  "packages": ["packages/*"],
  "npmClient": "yarn",
  "command": {
    "version": {
      "allowBranch": "master",
      "includeMergedTags": true
    },
    "publish": {
      "message": "chore(release): publish",
      "registry": "https://registry.npmjs.org/"
    }
  }
}


  • version:存储库的当前版本。
  • packages: 用作包位置的 glob 数组。
  • npmClient:用于指定特定客户端以运行命令的选项(也可以在每个命令的基础上指定)。更改为"yarn"使用 yarn 运行所有命令。默认为“npm”。
  • command.version.allowBranch: lerna version当从除master. 仅限制lerna version在主分支被认为是最佳实践
  • command.version.includeMergedTags: 检测到更改的包时包括来自合并分支的标签
  • command.publish.message:执行版本更新以进行发布时的自定义提交消息
  • command.publish.registry:使用它来设置要发布到的自定义注册表 url 而不是 npmjs.org,如果需要,您必须已经过身份验证。

六、工具函数


export {
  useRequest,
  useControllableValue,
  useDynamicList,
  useVirtualList,
  useResponsive,
  useEventEmitter,
  useLocalStorageState,
  useSessionStorageState,
  useSize,
  configResponsive,
  useUpdateEffect,
  useUpdateLayoutEffect,
  useBoolean,
  useToggle,
  useDocumentVisibility,
  useSelections,
  useThrottle,
  useThrottleFn,
  useThrottleEffect,
  useDebounce,
  useDebounceFn,
  useDebounceEffect,
  usePrevious,
  useMouse,
  useScroll,
  useClickAway,
  useFullscreen,
  useInViewport,
  useKeyPress,
  useEventListener,
  useHover,
  useUnmount,
  useSet,
  useMemoizedFn,
  useMap,
  useCreation,
  useDrag,
  useDrop,
  useMount,
  useCounter,
  useUpdate,
  useTextSelection,
  useEventTarget,
  useHistoryTravel,
  useCookieState,
  useSetState,
  useInterval,
  useWhyDidYouUpdate,
  useTitle,
  useNetwork,
  useTimeout,
  useReactive,
  useFavicon,
  useCountDown,
  useWebSocket,
  useLockFn,
  useUnmountedRef,
  useExternal,
  useSafeState,
  useLatest,
  useIsomorphicLayoutEffect,
  useDeepCompareEffect,
  useAsyncEffect,
  useLongPress,
  useRafState,
  useTrackedEffect,
  usePagination,
  useAntdTable,
  useFusionTable,
  useInfiniteScroll,
  useGetState,
  clearCache,
  useFocusWithin,
};


ahook写了以上工具函数,平时开发过程中自己用到的其实并没有这么多,我们可以封装自己的hooks。


七、总结


   在我们阅读完官方文档后,我们一定会进行更深层次的学习,比如看下框架底层是如何运行的,以及源码的阅读。    


这里广东靓仔给下一些小建议:

  • 在看源码前,我们先去官方文档复习下框架设计理念、源码分层设计
  • 阅读下框架官方开发人员写的相关文章
  • 借助框架的调用栈来进行源码的阅读,通过这个执行流程,我们就完整的对源码进行了一个初步的了解
  • 接下来再对源码执行过程中涉及的所有函数逻辑梳理一遍
相关文章
|
存储 前端开发 JavaScript
ahooks 正式发布:值得拥抱的 React Hooks 工具库
ahook定位于一套基于 React Hooks 的工具库,核心围绕 React Hooks 的逻辑封装能力,降低代码复杂度和避免团队的重复建设为背景,共同建设和维护阿里经济体层面的 React Hooks 库。
22802 1
ahooks 正式发布:值得拥抱的 React Hooks 工具库
|
前端开发 JavaScript API
020 Umi@4 中如何实现动态菜单
020 Umi@4 中如何实现动态菜单
1053 0
020 Umi@4 中如何实现动态菜单
|
资源调度 前端开发 容器
react插件推荐-瀑布流-macy
macy,一款react开发用的瀑布流插件,亲测体验很好
1906 0
【已解决】Error: Element type is invalid: expected a string (for built-in components) or a class/function
Error: Element type is invalid: expected a string (for built-in components) or a class/function
2552 0
【已解决】Error: Element type is invalid: expected a string (for built-in components) or a class/function
|
6月前
|
存储 前端开发 安全
常见的前端加密方式都有哪些?
【4月更文挑战第19天】本文介绍了前端加密的四种常见方法:哈希加密、对称加密、非对称加密和混合加密。哈希加密适用于密码存储,但存在哈希碰撞风险;对称加密速度快,适合安全通信;非对称加密更安全,但速度慢;混合加密结合两者优点,常用于 SSL/TLS。前端加密是数据安全的重要一环,但需与后端安全措施配合以构建全面防护体系。示例代码展示了 JavaScript 中的 SHA-256、AES 和 RSA 加密。
701 6
|
6月前
vue3 watch 监听多值以及深度监听用法
vue3 watch 监听多值以及深度监听用法
2001 0
|
前端开发 JavaScript API
ahooks 3.0 来了!高质量可靠的 React Hooks 库
ahooks 3.0 来了!高质量可靠的 React Hooks 库
812 0
|
API
React+Hook+ts+antDesign实现table行编辑功能(1)
React+Hook+ts+antDesign实现table行编辑功能
199 0
|
前端开发 JavaScript API
MonacoEditor 加载很慢该怎么优化?
MonacoEditor 加载很慢该怎么优化?
1455 0
|
6月前
|
JavaScript 前端开发
深入了解rollup(二)常用配置
Rollup是一个JavaScript模块打包器,它可以将多个模块打包成一个单独的文件,以便在浏览器中使用。与其他打包工具相比,Rollup的主要优势在于它可以生成更小、更快的代码。在本文中,我们将深入了解Rollup的常用配置的使用方法。
177 0