创建一个hooks
menus 需要消费packages/hooks底下的内容
packages/hooks/src 下新建useToggle 文件夹 index 文件
自定义hooks
import {useMemo, useState} from 'react'type defultFn = () =>void;export interface Actions{ setLeft:defultFn; setRight:defultFn; toggle:defultFn;}function useToggle<T = boolean>():[boolean,Actions];//返回结构为D或Rfunction useToggle<D,R>(defaultValue:D = false as D ,reversevalue?:R){ const [state,setState] = useState<D | R>(defaultValue); const actions = useMemo(()=>{ const reversevalueOrigin = (reversevalue === undefined ? !defaultValue : reversevalue) as D|R; const toggle = () =>setState((s) => (s === defaultValue ? reversevalueOrigin : defaultValue)); const setLeft = () =>setState(defaultValue); const setRight = () =>setState(reversevalueOrigin); return { toggle, setLeft, setRight } },[]) return [state, actions];}export default useToggle
src index.ts 中引入导出
import useToggle from "./useToggle";export{ useToggle}
最外层config.ts中配置
"paths": { "@/*": ["src/*"], "demoHook": ["./packages/hooks/src/index.ts"],//配置相应的映射 "demo-hooks": ["./packages/hooks/src/index.ts"], "encodeHooks/lib/*": ["./packages/hooks/src/*"], "encode-hooks/lib/*": ["./packages/hooks/src/*"] },
useToggle 下创建对应demo文件夹 demo1.tsx
/** * title:useToggle基础用法 * desc:当action中的值没有初始化时,默认是false */import React from "react";import {useToggle} from 'demoHook';export default ()=>{ const [state,{toggle,setLeft,setRight}] = useToggle(); return <div> <p>当前state 的值为:{`${state}`}</p> <p> <button type ="button" onClick={toggle}>toggle切换</button> </p> <p> <button type ="button" onClick={setLeft}>setLeft切换</button> </p> <p> <button type ="button" onClick={setRight}>setRight切换</button> </p> </div>}
useToggle下创建index.md path 关联/hooks 路径
---nav: path: /hooks---# useToggle进行值切换的基础 hooks## demo<code src="./demo/demo1.tsx">
menus 中消费相应的index.md
export const menus = [ { title: '状态', children: ['useToggle'], }, ];
config.ts中配置
alias: { demoHook: process.cwd() + '/packages/hooks/src/index.ts', },
//导航栏的配置 navs: [ { title: '指南', path: '/guide' }, { title: 'Hooks', path: '/hooks' }, ], //指向的docs文件夹下的路径,默认Index menus: { '/': [ { title: '首页', path: 'index', }, ], '/guide': [ { title: '介绍', // 左侧导航栏内容 path: '/guide', }, ], '/hooks': menus, },
jest 写测试用例
全局状态下配置jest.config.js
//针对浏览器黄精配置的基础jest 内容module.exports = { preset: 'ts-jest/presets/js-with-ts', testEnvironment: 'jsdom', clearMocks: true, testPathIgnorePatterns: ['/.history/'], modulePathIgnorePatterns: ['<rootDir>/package.json'], resetMocks: false, setupFiles: ['./jest.setup.js', 'jest-localstorage-mock'], setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'], transform: { '^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.json' }], }, moduleNameMapper: { '^lodash-es$': 'lodash', }, collectCoverageFrom: [ '<rootDir>/**/src/**/*.{js,jsx,ts,tsx}', '!**/demo/**', '!**/example/**', '!**/es/**', '!**/lib/**', '!**/dist/**', ], transformIgnorePatterns: ['^.+\\.js$'], };
创建一个空的 jest.setup.js,存放一些公共的方法
jest 默认会解析_tests_下的文件 index.test.ts
import {renderHook,act} from '@testing-library/react'import useToggle from "../index";const callToggle = (hook)=>{ act(()=>{ hook.result.current[1].toggle() })}describe('useToggle',()=>{ //jest it('针对基础功能使用测试',()=>{ const hooks = renderHook(()=>useToggle()); expect(hooks.result.current[0]).toBe(false); }) it('针对手动切换toggle模拟',()=>{ const hooks = renderHook(()=> useToggle("haleyliang","lianghaley")) expect(hooks.result.current[0]).toBe("haleyliang"); callToggle(hooks) expect(hooks.result.current[0]).toBe("lianghaley"); })})
package.json
scripts
"test":"jest"
pnpm run test 运行测试用例 或者指名道姓执行一个单一的测试用例
pnpm run test useToggle
npm 代码构建发布
全局package.json中添加指令
"pub:beta":"pnpm run build && pnpm -r --filter=./packages/hooks publish --tag beta",
"pub":"pnpm run build && pnpm -r --filter=./packages/hooks publish",
"build:doc": "dumi build",
登录npm
执行 pnpm run pub:beta 发布包 仅可用于首次
pnpm run pub 发布包第二次同时需要修改包版本
发布成功,npm packages 下可以查到发布的包
外层添加 README.md , gulp打包同步README.md 到 hooks文件夹下
gulp.task('copyReadme', async function () { await gulp.src('../../README.md').pipe(gulp.dest('../../packages/hooks'));});
package.json 中添加待发布包文件路径
"files": ["README.md"]
README.md 最终就是npm 包的描述
收集meta信息
hooks gulpfile.js md 下的标题通过正则校验添加至meta.json 文件中,并发布至npm
const commonConfig = require('../../gulpfile');const gulp = require('gulp');const fs = require('fs');const fse = require('fs-extra');const fg = require("fast-glob");//类似于fs的升级版const gm = require('gray-matter');const { async } = require('fast-glob');async function genDesc(mdPath){ if(!fs.existsSync(mdPath)){ return } const mdFile = fs.readFileSync(mdPath,'utf-8'); const {content} = gm(mdFile); let description = (content.replace(/\r\n/g, '\n').match(/# \w+[\s\n]+(.+?)(?:, |\. |\n|\.\n)/m) || [])[1] || ''; description = description.trim(); return description} //添加一个hooks的文档声明async function genMetaData(){ //收集meta描述 const metaData={ function:[] }; //获取src 下 use* 目录名,map循环遍历去除src/路径前缀,排序 const hooks = fg.sync('src/use*',{ onlyDirectories:true }).map((hooks)=>hooks.replace('src/','')).sort(); // console.log(hooks) [ 'useToggle' ] await Promise.allSettled( hooks.map(async (hook)=>{ const description = await genDesc(`src/${hook}/index.md`); return { name:hook, description } }).then((res)=>{ metaData.function = res.map((item)=>{ if(item.status === 'fulfilled'){ return item.value } return null }) }) ) return metadata;}gulp.task('metaData', async function(){ const metaData = await genMetaData(); await fse.writeJson('metadata.json', metadata, { spaces: 2 });})exports.default = gulp.series(commonConfig.default,'metaData');
发布代码到github.io, 创建 .github/workflows 包含test.yml deploy.yml
可参照 使用Github Actions 来构建发布应用 - 知乎 (zhihu.com)
test.yml
name: Build and Deployon: push: branches: - masterjobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout ️ uses: actions/checkout@v2.3.1 - name: lock npm version uses: actions/setup-node@v3 with: node-version: 16.18.0 - name: Install and Build run: | npm i -g pnpm pnpm run init env: NODE_OPTIONS: '--max_old_space_size=4096' - name: test run: | pnpm run test
deploy.yml
name: Build and Deployon: push: branches: - masterjobs: build-and-deploy: runs-on: ubuntu-latest permissions: contents: write steps: - name: Checkout uses: actions/checkout@v2.3.1 - name: Lock npm version uses: actions/setup-node@v3 with: node-version: 16.18.0 - name: Install and Build run: | npm i -g pnpm pnpm run init pnpm run build:doc env: NODE_OPTIONS: '--max_old_space_size=4096' - name: Deploy uses: JamesIves/github-pages-deploy-action@4.1.3 with: BRANCH: gh-pages FOLDER: dist ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
ACCESS_TOKEN是访问github api的令牌
点击github主页 --- 个人头像 -- settings --- develper settings --- Personal access tokens 进行生成 ACCESS_TOKEN
配置 ACCESS_TOKEN
配置路径
若页面能正常打开但是js css 请求报404则配置如下路径