Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(frontend): reduce api requests for non-logged-in enviroment #15001

Merged
merged 4 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/663)
- Enhance: サイドバーを簡単に展開・折りたたみできるように ( #14981 )
- Enhance: リノートメニューに「リノートの詳細」を追加
- Enhance: 非ログイン状態でMisskeyを開いた際のパフォーマンスを向上
- Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
- Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
Expand Down
14 changes: 13 additions & 1 deletion packages/backend/src/server/web/ClientServerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ export class ClientServerService {
}
});

//#region SSR (for crawlers)
//#region SSR
// User
fastify.get<{ Params: { user: string; sub?: string; } }>('/@:user/:sub?', async (request, reply) => {
const { username, host } = Acct.parse(request.params.user);
Expand All @@ -584,11 +584,17 @@ export class ClientServerService {
reply.header('X-Robots-Tag', 'noimageai');
reply.header('X-Robots-Tag', 'noai');
}

const _user = await this.userEntityService.pack(user);

return await reply.view('user', {
user, profile, me,
avatarUrl: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user),
sub: request.params.sub,
...await this.generateCommonPugData(this.meta),
clientCtx: htmlSafeJsonStringify({
user: _user,
}),
});
} else {
// リモートユーザーなので
Expand Down Expand Up @@ -641,6 +647,9 @@ export class ClientServerService {
// TODO: Let locale changeable by instance setting
summary: getNoteSummary(_note),
...await this.generateCommonPugData(this.meta),
clientCtx: htmlSafeJsonStringify({
note: _note,
}),
});
} else {
return await renderBase(reply);
Expand Down Expand Up @@ -729,6 +738,9 @@ export class ClientServerService {
profile,
avatarUrl: _clip.user.avatarUrl,
...await this.generateCommonPugData(this.meta),
clientCtx: htmlSafeJsonStringify({
clip: _clip,
}),
});
} else {
return await renderBase(reply);
Expand Down
3 changes: 3 additions & 0 deletions packages/backend/src/server/web/views/base.pug
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ html
script(type='application/json' id='misskey_meta' data-generated-at=now)
!= metaJson

script(type='application/json' id='misskey_clientCtx' data-generated-at=now)
!= clientCtx

script
include ../boot.js

Expand Down
14 changes: 11 additions & 3 deletions packages/frontend/src/pages/clip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,28 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { computed, watch, provide, ref } from 'vue';
import * as Misskey from 'misskey-js';
import { url } from '@@/js/config.js';
import type { MenuItem } from '@/types/menu.js';
import MkNotes from '@/components/MkNotes.vue';
import { $i } from '@/account.js';
import { i18n } from '@/i18n.js';
import * as os from '@/os.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import { url } from '@@/js/config.js';
import MkButton from '@/components/MkButton.vue';
import { clipsCache } from '@/cache.js';
import { isSupportShare } from '@/scripts/navigator.js';
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
import { genEmbedCode } from '@/scripts/get-embed-code.js';
import type { MenuItem } from '@/types/menu.js';
import { getServerContext } from '@/server-context.js';

const CTX_CLIP = getServerContext('clip');

const props = defineProps<{
clipId: string,
}>();

const clip = ref<Misskey.entities.Clip | null>(null);
const clip = ref<Misskey.entities.Clip | null>(CTX_CLIP);
const favorited = ref(false);
const pagination = {
endpoint: 'clips/notes' as const,
Expand All @@ -64,6 +67,11 @@ const pagination = {
const isOwned = computed<boolean | null>(() => $i && clip.value && ($i.id === clip.value.userId));

watch(() => props.clipId, async () => {
if (CTX_CLIP && CTX_CLIP.id === props.clipId) {
clip.value = CTX_CLIP;
return;
}

clip.value = await misskeyApi('clips/show', {
clipId: props.clipId,
});
Expand Down
11 changes: 10 additions & 1 deletion packages/frontend/src/pages/note.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,16 @@ import { dateString } from '@/filters/date.js';
import MkClipPreview from '@/components/MkClipPreview.vue';
import { defaultStore } from '@/store.js';
import { pleaseLogin } from '@/scripts/please-login.js';
import { getServerContext } from '@/server-context.js';

const CTX_NOTE = getServerContext('note');

const props = defineProps<{
noteId: string;
initialTab?: string;
}>();

const note = ref<null | Misskey.entities.Note>();
const note = ref<null | Misskey.entities.Note>(CTX_NOTE);
const clips = ref<Misskey.entities.Clip[]>();
const showPrev = ref<'user' | 'channel' | false>(false);
const showNext = ref<'user' | 'channel' | false>(false);
Expand Down Expand Up @@ -116,6 +119,12 @@ function fetchNote() {
showPrev.value = false;
showNext.value = false;
note.value = null;

if (CTX_NOTE && CTX_NOTE.id === props.noteId) {
note.value = CTX_NOTE;
return;
}

misskeyApi('notes/show', {
noteId: props.noteId,
}).then(res => {
Expand Down
18 changes: 16 additions & 2 deletions packages/frontend/src/pages/user/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
import { i18n } from '@/i18n.js';
import { $i } from '@/account.js';
import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
import { getServerContext } from '@/server-context.js';
const XHome = defineAsyncComponent(() => import('./home.vue'));
const XTimeline = defineAsyncComponent(() => import('./index.timeline.vue'));
Expand All @@ -52,6 +53,8 @@ const XFlashs = defineAsyncComponent(() => import('./flashs.vue'));
const XGallery = defineAsyncComponent(() => import('./gallery.vue'));
const XRaw = defineAsyncComponent(() => import('./raw.vue'));
const CTX_USER = getServerContext('user');
const props = withDefaults(defineProps<{
acct: string;
page?: string;
Expand All @@ -61,13 +64,24 @@ const props = withDefaults(defineProps<{
const tab = ref(props.page);
const user = ref<null | Misskey.entities.UserDetailed>(null);
const user = ref<null | Misskey.entities.UserDetailed>(CTX_USER);
const error = ref<any>(null);
function fetchUser(): void {
if (props.acct == null) return;
const { username, host } = Misskey.acct.parse(props.acct);
if (CTX_USER && CTX_USER.username === username && CTX_USER.host === host) {
user.value = CTX_USER;
return;
}
user.value = null;
misskeyApi('users/show', Misskey.acct.parse(props.acct)).then(u => {
misskeyApi('users/show', {
username,
host,
}).then(u => {
user.value = u;
}).catch(err => {
error.value = err;
Expand Down
23 changes: 23 additions & 0 deletions packages/frontend/src/server-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import * as Misskey from 'misskey-js';
import { $i } from '@/account.js';

const providedContextEl = document.getElementById('misskey_clientCtx');

export type ServerContext = {
clip?: Misskey.entities.Clip;
note?: Misskey.entities.Note;
user?: Misskey.entities.UserLite;
} | null;

export const serverContext: ServerContext = (providedContextEl && providedContextEl.textContent) ? JSON.parse(providedContextEl.textContent) : null;

export function getServerContext<K extends keyof NonNullable<ServerContext>>(entity: K): Required<Pick<NonNullable<ServerContext>, K>> | null {
// contextは非ログイン状態の情報しかないためログイン時は利用できない
if ($i) return null;

return serverContext ? (serverContext[entity] ?? null) : null;
}
Loading