* perf: optimize MyChores component performance and fix timer errors ## Fixed Issues - ✅ Timer error: `Timer '🏁 Main useEffect processing' does not exist` - ✅ Reduced 1049ms and 613ms message handler violations - ✅ Fixed 1+ second blank screen before chores display - ✅ Eliminated multiple redundant `getFilteredChores` calculations ## Performance Optimizations ### 1. Fixed Timer Execution Issue **Problem**: React strict mode was causing timer mismatch between `console.time` and `console.timeEnd` **Solution**: Restructured async useEffect to ensure proper timer lifecycle ```javascript // Before: Timer in async IIFE caused double-execution issues ;(async () => { console.time('🏁 Main useEffect processing') // ... console.timeEnd('🏁 Main useEffect processing') })() // After: Proper async function structure const processEffectAsync = async () => { // ... async operations console.timeEnd('🏁 Main useEffect processing') } processEffectAsync() ``` ### 2. Optimized useState Lazy Initialization **Problem**: `JSON.parse()` called on every render for state initialization ```javascript // Before: Expensive operation on each render const [openChoreSections, setOpenChoreSections] = useState( JSON.parse(localStorage.getItem('openChoreSections')) || {}, ) // After: Lazy initialization with error handling const [openChoreSections, setOpenChoreSections] = useState(() => { try { return JSON.parse(localStorage.getItem('openChoreSections')) || {} } catch { return {} } }) ``` ### 3. Reduced useEffect Dependencies **Problem**: useEffect running too frequently due to object reference dependencies ```javascript // Before: Full objects cause frequent re-runs }, [choresData, membersData, userProfile, impersonatedUser, ...] // After: Only specific properties that matter }, [choresData?.res, membersData?.res, userProfile?.id, impersonatedUser?.userId, ...] ``` ### 4. Added Memoization for Section Updates **Problem**: `choreSections` updated even when data hadn't actually changed ```javascript // Before: Always updating sections setChoreSections(processedSections) // After: Only update if data actually changed setChoreSections(prevSections => { if (JSON.stringify(prevSections) === JSON.stringify(processedSections)) { return prevSections } return processedSections }) ``` ### 5. Optimized localStorage Access **Problem**: Multiple `localStorage.getItem()` calls and repeated parsing ```javascript // Before: Multiple localStorage calls if (localStorage.getItem('openChoreSections') === null) { // ...localStorage operations } // After: Single cached read const storedSections = localStorage.getItem('openChoreSections') if (storedSections === null) { // ...operations } ``` ### 6. Added useMemo/useCallback for Heavy Computations - `processedChores` - Memoized chore sorting and filtering - `processedSections` - Memoized section grouping - `getFilteredChores` - Memoized filtered chore calculations - `handleChoreUpdated`, `handleChoreDeleted`, `updateChores` - useCallback for stable references ## Performance Results **Before**: 1+ second loading delay, timer errors, frequent violations **After**: - `processedChores calculation: ~0.002ms` (was much slower) - `processedSections calculation: ~0.001ms` (was much slower) - `getFilteredChores: ~0.022ms` (down from multiple slow calls) - `Main useEffect processing: ~0.298ms` (reasonable time) - `Auto-update sections: ~0.007ms` (very fast) 🚀 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: update package.json to remove deprecated @vitejs/plugin-react dependency and add wrangler.toml for build configuration * Revert vite.config.js to it's original state --------- Co-authored-by: Claude <noreply@anthropic.com>
114 lines
4.2 KiB
JSON
114 lines
4.2 KiB
JSON
{
|
|
"name": "donetick",
|
|
"private": true,
|
|
"version": "0.1.111",
|
|
"type": "module",
|
|
"engines": {
|
|
"node": ">=20.0.0",
|
|
"npm": ">=9.0.0"
|
|
},
|
|
"lint-staged": {
|
|
"*.{js,jsx,ts,tsx}": [
|
|
"eslint --fix",
|
|
"prettier --write"
|
|
]
|
|
},
|
|
"scripts": {
|
|
"start": "vite --host",
|
|
"dev": "vite",
|
|
"build": "vite build",
|
|
"build-cf": "rm -rf package-lock.json && npm install && npm install --force @rollup/rollup-linux-x64-gnu@4.34.9 @swc/core-linux-x64-gnu && vite build",
|
|
"build-selfhosted": "rm -rf package-lock.json && npm install && npm install --force @rollup/rollup-linux-x64-gnu@4.34.9 @swc/core-linux-x64-gnu && vite build --mode selfhosted",
|
|
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
|
"preview": "vite preview",
|
|
"setup-m1": "rm -rf node_modules package-lock.json && npm install && npm install --force @rollup/rollup-darwin-arm64 @swc/core-darwin-arm64",
|
|
"setup-apple-silicon": "npm install --no-optional && npm install --force @rollup/rollup-darwin-arm64 @swc/core-darwin-arm64",
|
|
"test-cloudflare-build": "rm -rf node_modules package-lock.json && npm install && npm install --force @rollup/rollup-linux-x64-gnu@4.34.9 @swc/core-linux-x64-gnu && vite build",
|
|
"release": "npm version patch && npm run build && git push origin develop --tags",
|
|
"merge": "git checkout main && git merge develop && git push origin main && git checkout develop",
|
|
"ionic:build": "npm run build",
|
|
"ionic:serve": "npm run start"
|
|
},
|
|
"dependencies": {
|
|
"@capacitor-community/sqlite": "^7.0.0",
|
|
"@capacitor/android": "^7.0.0",
|
|
"@capacitor/app": "^7.0.0",
|
|
"@capacitor/browser": "^7.0.2",
|
|
"@capacitor/core": "^7.0.0",
|
|
"@capacitor/device": "^7.0.0",
|
|
"@capacitor/ios": "^7.0.0",
|
|
"@capacitor/local-notifications": "^7.0.0",
|
|
"@capacitor/network": "^7.0.1",
|
|
"@capacitor/preferences": "^7.0.0",
|
|
"@capacitor/push-notifications": "^7.0.0",
|
|
"@capacitor/status-bar": "^7.0.0",
|
|
"@capgo/capacitor-social-login": "^7.5.3",
|
|
"@dnd-kit/core": "^6.3.1",
|
|
"@dnd-kit/sortable": "^10.0.0",
|
|
"@dnd-kit/utilities": "^3.2.2",
|
|
"@emotion/react": "^11.11.3",
|
|
"@emotion/styled": "^11.11.0",
|
|
"@hello-pangea/dnd": "^18.0.1",
|
|
"@mui/icons-material": "^5.16.13",
|
|
"@mui/joy": "^5.0.0-beta.20",
|
|
"@mui/material": "^5.15.2",
|
|
"@openreplay/tracker": "^14.0.4",
|
|
"@revenuecat/purchases-capacitor": "^11.1.0",
|
|
"@revenuecat/purchases-capacitor-ui": "^11.1.0",
|
|
"@swc/core": "^1.12.5",
|
|
"@tanstack/react-query": "^5.17.0",
|
|
"aos": "^2.3.4",
|
|
"browser-image-compression": "^2.0.2",
|
|
"capacitor-plugin-safe-area": "^4.0.0",
|
|
"chrono-node": "^2.7.7",
|
|
"dotenv": "^16.4.5",
|
|
"esm": "^3.2.25",
|
|
"event-source-polyfill": "^1.0.31",
|
|
"fuse.js": "^7.0.0",
|
|
"js-cookie": "^3.0.5",
|
|
"moment": "^2.30.1",
|
|
"murmurhash": "^2.0.1",
|
|
"prop-types": "^15.8.1",
|
|
"qrcode": "^1.5.4",
|
|
"quill": "^2.0.3",
|
|
"quilljs-markdown": "^1.2.0",
|
|
"react": "^18.2.0",
|
|
"react-calendar": "^5.1.0",
|
|
"react-dom": "^18.2.0",
|
|
"react-easy-crop": "^5.4.2",
|
|
"react-router-dom": "^6.21.1",
|
|
"react-transition-group": "^4.4.5",
|
|
"reactjs-social-login": "^2.6.3",
|
|
"recharts": "^2.15.0",
|
|
"reusify": "^1.0.4",
|
|
"vite-plugin-pwa": "^0.20.0"
|
|
},
|
|
"devDependencies": {
|
|
"@capacitor/assets": "^3.0.5",
|
|
"@capacitor/cli": "^7.0.0",
|
|
"@tanstack/eslint-plugin-query": "^5.14.6",
|
|
"@types/react": "^18.2.43",
|
|
"@types/react-dom": "^18.2.17",
|
|
"@vite-pwa/assets-generator": "^0.2.4",
|
|
"@vitejs/plugin-react-swc": "^3.5.0",
|
|
"autoprefixer": "^10.4.16",
|
|
"eslint": "^8.56.0",
|
|
"eslint-config-prettier": "^9.1.0",
|
|
"eslint-plugin-prettier": "^5.1.2",
|
|
"eslint-plugin-react": "^7.33.2",
|
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
"eslint-plugin-react-refresh": "^0.4.5",
|
|
"eslint-plugin-simple-import-sort": "^10.0.0",
|
|
"eslint-plugin-sort-destructure-keys": "^1.5.0",
|
|
"eslint-plugin-sort-keys-fix": "^1.1.2",
|
|
"eslint-plugin-tailwindcss": "^3.13.1",
|
|
"husky": "^8.0.3",
|
|
"postcss": "^8.4.32",
|
|
"prettier": "^3.1.1",
|
|
"prettier-plugin-tailwindcss": "^0.5.10",
|
|
"tailwindcss": "^3.4.0",
|
|
"vite": "^5.2.13"
|
|
},
|
|
"optionalDependencies": {}
|
|
}
|