Quantcast
Channel: SharePoint Development Lab by @avishnyakov » js
Viewing all articles
Browse latest Browse all 13

Uninspected SOD behavior in SharePoint 2010

$
0
0

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

Script registration is a pain.
There were a few “client side” web parts in the project and a little jQuery magic. As some parts of the project were “legacy”, it turned out that we had several jQuery file registrations – at the site collection level from CDN, inside several web parts from pointing to “Style Library/3rd part scripts” folder, inside several app pages pointing to hive14 folder. Unfortunately, there wasn’t any chance to improve that. So, we decided to go with SOD features and “whoever registers first, ones wins” strategy. It means, jQuery file was registered with SP.SOD.regiserSod() function with the same key, but different file location and the very first registration ruled the game.

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.

Js registration challanges
Also, it seems that to share some reusable JavaScript libraries such as KnockoutJs, underscore or something else across your solutions is not a big deal. Name convention, SOD, consolidated JavaScript files registration solve the problem. However, it is totally puzzling how to make sure that all of those files haven’t been registered by ISV’s solution or any other, for example, open source solution in your farm/site/page.

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.

Browser magic in action
I’m not quite sure why it happens, but it seems people report sort of same behavior across different forums and blog posts. The reason and an appropriate solution are still unknown to me.

Some links to get started

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.


Viewing all articles
Browse latest Browse all 13

Trending Articles