Skip to content

Commit

Permalink
fix.修复因计算时间引起的内存泄漏 (#186)
Browse files Browse the repository at this point in the history
* fix memory

* chore: 清理依赖,升级vue版本跟进性能改进,替换luxon为更小的dayjs

移除lodash,避免整个lodash库的函数都充斥在自动提示里
vue3.4在computed/watch上有性能改进,刚好也对得上书架的时钟跳动场景
替换luxon为dayjs,主要是前者屁事一堆但又没有特别的性能/体积改进
移除已经不在使用的vue-recaptcha-v3

* feat: 重构useToNow实现

* fix: 移除调试用代码

* chore: 添加preview方便验证prod代码

---------

Co-authored-by: bagolo6911 <[email protected]>
  • Loading branch information
wuyu8512 and bagolo6911 authored Jan 10, 2024
1 parent f4ec58b commit 5be996d
Show file tree
Hide file tree
Showing 21 changed files with 918 additions and 435 deletions.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20
1,037 changes: 753 additions & 284 deletions package-lock.json

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"build:android": "quasar build -m capacitor -T android",
"build:ios": "quasar build -m capacitor -T ios",
"build:electron": "quasar build -m electron",
"preview": "quasar build && serve -s dist/spa",
"lint": "eslint --ext .js,.ts,.vue ./",
"format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore",
"inspect": "quasar inspect > debug/webpack.config.txt"
Expand All @@ -26,39 +27,38 @@
"assert": "^2.0.0",
"blurhash": "^2.0.5",
"core-js": "^3.30.1",
"dayjs": "^1.11.10",
"dompurify": "^3.0.2",
"hash.js": "^1.1.7",
"immer": "^10.0.1",
"localforage": "^1.10.0",
"lodash-es": "^4.17.21",
"luxon": "^3.3.0",
"lodash.isequal": "^4.5.0",
"md-editor-v3": "^2.11.2",
"minimasonry": "^1.3.2",
"nanoid": "^4.0.2",
"nanoid": "^5.0.4",
"pako": "^2.1.0",
"pinia": "^2.0.35",
"pinia": "^2.1.7",
"process": "^0.11.10",
"quasar": "^2.11.10",
"sortablejs": "^1.15.0",
"turndown": "^7.1.2",
"util": "^0.12.5",
"v-viewer": "^3.0.11",
"vue": "^3.2.47",
"vue-recaptcha-v3": "^2.0.1",
"vue-router": "^4.1.6",
"vue": "^3.4.7",
"vue-router": "^4.2.5",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
"@iconify/json": "^2.2.56",
"@quasar/app-webpack": "^3.9.2",
"@types/dompurify": "^3.0.2",
"@types/luxon": "^3.3.0",
"@types/lodash.isequal": "^4.5.8",
"@types/node": "^18.16.1",
"@types/sortablejs": "^1.15.1",
"@types/turndown": "^5.0.1",
"@typescript-eslint/eslint-plugin": "^5.59.1",
"@typescript-eslint/parser": "^5.59.1",
"@vue/compiler-sfc": "^3.2.47",
"@vue/compiler-sfc": "^3.4.7",
"dotenv": "^16.0.3",
"electron": "^22.3.25",
"electron-packager": "^17.1.1",
Expand All @@ -67,6 +67,7 @@
"eslint-plugin-vue": "^9.11.0",
"npm-check-updates": "^16.10.9",
"prettier": "^2.8.8",
"serve": "^14.2.1",
"unplugin-auto-import": "^0.15.3",
"unplugin-icons": "^0.16.1",
"unplugin-vue-components": "^0.24.1",
Expand All @@ -77,8 +78,7 @@
"supports es6-module"
],
"engines": {
"node": ">= 16",
"npm": ">= 6.13.4",
"yarn": ">= 1.21.1"
}
"node": ">= 20"
},
"packageManager": "[email protected]+sha1.b26d744770782a845881d278d6d53d14d9ade111"
}
1 change: 1 addition & 0 deletions src/boot/app.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import '../global'
import { boot } from 'quasar/wrappers'

