[Proposal] Optimize the index.js #10429

Closed
opened 2025-11-02 09:07:08 -06:00 by GiteaMirror · 11 comments
Owner

Originally created by @wxiaoguang on GitHub (Mar 14, 2023).

Feature Description

This is an idea for public (feel free to take it or work on it).

Gitea's index.js logic becomes more and more complex. On my MacBook Pro, almost every page loading says:

[Violation] 'setTimeout' handler took 99ms
[Violation] 'setTimeout' handler took 148ms

I think the setTimeout is actually the $(document).ready(() => {}) call in index.js, it's too complex. If that $(document).ready() is commented out, there is no warning anymore.

So, I think in the future, it's better to avoid making the index.js do too much slow init calls, instead, many calls should be optimized (by various approaches)

Some clues

  • initHeatmap takes around 100ms (update: vue3-calendar-heatmap 2.0.2, the time decreases from 100ms to 50ms)
  • initGlobalCommon is also slow, if there are many elements
  • initRepoTopicBar seems unnecessarily slow
initHeatmap() 103.100 (update: vue3-calendar-heatmap 2.0.2, the time decreases from 100ms to 50ms)
initGlobalCommon() 20.800
initDashboardRepoList() 12.400
initGlobalTooltips() 8.900
initGlobalFormDirtyLeaveConfirm() 1.400
initStopwatch() 1.100
initMarkupContent() 1.000
initRepoTopicBar() 0.600
attachTribute(document.querySelectorAll('#content, .emoji-input')) 0.400
initNotificationCount() 0.400
initMarkupAnchors() 0.300
initServiceWorker() 0.300
initRepoIssueList() 0.300
initGlobalCommon() 33.900
initRepoTopicBar() 32.300
initRepository() 10.600
initGlobalTooltips() 8.200
initGlobalFormDirtyLeaveConfirm() 1.600
initStopwatch() 0.700
initMarkupContent() 0.600
initMarkupAnchors() 0.300
attachTribute(document.querySelectorAll('#content, .emoji-input')) 0.300
Originally created by @wxiaoguang on GitHub (Mar 14, 2023). ### Feature Description This is an idea for public (feel free to take it or work on it). Gitea's `index.js` logic becomes more and more complex. On my MacBook Pro, almost every page loading says: ``` [Violation] 'setTimeout' handler took 99ms [Violation] 'setTimeout' handler took 148ms ``` I think the `setTimeout` is actually the `$(document).ready(() => {})` call in `index.js`, it's too complex. If that `$(document).ready()` is commented out, there is no warning anymore. So, I think in the future, it's better to avoid making the `index.js` do too much slow `init` calls, instead, many calls should be optimized (by various approaches) ### Some clues * `initHeatmap` takes around 100ms (update: vue3-calendar-heatmap 2.0.2, the time decreases from 100ms to 50ms) * `initGlobalCommon` is also slow, if there are many elements * `initRepoTopicBar` seems unnecessarily slow ``` initHeatmap() 103.100 (update: vue3-calendar-heatmap 2.0.2, the time decreases from 100ms to 50ms) initGlobalCommon() 20.800 initDashboardRepoList() 12.400 initGlobalTooltips() 8.900 initGlobalFormDirtyLeaveConfirm() 1.400 initStopwatch() 1.100 initMarkupContent() 1.000 initRepoTopicBar() 0.600 attachTribute(document.querySelectorAll('#content, .emoji-input')) 0.400 initNotificationCount() 0.400 initMarkupAnchors() 0.300 initServiceWorker() 0.300 initRepoIssueList() 0.300 ``` ``` initGlobalCommon() 33.900 initRepoTopicBar() 32.300 initRepository() 10.600 initGlobalTooltips() 8.200 initGlobalFormDirtyLeaveConfirm() 1.600 initStopwatch() 0.700 initMarkupContent() 0.600 initMarkupAnchors() 0.300 attachTribute(document.querySelectorAll('#content, .emoji-input')) 0.300 ```
GiteaMirror added the type/proposaltype/feature labels 2025-11-02 09:07:08 -06:00
Author
Owner

@silverwind commented on GitHub (Mar 14, 2023):

$(document).ready(() => {})

Can probably replace ready with DOMContentLoaded, to lessen our jQuery dependency. Oh, and the syntax in use is apparently deprecated as of jQuery 3.0.

initHeatmap takes around 100ms.

Is this true for pages without a heatmap as well? If so, we should definitely add early exit to that function. Generally it should be noted that heatmap data generation is very inefficient on server-side too.

@silverwind commented on GitHub (Mar 14, 2023): > $(document).ready(() => {}) Can probably replace [ready](https://api.jquery.com/ready/) with [DOMContentLoaded](https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event), to lessen our jQuery dependency. Oh, and the syntax in use is apparently deprecated as of jQuery 3.0. > initHeatmap takes around 100ms. Is this true for pages without a heatmap as well? If so, we should definitely add early exit to that function. Generally it should be noted that heatmap data generation is very inefficient [on server-side too](https://github.com/go-gitea/gitea/issues/21045).
Author
Owner

@wxiaoguang commented on GitHub (Mar 14, 2023):

$(document).ready(() => {})

Can probably replace ready with DOMContentLoaded, to lessen our jQuery dependency. Oh, and the syntax in use is apparently deprecated as of jQuery 3.0.

I agree we can refactor, but It's not related to this problem. The problem is many init functions are really slow.

initHeatmap takes around 100ms.

Is this true for pages without a heatmap as well? If so, we should definitely add early exit to that function. Generally it should be noted that heatmap data generation is very inefficient on server-side too.

No initHeatmap, no 100ms. With initHeatmap, then 100ms.

Other init functions could also be slow, eg: initGlobalCommon and initRepoTopicBar could also take 30ms

You could take a try.

  const fns = [];

  let last = performance.now();
  function record(s) {
    const now = performance.now();
    fns.push({fn:s, t: now-last});
    last = now;
  }

  initGlobalCommon();record(`initGlobalCommon()`);
...
  initUserSettings();record(`initUserSettings()`);
  initViewedCheckboxListenerFor();record(`initViewedCheckboxListenerFor()`);

  fns.sort((a, b) => b.t - a.t).forEach((f) => console.log(f.fn, f.t.toFixed(3)));
@wxiaoguang commented on GitHub (Mar 14, 2023): > > $(document).ready(() => {}) > > Can probably replace [ready](https://api.jquery.com/ready/) with [DOMContentLoaded](https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event), to lessen our jQuery dependency. Oh, and the syntax in use is apparently deprecated as of jQuery 3.0. I agree we can refactor, but It's not related to this problem. The problem is many `init` functions are really slow. > > initHeatmap takes around 100ms. > > Is this true for pages without a heatmap as well? If so, we should definitely add early exit to that function. Generally it should be noted that heatmap data generation is very inefficient [on server-side too](https://github.com/go-gitea/gitea/issues/21045). No `initHeatmap`, no 100ms. With `initHeatmap`, then 100ms. Other `init` functions could also be slow, eg: initGlobalCommon and initRepoTopicBar could also take 30ms You could take a try. ```js const fns = []; let last = performance.now(); function record(s) { const now = performance.now(); fns.push({fn:s, t: now-last}); last = now; } initGlobalCommon();record(`initGlobalCommon()`); ... initUserSettings();record(`initUserSettings()`); initViewedCheckboxListenerFor();record(`initViewedCheckboxListenerFor()`); fns.sort((a, b) => b.t - a.t).forEach((f) => console.log(f.fn, f.t.toFixed(3))); ```
Author
Owner

@lunny commented on GitHub (Mar 14, 2023):

Can we split index.js, at least we can have an admin.js which will only include admin related js

@lunny commented on GitHub (Mar 14, 2023): Can we split index.js, at least we can have an admin.js which will only include admin related js
Author
Owner

@wxiaoguang commented on GitHub (Mar 14, 2023):

Can we split index.js, at least we can have an admin.js which will only include admin related js

At the moment, initAdmin related functions only cost 0~0.1ms. See my test code above.

Find the root problem and focus on the root problem.

@wxiaoguang commented on GitHub (Mar 14, 2023): > Can we split index.js, at least we can have an admin.js which will only include admin related js At the moment, `initAdmin` related functions only cost 0~0.1ms. See my test code above. Find the root problem and focus on the root problem.
Author
Owner

@HesterG commented on GitHub (Mar 15, 2023):

Which measurement tool did you use?

@HesterG commented on GitHub (Mar 15, 2023): Which measurement tool did you use?
Author
Owner

@wxiaoguang commented on GitHub (Mar 15, 2023):

Which measurement tool did you use?

Home-made JS in https://github.com/go-gitea/gitea/issues/23461#issuecomment-1468980296


I push the test code to https://github.com/wxiaoguang/gitea/tree/test-js-slow

@wxiaoguang commented on GitHub (Mar 15, 2023): > Which measurement tool did you use? Home-made JS in https://github.com/go-gitea/gitea/issues/23461#issuecomment-1468980296 ---- I push the test code to https://github.com/wxiaoguang/gitea/tree/test-js-slow
Author
Owner

@HesterG commented on GitHub (Mar 15, 2023):

截屏2023-03-15 16 36 17 For Heatmap, looks like it is depending on tippy, which takes the half of the init time.
@HesterG commented on GitHub (Mar 15, 2023): <img width="429" alt="截屏2023-03-15 16 36 17" src="https://user-images.githubusercontent.com/17645053/225252747-dcd5ba7e-1f6b-487f-bc38-a3b108a26e8b.png"> For Heatmap, looks like it is depending on tippy, which takes the half of the init time.
Author
Owner

@silverwind commented on GitHub (Mar 15, 2023):

Note this is a separate, second instance of tippy.js because https://github.com/razorness/vue3-calendar-heatmap has its own dependency on it. So essentially we init tippy twice because of it. I guess a better solution may be to incorporate that module into first-party code.

@silverwind commented on GitHub (Mar 15, 2023): Note this is a separate, second instance of tippy.js because https://github.com/razorness/vue3-calendar-heatmap has its own dependency on it. So essentially we init tippy twice because of it. I guess a better solution may be to incorporate that module into first-party code.
Author
Owner

@silverwind commented on GitHub (Mar 16, 2023):

Looking through that module, it seem to create a tippy instance for each day, so 365 tippy instances. I think this is reason why it's slow to init. A better approach may be to just use title attribute or to only create instances on-demand on mouseenter/click event.

@silverwind commented on GitHub (Mar 16, 2023): Looking through [that module](https://github.com/razorness/vue3-calendar-heatmap/blob/2eb2ce942c0f14c14fc2c11a1d06ecd029affe22/src/components/CalendarHeatmap.vue#L194), it seem to create a tippy instance for each day, so 365 tippy instances. I think this is reason why it's slow to init. A better approach may be to just use `title` attribute or to only create instances on-demand on mouseenter/click event.
Author
Owner

@wxiaoguang commented on GitHub (Mar 20, 2023):

vue3-calendar-heatmap has released 2.0.2 with lazy tippy init.

According to my test, the initHeatmap time decreases from 100ms to 50ms. So I put the upgrading in #23574 together.

@wxiaoguang commented on GitHub (Mar 20, 2023): vue3-calendar-heatmap has released 2.0.2 with lazy tippy init. According to my test, the `initHeatmap` time decreases from 100ms to 50ms. So I put the upgrading in #23574 together.
Author
Owner

@wxiaoguang commented on GitHub (Jul 12, 2023):

Out-dated and there is no planned work in near future.

@wxiaoguang commented on GitHub (Jul 12, 2023): Out-dated and there is no planned work in near future.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/gitea#10429