With SharePoint 2010, a massive amount of Java Script code was created to support a better UI, Ribbon, modal dialogs, notifications and much more. All these wonderful things require a lot of javascript behind the scenes which is finally managed by SOD framework. SOD provides abilities to load particular js scripts on demand, manage script dependencies, execute functions on particular loading events.
I was working recently on the project with active client side development and got a few insights about uninspected SOD behavior.
SP.SOD.registerSod overrides previous key-value pair
So, there is a good function “SP.SOD.registerSod” meant to register on demand script via Javascript. Internally, it creates an array to store key/url pair. However, it turned out that this function overrides the previous value. It means that the following code loads the same file three times. Once for the every location:
//Peace of the code inside the "news Web Part" SP.SOD.registerSod("jQuery", "path to CDN"); SP.SOD.executeFunc("jQuery", null, function () {} ); //Peace of the code inside the "Task View Web Part" SP.SOD.registerSod("jQuery", "path to style library"); SP.SOD.executeFunc("jQuery", null, function () {} ); //Peace of the code inside the "My Tasks web part" SP.SOD.registerSod("jQuery", "path to hive14"); SP.SOD.executeFunc("jQuery", null, function () {} );
And here is the registerSod function code explaining such a behavior:
function RegisterSod(key, url) { ULSxSy: ; key = NormalizeSodKey(key); var sod = new Sod(url); _v_dictSod[key] = sod; }
I would say, at some point this is really puzzling behavior. I do expect either exception or “no action” while I call RegisterSod with the same parameters.
Finally, if you want to make sure you utilize the same “shared” key across the SOD registration, you need manually check if a particular file has been already loaded. This code could help:
//Peace of the code inside the "news Web Part" if (LoadSodByKey('jQuery', null) == Sods.missing) RegisterSod('jQuery', 'path to CDN'); SP.SOD.executeFunc("jQuery", null, function () {} ); //Peace of the code inside the "Task View Web Part" if (LoadSodByKey('jQuery', null) == Sods.missing) RegisterSod('jQuery', 'path to style library'); SP.SOD.executeFunc("jQuery", null, function () {} ); //Peace of the code inside the "My Tasks web part" if (LoadSodByKey('jQuery', null) == Sods.missing) RegisterSod('jQuery', 'path to hive14'); SP.SOD.executeFunc("jQuery", null, function () {} );
Now we get only one jQuery file depending on which part of code is “first” on the page. The SOD key now reused across all the registrations.
SP.SOD.executeFunc and RegisterSodDep may not guarantee the right loading sequence
Well, somehow it turned out that following code could produce totally unpredictable outcome in terms of script loading sequence:
RegisterSod('jquery', 'path to jQuery'); RegisterSod('jquery.addin', "path to jQuery add in"); RegisterSod('myapp', 'path to my app'); RegisterSodDep('myapp', 'jquery'); RegisterSodDep('myapp', 'jquery.addin'); SP.SOD.executeFunc("myapp", null, function () { } ):
Surely, we expect the following file including sequence during the page loading:
- jquery
- jquery.addin
- myapp
However, depending on browser, NLB solution, firewall or something else (I haven’t really get it yet), the final sequence is sort of random. “myapp” could be the very first file or “jquery.addin” is loaded before “jquery”. Surely, it breaks all the solution.
To avoid that and check that loading sequence is okay, the following code could be used:
SP.SOD.executeFunc("jquery", null, function () { SP.SOD.executeFunc("myapp", null, function () { // actual code }); });
Surely, a helper function could be written to allow you define expected loading sequence.
Some links to get started
- MSDN: JavaScript Class Library (SharePoint 2010)
- Loading Script in SharePoint 2010 (Dallas Tester)
- SHAREPOINT SCRIPTS ON DEMAND (SP.SOD)
Conclusion
With the latest SharePoint 2013 release, it is a good thing to invest some time on client side development. However, SOD and client side object model aren’t documented very well. Depending on the particular case, requirement or event infrastructure, you may get some interesting or event uninspected behavior.
Also, described issue with loading sequence and SP.SOD.executeFunc/RegisterSodDep are still unknown to me. It would be nice if you could share any thought on that as I have absolutely no idea how to trace and address it in a better way.