let app = null
Expand Down
10 changes: 2 additions & 8 deletions src/components/BookCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

<script lang="ts" setup>
import { computed, ref } from 'vue'
import { useToNow } from 'src/composition/useToNow'
import { useToNowRef } from 'src/composition/useToNowRef'
import { BookInList } from 'src/services/book/types'
import { useQuasar } from 'quasar'
import BlurHash from 'src/components/BlurHash.vue'
Expand All @@ -57,13 +57,7 @@ const { generalSetting } = settingStore // 引入setting用于控制图片自定
const $q = useQuasar()
const props = defineProps<{ book: BookInList }>()
const cover = computed(() => props.book.Cover)
const updateTime = computed(() => {
if (+props.book.LastUpdateTime <= 0) {
return ''
}
return useToNow(computed(() => props.book.LastUpdateTime)).value
})
const updateTime = useToNowRef(() => props.book.LastUpdateTime)
const visible = ref(false)
function onIntersection(entry: IntersectionObserverEntry) {
visible.value = entry.isIntersecting
Expand Down
5 changes: 2 additions & 3 deletions src/components/Comment.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
</q-item-label>
<q-item-label caption>
<div class="row flex-align-center q-gutter-x-md">
<div>{{ toNow(comment.Commentaries[`${item.Id}`].CreatedTime, baseTime) }}</div>
<div>{{ toNow(comment.Commentaries[`${item.Id}`].CreatedTime) }}</div>
<div>
<q-btn flat dense @click="showReply(item.Id)">回复</q-btn>
<q-btn flat dense v-if="comment.Commentaries[`${item.Id}`].CanEdit" @click="_delete(item.Id)">
Expand Down Expand Up @@ -108,7 +108,7 @@
</q-item-label>
<q-item-label caption>
<div class="row flex-align-center q-gutter-x-md">
<div>{{ toNow(comment.Commentaries[`${replyId}`].CreatedTime, baseTime) }}</div>
<div>{{ toNow(comment.Commentaries[`${replyId}`].CreatedTime) }}</div>
<div>
<q-btn flat dense @click="showReply(item.Id, replyId)">回复</q-btn>
<q-btn
Expand Down Expand Up @@ -191,7 +191,6 @@
<script lang="ts" setup>
import { postComment, replyComment, getComment, deleteComment } from 'src/services/comment'
import { CommentType, GetComment } from 'src/services/comment/types'
import { baseTime } from 'src/composition/useToNow'
import { toNow } from 'src/utils/time'
import { useAppStore } from 'stores/app'
import { computed, ref, watch } from 'vue'
Expand Down
24 changes: 12 additions & 12 deletions src/components/app/Container/AuthenticationGuard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@
import { defineComponent } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { unAuthenticationNotify } from 'src/utils/biz/unAuthenticationNotify'
import { useQuasar } from 'quasar'
/** 监听鉴权失败消息 */
export default defineComponent(() => {
const route = useRoute()
const router = useRouter()
const $q = useQuasar()
export default defineComponent({
setup(props, ctx) {
const route = useRoute()
const router = useRouter()
unAuthenticationNotify.useSubscribe(() => {
// 必须要到这里才解构取值,不然解构后就不reactive了
const { name, fullPath } = route
unAuthenticationNotify.useSubscribe(() => {
// 必须要到这里才解构取值,不然解构后就不reactive了
const { name, fullPath } = route
if (name !== 'Login') {
router.replace({ name: 'Login', params: { authRedirect: 1 }, query: { from: encodeURIComponent(fullPath) } })
}
})
if (name !== 'Login') {
router.replace({ name: 'Login', params: { authRedirect: 1 }, query: { from: encodeURIComponent(fullPath) } })
}
})
}
})
</script>
36 changes: 0 additions & 36 deletions src/composition/useTickSource.ts

This file was deleted.

39 changes: 0 additions & 39 deletions src/composition/useToNow.ts

This file was deleted.

81 changes: 81 additions & 0 deletions src/composition/useToNowRef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import dayjs, { Dayjs } from 'dayjs'
import { type MaybeRefOrGetter, toValue } from 'vue'
import { parseTime, toNow } from 'src/utils/time'

/**
* 返回一个定时刷新的 'xx天前' 文案
*
* @example
* ```ts
* const book = ref<{ LastUpdateTime: Date }>({ LastUpdateTime: new Date() })
* onMounted(async () => {
* Promise.resolve().then(() => {
* book.value.LastUpdateTime = new Date()
* })
* })
*
* const lastUpdateTimeSourceRef = computed(() => book.value.LastUpdateTime)
* const lastUpdateTime = useToNow(lastUpdateTimeSourceRef)
*
* // 这样合起来写也行↓
* // const lastUpdateTime = useToNow(() => book.value.LastUpdateTime)
*
* return { lastUpdateTime }
* ```
*/
export function useToNowRef(dateGetter: MaybeRefOrGetter<Date | Dayjs | undefined | null>): ComputedRef<string> {
const dateRef = computed<Dayjs | null>(() => {
const dateVal = toValue(dateGetter)
if (!dateVal) {
return null
}

return parseTime(dateVal)
})

const nowRef = shallowRef(dayjs())
// 刷新nowRef
watchEffect((onClean) => {
const date = unref(dateRef)
const now = unref(nowRef)

// 不是同一天的就不更新了
if (!date || !date.isSame(now, 'day')) {
return
}

// 秒级别的差异,每半分钟刷新一次
// => "x秒前"
if (date.diff(now, 'second') < 60) {
const timeout = setTimeout(() => {
nowRef.value = dayjs()
}, 1_000 * 1)

onClean(() => clearTimeout(timeout))
return
}

// 分钟级别的差异,每分钟刷新一次
// => "x分钟前"
if (date.diff(now, 'minute') < 60) {
const timeout = setTimeout(() => {
nowRef.value = dayjs()
}, 1_000 * 60)
onClean(() => clearTimeout(timeout))
return
}

// 小时级别的差异,每半小时刷新一次
// => "x小时前"
const timeout = setTimeout(() => {
nowRef.value = dayjs()
}, 1_000 * 60 * 60)
onClean(() => clearTimeout(timeout))
return
})

return computed(() => {
// console.log('re-calc toNow', dateRef.value.format(), nowRef.value.format())
return dateRef.value ? toNow(dateRef.value, { now: nowRef.value }) : null
})
}
14 changes: 14 additions & 0 deletions src/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 全局初始化内容
import dayjs from 'dayjs'
import zh from 'dayjs/locale/zh'

import relativeTime from 'dayjs/plugin/relativeTime'
import updateLocale from 'dayjs/plugin/updateLocale'
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'

dayjs.extend(relativeTime)
dayjs.extend(isSameOrAfter)
dayjs.extend(updateLocale)

dayjs.locale(zh)
dayjs.updateLocale(zh.name, { relativeTime: { ...zh.relativeTime, s: '%d秒' } })
1 change: 1 addition & 0 deletions src/services/book/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export interface BookInList {
Id: number
Cover: string
Placeholder?: string
// TODO: 走了二进制解码后自动转Date对象的特性丢失了,就是一个ISO 8601的日期
LastUpdateTime: Date
UserName: string
Title: string
Expand Down
2 changes: 1 addition & 1 deletion src/stores/shelf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ShelfItem, ShelfBookItem, ShelfFolderItem, ShelfItemTypeEnum, SHELF_STR
import { shelfDB, shelfStructVerDB } from 'src/utils/storage/db'
import { toRaw } from 'vue'
import { produce } from 'immer'
import { isEqual } from 'lodash-es'
import isEqual from 'lodash.isequal'
import { Notify } from 'quasar'
import { nanoid } from 'nanoid'
import { getBookShelfBinary, saveBookShelf } from 'src/services/user'
Expand Down
Loading

0 comments on commit 5be996d

Please sign in to comment.