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

Check loading order in TYPO3 backend #57

Open
s2b opened this issue May 27, 2024 · 6 comments
Open

Check loading order in TYPO3 backend #57

s2b opened this issue May 27, 2024 · 6 comments

Comments

@s2b
Copy link
Owner

s2b commented May 27, 2024

There has been a report that JS loaded by vite in the TYPO3 backend doesn't have access to the global TYPO3 variable. This might be related to the loading order of JS files in the backend. It is probably not related to the extension, but should be investigated and potentially fixed in the TYPO3 core.

@mediaessenz
Copy link
Contributor

mediaessenz commented May 28, 2024

After some more investigation I found the cause of the global TYPO3 var loading problem:
I moved the reading of the global TYPO3 var to an extra file (Typo3Vars.js):

export const lang = Typo3Utilities.getTypo3LanguageLabels(TYPO3.lang ?? []); 

and imported the lang var inside my App.vue like so:

import { lang } from './Typo3Vars';

Then I created the App before the DOMContentLoaded event was fired:

import { createApp } from 'vue';
import App from './App.vue';

const app = createApp(App);

document.addEventListener('DOMContentLoaded', () => {
    app.mount('#app');
});

To fix it, I put the const lang = Typo3Utilities.getTypo3LanguageLabels(TYPO3.lang ?? []); direct into my App.vue code and changed the init code like so:

import { createApp } from 'vue';
import App from './App.vue';

document.addEventListener('DOMContentLoaded', () => {
    const app = createApp(App);
    app.mount('#app');
});

It could be, that only the last change (moving the createApp into the event callback) does the trick.

However, I think this issue can be closed from my point of view.

@mediaessenz
Copy link
Contributor

Meanwhile I found out that this issue is still not solved in safari and other webkit based browsers.
The global var TYPO3 is still not present when DOMContentLoaded is fired.

To solve this problem, I use a helper function waitForVariable which looks like this:

function waitForVariable(variableName, callback, checkInterval = 100) {
    const intervalId = setInterval(() => {
        if (typeof window[variableName] !== 'undefined') {
            clearInterval(intervalId);
            callback(window[variableName]);
        }
    }, checkInterval);
}

The initialization of my vue app looks like this now:

waitForVariable('TYPO3', () => {
    const app = createApp(App);
    app.mount('#app');
});

@mediaessenz
Copy link
Contributor

To reproduce this behavior this js can be helpfull:

document.addEventListener('DOMContentLoaded', () => {
    if (typeof TYPO3 === 'undefined') {
        console.log('global var TYPO3 is undefined!');
    }
});

@mediaessenz
Copy link
Contributor

mediaessenz commented May 29, 2024

After further research, I found the reason, why the DOMContentLoaded event is not working:
The JS containing the global TYPO3 vars coming from the TYPO3 "java-script-item-handler" is loaded async!
Since DOMContentLoaded is not waiting for async loaded stuff, the TYPO3 var not available at this time.

But even if I put the initialization code inside of a construction like this:

window.addEventListener('load', () => {
    if (typeof TYPO3 === 'undefined') {
        console.log('global var TYPO3 is undefined!');
    }
})

it only works half the time in safari and consorts!
I think, that the async code containing the global vars has to be handled by a TYPO3 script first to get into the window object.
Maybe this process fires an event itself if finished, but I can not find any documentation about it.

@mediaessenz
Copy link
Contributor

mediaessenz commented May 29, 2024

I think I found the script which loads the global TYPO3 vars:
vendor/typo3/cms-core/Resources/Public/JavaScript/java-script-item-processor.js
(Source https://github.com/TYPO3/typo3/blob/12.4/Build/Sources/TypeScript/core/java-script-item-processor.ts)

There is a "typo3:import-javascript-module" event dispatched somewhere in this code, but I'm not sure if it is usefull.

@mediaessenz
Copy link
Contributor

mediaessenz commented Jun 3, 2024

Since the TYPO3 core injects the global backend module js variables by loading it async I do not think that there is a way to fix it from your side.
In my opinion, it does not matter when the JS delivered by vite is loaded. It is always uncertain whether the global variables have already been loaded.

Helmut Hummel suggested at the vite slack channel, that this problem could be solved by typo3 by emitting an event when labels are populated, but I'm not sure if this is really error proof since in the end the browsers and its caching mechanism are involved ....

The only save way I see, is to go the "official" way and register the js as an es6 module over the typo3 api.
Unfortunately this would kills the main advantage of vite: hot module replacement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants