I am writing a networked application that needs to load and unload self-contained (approved) code dynamically. The main goal, in short, is to load these scripts for short amounts of time and avoid global name collisions or contaminating the global scope, and being able to unload them and have everything be garbage collected.
The initial problem was that any global variables will persist after unload if I simply add and remove a script in the DOM.
My temporary solution was to wrap all of my individual dynamic code section files in:
systemArray.push((function() {
// local-global scope
function main() {
// do something
}
return main;
}()));
...
...
// some external code calls:
systemArray[sandboxIdx](); // max of 10 sandboxes at once, need to unload old sandboxes that have been exited
and simply pop the array upon unload to let the garbage collector do its work. However, this doesn't really allow for splitting the sub-program into multiple files, and it seems a little error-prone unless I can do some preprocessing on the server-side to create a concatenated file.
Then I looked into ES6 modules. These seem to be fine and avoid name collisions, but it's unclear to me whether modules can ever be unloaded, which is the key thing that I need to do without changing webpages or refreshing.
Firstly, is there a way to unload a module explicitly at runtime? The main, non-unloading part of the application only needs to import one function, but the scripts themselves may have a lot of code.
Secondly, if the answer is yes, do any modules that the unloaded module load also get unloaded? Are global variables within the modules correctly garbage collected? If the answer is no, what other options are there?
Related
Is there a way to remove angular.module('SomeModule') dynamically?
This because I need to load and unload modules from a page in a tab-container.
This is based on Scott Moss' concept of where every single component is seen as a separate app on Frontendmasters.com.
I can get the module object by
angular.module(name)
Which returns an object respectively, but there I miss a clear way of clearing the references to this object. Has anyone solved something like this yet?
Template: http://plnkr.co/edit/8hK3lYjE7f06XtdHgNwL?p=preview
It sounds like you might be trying to optimize for something that doesn't exist.
First, there does not appear to be any documented way to remove modules. The reasons seem to be covered in the docs. In there you will find this statement (emphasis mine):
The modules can be loaded in any order (or even in parallel) because modules delay execution.
In that sentence it doesn't specify for how long the delay is but later we get this snippet (again, emphasis mine):
Because modules do nothing at load time they can be loaded into the VM in any order and thus script loaders can take advantage of this property and parallelize the loading process.
Put together, it sounds as if even with multiple of multiple modules, you won't notice a load on your site because the module will only be loaded when it is needed therefore removing modules is not a process that should ever need to be done.
I have a page that could contain a different inner page at any specific time.
Each inner page needs a specific js file, that is being loaded dynamically using the Headjs.
To avoid collisions (of methods and object names), I would like to unload the old js file before loading a new one.
Does anyone know how to do it, or if it is even possible? Thanks!
No. Theoretically there's nothing like "unload" javascript file. Once its loaded its there all the time.
But there might be other tricks to avoid "collision", mainly clean code. some examples for your case would be
1- Usage of namespaces
2- avoid global variables
3- define everything within a scope and understand scopes
4- Use understandable descriptive variable names, avoid variables named s,i,j, etc.. unless you are used to that and know what're doing. Also be aware since javascript files are loaded when a page is requested, so it causes extra traffic to use huge large names for variables and classes.
Lets say you have functions with same name but live in different scopes/namespace
Example:
var myclass;
if (something) myclass = Obj1;
else if (somethingelse) myclass = Obj2;
myclass.func();
so here you go, two functions with the same name, but live in different classes.and so you can switch between different implementations
Hope this helps
The custom javascript of my site is namespaced, combined and minified resulting in a 12kb file of custom js. This is code for the entire site, and usually after pageload has been triggered a greater portion of it doesn't have to sit in memory.
My question:
Does a heap of custom script that only gets executed once or not at all affect a users performance? Especially if the user has multiple tabs open
I was thinking of setting mynamespace = null but I wouldn't know if this actually improves the users browsers performance.
Nulling it out should trigger the garbage collector to free up some memory. Unless the system had enough stuff in memory that it was being swapped out to the disk, the user wouldn't notice a difference.
You don't have to unset JavaScript objects manually.
Because JavaScript can do "Garbage Collection"
Edit:
You can do
delete window.mynamespace;
And the "mynamespace" will be deleted
I am currently making a sort of web app and part of it works by dynamically loading and adding js scripts to the page. For this I am using JQuery's $.getScript() method which loads it in.
I have it set as cached.
With my program if a script already exists it is loaded again anyway, from what appears to be cache. What I am wondering though is how much would this effect the site and performance. Does a newly loaded script that has the same src as an existing one overwrite the previous one or is the new one added alongside the old one?
Further more as my site is an AJAX site its possible for several scripts from different pages to eventually be loaded up over time. Is there any browser restrictions on how many scripts one can have loaded?
It will affect site performance. Even if your script is cached on the client with expiration set the browser still needs to parse and execute newly included script. More than that, there's a very good chance you will run into javascript errors because you scripts will override variables already set by previous version. JavaScript parsing and executing is still a blocking operation in all browsers, so while your file is being processed your UI will lock up.
To answer second part of the question, as far as I know there's no limit of number of javascript files on a given page. I've seen pages with over 200 javascripts that didn't throw any exceptions.
I think Ilya has provided some great points to consider, and I think that answers your specific question. If what you're trying to accomplish, however, is rerunning a $(document).ready() handler, you could do:
(function(){
var myreadyfunction = function(){
$('#affected').toggleClass('blue');
};
$(document).ready(myreadyfunction);
$(document).ready(function(){
$('button').click(myreadyfunction);
});
})();
http://jsfiddle.net/Z97cm/
I've scoped it into an anonymous (function(){})(); to keep out of the global scope, so you might want to consider that if you need to access that function from outside that scope. But that gives you the general idea of what I was talking about.
Although I am almost certain the answer to this question will be browser specific, do any of the browsers define behavior for when multiple <script> tags are used and have the same src attribute?
For instance...
<script src="../js/foo.js"></script>
...
<!-- what happens here? -->
<script src="../js/foo.js"></script>
The reason I ask this question in the first place, is that in my particular case I am using partial views in an ASP.NET MVC application which make use of JQuery. The JQuery JS file(s) are all included in the master template file via script tags. I would prefer to add script tags to the partial view files so that in case they are used outside the context of the master template, they will automatically include all the necessary JS files, and not rely on another view or template to include them. However, I certainly don't want to cause JS files to have to be transferred to the client multiple times, or any other side effects that could negatively impact the user experience.
My thinking right now is that most, if not all, of the major browsers (FF, Safari, IE, Opera) will cache a JS file the first time it is used, and then on subsequent script tags the browser will use the cached copy if available and if it hasn't expired. However, caching behavior can usually be altered through browser configuration, so it doesn't seem too "safe" to rely on any kind of caching behavior.
Will I just have to accept the fact that my partial views are going to have be dependent on other templates or views including the appropriate JS files?
Even if they're cached, you may have problems since the same code will be executed twice. At the very least, this will cause the browser to take more time than necessary. And it may cause errors, since most JavaScript code isn't written to be executed twice. For example, it may attach the same event handlers twice.
Don't output script tags directly in your partials. Create a mechanism to register script files for later inclusion. That mechanism can be responsible for only including files once.
What happens is that JavaScript is feed into the interpreter the moment it is downloaded. In the event of a namespace collision only the variable name, of a given scope, survives to execution. Normally this last only process prevents problems from arising by overwriting functions feed into the interpreter earlier. The problem is that a function defines variable scope, which those variables could be other functions that introduce then other namespace scopes of variables. That is a problem because if functions share the same name value and include different variable definitions then there could be leakage where variables from a function feed into the interpreter early survive even after that function is overwritten, which can then cause expected namespace collisions.
If the exact same file is included twice there should be no problem. The problem occurs when different versions of the same file are included or different files with the same function names are included. Including the same file twice can mean multiple transmissions, which is a waste of bandwidth.
FF 3.5x, Chrome 4x include it only once.
:) IE 8 has two copies (view in Developer Tools > Scripts tab there are two jquery-1.3.2.min.js entries)