Recommended approach to initialise a custom js library
Added by Dries Mys 4 months ago
What is the recommended approach to initialize a custom library once for each Wt::WApplication
instance?
E.g.
class MyClass : public Wt::WContainerWidget
{
public:
MyClass ()
{
require("myLibrary.js");
doJavascript("initLibrary();"); // should be called once per Wapplication, not every time a MyClass object is created
}
}
Sub questions:
- Is it better to call
wApp->doJavascript("initLibrary();");
to perform a global initialization orWWidget::doJavascript("initLibrary();");
. AreWApplication::doJavascript
js calls being executed before or afterWWidget::doJavascript
? Or is the execution order of the js code undefined? - Wt often uses
WApplication::loadJavaScript
instead ofWApplication::require
to load js library. Should we use that approach too? Advantage is thatWApplication
has ajavaScriptLoaded
which is f.ex. used byWTextEdit::initTinyMCE
to perform the initialization only once for allWTextEdit
's of the same application, but a similar function doesn't exist to check whether the library is already loaded usingrequire
.
Replies (3)
RE: Recommended approach to initialise a custom js library - Added by Matthias Van Ceulebroeck 2 months ago
Hello Dries,
I apologize for the delayed reply, I have been very busy, and I am going through my backlog now.
So, require
is better used to add libraries that are required to make the application function, those will be added to a script
tag, at the top of your DOM tree.
When you use loadJavaScript
, this JS will be added to the JS preamble, which is executed just before the doJavaScript
calls, but after the require
scripts have been added.
Although there is no real convention, I would approach it like this:
- use
require
if and only if the library is required everywhere, and makes the site function (like e.g. jQuery, Angular, Vue, ...), this indicates that it is a "framework" - use
loadJavaScript
for all other libraries (e.g. a library only necessary for certain pages). These libraries can then be indeed added to the widget that contains the functionality, so it isn't always loaded (and would take up resources)
A doJavaScript
can then be called to initialize the library. If it is a require
library, this can be done in the application constructor (or whatever function performs the first load), if it is a loadJavaScript
, it can be called whenever the library is necessary (so often close to the loadJavaScript
).
Now, to ensure that it is only called once, I suppose a very simple approach would be something like:
doJavaScript("if (window.isMyLibraryInitialised !== true) { initLibrary(); window.isMyLibraryInitialised = true; };");
Does that answer the question?
Best,
Matthias
RE: Recommended approach to initialise a custom js library - Added by Dries Mys 2 months ago
Dear Matthias,
Thanks for the clear information.
If loadJavascript
is the/your preferred approach in certain cases, why isn't it documented?
In WApplication.h
, it is stated that this function is for internal use only. The type of the second argument, i.e. WJavaScriptPreamble
, seems to be an internal type too (in case of WT_DEBUG_JS is undefined).
Kind regards,
Dries
RE: Recommended approach to initialise a custom js library - Added by Matthias Van Ceulebroeck about 2 months ago
Hello Dries,
I do apologize, I always use Wt builds with nearly all possible flags, and debugging enabled. I sometimes forget what is public API and what is not. You can omit my remark about loadJavaScript
. require
is what we offer publicly, and functions as I said above.
Wt indeed uses loadJavaScript
often, due to subtle difference in the way this works. This doesn't produce a script
in the DOM, but allows the JS to be added to the response Wt server hands to the client. This enforces that the JS is only added once, and ensures that it is added right before the widgets can be used.
The remainder of my response is still valid. To recap:
- use
require
to include the right JS file - call
doJavaScript("if (window.isMyLibraryInitialised !== true) { initLibrary(); window.isMyLibraryInitialised = true; };");
to initialise the library.
Best,
Matthias