Description
Background
The frontend needs a big refactor now.
web_src/index.js
is too big to add new code (or modify/debug).- code doesn't do what it should do, eg:
initVueApp
/initVueComponents
is quite misleading - Vue/fomantic/jQuery are mixed together, and we may need JSX Enable JSX support in frontend #15293
- no easy way to pass complex data structure from backend to frontend. eg: code like
var ActivityTopAuthors = {{Json .ActivityTopAuthors | SafeJS}};
is not a good idea. - difficult to shared data between modules, eg: how can different frontend modules get current issue index?
- the dependency and coupling are not clear, many frontend code work like
if ( $('.xxx').length == 0) return;
, we do not know what pages need this function, and these css class names may conflict. A little change may break something. - many events are attached to
document
, they may conflict. Add namespace to global click event #16833 - some problems should be resolved by framework: Prevent double click new issue/pull/comment button #16157 , Click buttons quickly in some forms will submit repeated/duplicated requests #17111
Guideline
- Every feature should be put in separated files/directories.
- HTML id/css-class-name should use
kebab-case
. - HTML id/css-class-name used by JavaScript top-level selector should be unique in whole project, and should contain feature related keywords.
- jQuery events across different features should use their own namespaces.
Plan
What frontend frameworks should be used?
- fomantic will stay as long as possible. And MVC is SEO friendly.
- jQuery is a part of fomantic.
- Vue is already used, so we can continue to use it, but we should upgrade it to Vue3 and do a refactor. Vue3 is handy to implement complex UI.
- JSX is nice to have and it works well with Vue3. But we do not choose it now (according to the discussions)
- ReactJS or other MVVM? I think it doesn't make big difference from Vue3 in this project, however if we drop Vue then we must migrate many components, not worthy.
I prefer fomantic + Vue3
How to pass backend data to frontend?
-
For simple data, it can be put into HTML
data-xxx
tag during template rendering -
For complex data like array/map, it can be put into
window.config.pageData.xxx
. We write some common code to renderpageData
into JSON automatically in base template:
<script>
window.config.pageData = {{ .PageData }}
</script>
Then backend work will be easy:
ctx.PageData["xxx"] = someMap
How to init frontend functions in a page?
We have two choices (I prefer keep and improve current mechanism)
Frontend functions depned on templates
It is the mechanism what we are using now. In index.js
it calls every init function, every init function checks whehter current page has some DOM elements. If current page has the matched DOM elements, then the feature will be loaded.
Pros:
- Simple, it doesn't change much with current mechanism
Cons:
- init functions can not have arguments
- There will be tens of init functions calls in
index.js
(maybe more than a hundred soon?)
Templates call frontend init functions
index.js
exports init functions. Templates render scripts in HTML like this:
<script>
window.config.ready(function($gitea)) {
$gitea.initIssueList();
$gitea.initUserList(extraData);
}
</script>
When the page is loaded, index.js
calls every function registered by window.config.ready
.
Pros:
- It saves init time because only necessary functions are called.
- Flexible, template code can do more things when JavaScript modules are ready.
Cons:
- Order/dependency problem?
- Some init functions can only be called once while others are called many times?
Other suggestions?
TODO
Refactor Steps
-
(DONE) Complete a formal frontend guideline document in
docs/content/doc/developers/frontend.md
. The guideline can come from this draft. -
(DONE) Split
web_src/index.js
into small files inweb_src/features/
. Add function calls toinitXxx
inindex.js
as before. This step can be done ASAP, and must be reviewed and approved quickly to prevent from further conflicts. Any new feature should be placed inweb_src/features/
later. -
(DONE) Introduce a common mechanism to pass backend data to frontend. eg:
window.config.pageData
. -
(keep current mechanism) Introduce or improve a common mechanism to call page related
init
functions. -
[FUTURE] Upgrade Vue from 2 to 3.
-
[DONE] If a change is made to legacy frontend code, the author should also follow the guideline to refactor related modules.
-
[FUTURE] Implement common and reusable code to resolve legacy frontend issues.
Activity