I understand that if I have a js file (x.js) that has some function and another file (y.js) that uses the function from x.js then when loading the files, I must load x.js then y.js
In bigger projects, 1) is there a way - i.e. editor tool, plugin, console tool, website - that checks if JS files are loaded in the right order? or 2) is there a standardized method of checking the order of JS file load?
I picked up* a huge project last week at work and sometimes the main page loads correctly with no console errors, other times I get a number of console errors.
*The project had many parts in the past, but right now they cut it down to one part. However, the JS files have way too many dependencies and the person who worked before me did not bother cleaning the files, marking unused functions, or even commenting.
I believe you can mark the scripts that have dependencies as defer so they won't load until other scripts load first. From the html5 spec:
If the element has a src attribute, and the element has a defer
attribute, and the element has been flagged as "parser-inserted", and
the element does not have an async attribute The element must be added
to the end of the list of scripts that will execute when the document
has finished parsing associated with the Document of the parser that
created the element.
Related
I am having an issue with HTML injection into an already loaded DOM where the inline javascript is being loaded after the script file is downloaded. From what I know this should not be async and the inline script should execute after the script file. This works if the domain name is the same as the calling page, but using a CDN or even a subdomain does the same thing. Is there something I should do to rework how I am calling these? I swear this worked before as I had the CDN on for over a week but maybe I never caught this issue.
Console
Loading Inline Script
VM1400:3 Uncaught TypeError: Cannot read property 'init' of undefined(anonymous function)
app.members.event.js?v=204&_=1453644424985:5 Loading Script File
app.members.event.js?v=204&_=1453644424985:71 Finished Script File
Javascript
<script type="text/javascript" src="https://test.azureedge.net/Areas/Directors/scripts/app.members.event.js?v=204"></script>
<script type="text/javascript">
console.log('Loading Inline Script');
app.viewModel.members.event.init();
console.log('Finished Inline Script');
One way is to use jquery's getScript() function.
But preferably, you may use native javascript to load the script file and then run the inline script.
Maybe i have not understood the question clearly.
Edit:
This is a quote from the HTML5 spec regarding script elements.
If the element has a src content attribute, run these substeps:
Let src be the value of the element's src attribute.
If src is the empty string, queue a task to fire a simple event named
error at the element, and abort these steps.
Resolve src relative to the element.
If the previous step failed, queue a task to fire a simple event named
error at the element, and abort these steps.
Do a potentially CORS-enabled fetch of the resulting absolute URL,
with the mode being the current state of the element's crossorigin
content attribute, the origin being the origin of the script element's
Document, and the default origin behaviour set to taint.
The resource obtained in this fashion can be either CORS-same-origin
or CORS-cross-origin. This only affects how error reporting happens.
For performance reasons, user agents may start fetching the script (as
defined above) as soon as the src attribute is set, instead, in the
hope that the element will be inserted into the document (and that the
crossorigin attribute won't change value in the meantime). Either way,
once the element is inserted into the document, the load must have
started as described in this step. If the UA performs such
prefetching, but the element is never inserted in the document, or the
src attribute is dynamically changed, or the crossorigin attribute is
dynamically changed, then the user agent will not execute the script
so obtained, and the fetching process will have been effectively
wasted.
Then, the first of the following options that describes the situation
must be followed:
If the element has a src attribute, and the element has a defer
attribute, and the element has been flagged as "parser-inserted", and
the element does not have an async attribute The element must be added
to the end of the list of scripts that will execute when the document
has finished parsing associated with the Document of the parser that
created the element.
The task that the networking task source places on the task queue once
the fetching algorithm has completed must set the element's "ready to
be parser-executed" flag. The parser will handle executing the script.
If the element has a src attribute, and the element has been flagged
as "parser-inserted", and the element does not have an async attribute
The element is the pending parsing-blocking script of the Document of
the parser that created the element. (There can only be one such
script per Document at a time.)
The task that the networking task source places on the task queue once
the fetching algorithm has completed must set the element's "ready to
be parser-executed" flag. The parser will handle executing the script.
If the element does not have a src attribute, and the element has been
flagged as "parser-inserted", and either the parser that created the
script is an XML parser or it's an HTML parser whose script nesting
level is not greater than one, and the Document of the HTML parser or
XML parser that created the script element has a style sheet that is
blocking scripts The element is the pending parsing-blocking script of
the Document of the parser that created the element. (There can only
be one such script per Document at a time.)
Set the element's "ready to be parser-executed" flag. The parser will
handle executing the script.
If the element has a src attribute, does not have an async attribute,
and does not have the "force-async" flag set The element must be added
to the end of the list of scripts that will execute in order as soon
as possible associated with the Document of the script element at the
time the prepare a script algorithm started.
The task that the networking task source places on the task queue once
the fetching algorithm has completed must run the following steps:
If the element is not now the first element in the list of scripts
that will execute in order as soon as possible to which it was added
above, then mark the element as ready but abort these steps without
executing the script yet.
Execution: Execute the script block corresponding to the first script
element in this list of scripts that will execute in order as soon as
possible.
Remove the first element from this list of scripts that will execute
in order as soon as possible.
If this list of scripts that will execute in order as soon as possible
is still not empty and the first entry has already been marked as
ready, then jump back to the step labeled execution.
If the element has a src attribute The element must be added to the
set of scripts that will execute as soon as possible of the Document
of the script element at the time the prepare a script algorithm
started.
The task that the networking task source places on the task queue once
the fetching algorithm has completed must execute the script block and
then remove the element from the set of scripts that will execute as
soon as possible.
Otherwise The user agent must immediately execute the script block,
even if other scripts are already executing. Fetching an external
script must delay the load event of the element's document until the
task that is queued by the networking task source once the resource
has been fetched (defined above) has been run.
From this I think that your "external" file is loaded after the inline script block. I would therefore use the "getScript()" function from jquery to make sure that the script is loaded before the inline script block.
This is a common problem in the injection scenerio. It occurs due to the variable delays in script availability, as well as due to the parallel and differing implementations on various browsers.
There are 3 options, depending on whether the source code is available for editing or not, and if more than 2 dependencies exist between the script files.
Option 1. Using defer attribute in the script tag
This option can be used, if both scripts are remote (ie, not inline)
"defer" indicates to the browser that the script has to execute after the document has been parsed (quoted from MDN). This is applicable only for remote (not inline) scripts, that have the "src" attribute.
https://html.spec.whatwg.org/multipage/scripting.html#attr-script-defer
You can use it like below.
Defer is supported on major browsers, and I validated on Chrome, Firefox, Webkit on Tizen, and Safari:
https://developer.mozilla.org/en/docs/Web/HTML/Element/script#Browser_compatibility
To provide concrete example of the above cases, refer below. Note that the below have been validated on Firefox, Chrome, IE11, Safari on iPhone, and Webkit on Tizen.
Case 1:
Many Javascript files - All independent:
If there is no dependency, the "defer" attribute allows the HTML to be loaded quickly. The script takes over after downloading, without issues (assuming onload etc are taken care).
Case 2:
Two javascript files test1.js and test2.js - One dependent on the other:
If test2.js is dependent on the loading of test1.js, then the script tag for test2.js "only" should have the defer attribute.
This usage is shown in
http://www.gpupowered.org/loadtest/2_defer.html
Incorrect usage is shown in
http://www.gpupowered.org/loadtest/no_defer.html (Both scripts do not have defer tag - this fails)
http://www.gpupowered.org/loadtest/all_defer.html (Both scripts having defer tag - this also fails)
Async usage that does not work is at,
http://gpupowered.org/loadtest/2_async.html (this fails)
Where does "defer" not meet the needs ?
If the functionality is split across several JS files (say n), and all "n-1" need to be downloaded before "n"th file can start processing some variables, even though the "defer" attribute might be present on all the script source tags, it is rendered irrelevant because the order in which they are received are indeterminate.
More background on defer and the various options for deferred loading (doesnot cover the multi defer case)
http://www.html5rocks.com/en/tutorials/speed/script-loading/
https://developer.mozilla.org/en/docs/Web/HTML/Element/script
Option 2: Using state variables
This option can be used if some additional state variables can be added to both javascript source files.
The approach relies on a named variable in the dependent js file, and a named function in the js file that uses the dependent file. If the dependent file is not loaded at the time the user file is trying to access its functionality, it exits and will be called back when it is really loaded.
This is demonstrated in the below html file.
http://gpupowered.org/loadtest/variable.html (works correctly)
This option does not work if the loading needs to happen repetitively (ie, loading of multiple files of same name etc).
Option 3: Native script loader
In this case, there are multiple javascript files having dependencies between each other.
There is no solution for this case using defer or async or other specification provided tags. For the use-case I had in the remote labs in gpupowered.org, I had to implement my own native script loader using XMLHttpRequest, and the source for this is provided in the link below. This uses worker threads as some of the textures I have are fairly big. The callback function can be used to implement the dependency logic as per the application needs. For example, keep count of all loaded scripts and then trigger full execution etc.
https://github.com/prabindh/gpupowered.gl/blob/master/worker/worker_object_loader.js
The jquery script loader uses the HTTP request as well, though I have not checked if it uses a worker for loading.
https://api.jquery.com/jquery.getscript/
I have two theories:
Might be that there's something in the external script that's delaying the creation of the app.viewModel.members object (either a timeout or an event handler that takes a while to fulfil). This can be easily tested by setting a long timeout in your inline script (f.i. 5000+ms) and then checking if the models object exists.
There's something funky going on when loading a same origin script.
In this case you could try is delay the execution of your inline script by doing the following:
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function(event) {
app.viewModel.members.event.init();
});
</script>
or just put your inline code in an external .js file and call it with the 'deferred' flag:
<script type="text/javascript" src="https://test.azureedge.net/Areas/Directors/scripts/app.members.event.js?v=204"></script>
<script type="text/javascript" src="{link-to-external-js-file}" defer></script>
function onloadCallback(){
app.viewModel.members.event.init();
}
Use this:
<script type="text/javascript" src="https://test.azureedge.net/Areas/Directors/scripts/app.members.event.js?v=204&onload=onloadCallback"></script
<script type="text/javascript">function onloadCallback(){
app.viewModel.members.event.init();}</script>
I have the issue that binding expressions such as
<div data-bind="text: $data.Property"></div>
-where Property is an observable- causes the actual text of knockout's observable function to display instead of the value Property is supposed to represent. This was addressed here In IE8, KnockoutJS 3.2 displaying actual observable function rather than the observable's value.
The cause of that issue was that duplicate knockout library files were being loaded. The "UPDATE:" section and answer of the linked SO question includes some detail around that.
I now need to know how to keep the knockout library from being loaded twice. Emphasis on loaded not just executed. So far I haven't found anything that quite answered this.
RequireJS: is used by the site but, not by the pages under investigation.
SignalR: is used by the page. I'm a bit unfamiliar with SignalR so I can't say how likely it is that this is causing multiple loads.
Ajax: is used as well but it is used to receive JSON data.
There is only 1 explicit reference to the knockout library.
Looking at the network tab, the first file is loaded from the speculative download feature of IE. The second file is from the main parser. The first file is completely downloaded, and then the second is completely downloaded.
What I haven't been able to figure out is a way to keep:
The Lookahead Downloader from downloading the file the first time
The main parser from downloading the file a second time
The file from being executed a second time without changing the code in the library file.
One of the above solutions can be acceptable at this point. Can anyone offer insight, suggestions or know of a solution to this?
I finally got this figured out. The issue was the order that the scripts were listed in the page. ASP.NET MVC 5 supports renderable named sections. In this case scripts:
Layout -
#RenderSection("scripts", required: false)
Views/Partial Views -
#section scripts {
// script includes ...
}
In my case a partial view did not include scripts in a scripts section causing them to be parsed/downloaded by the preparser and the main parser.
Adding all scripts to scripts sections in the proper order solved this problem. The order has been determined by the the scripts' dependencies.
I want to decrease the time taken by my pages to load and be displayed, assuming I start with an empty browser cache, and the pages may or may not have inline css and javascript in the html file. does changing the order in which files are sent to the browser decrease the display time, and thus make pages seem to be loading faster?
For example if a page has some .css, .js, .png files and so on, would loading the css first, display things faster?
And is there a standard/specific order to load file types?
Here are few steps that could optimize the performance of your web pages.
put css at top.
put javascript at bottom.
cache everything.
set far future expire header.
return 304 when appropriate.
use unique url for css and js for propagating the change.
apart from that use ajax wherever required.
Beware of too many HTTP connections. It takes time to establish an HTTP connection and it can easily eat up loading time if you have many elements linked in your HTML file.
If you have many small icons, glyphs, etc. combine them into a sprite so only one image is loaded. Facebook for instance makes use of the sprite technique - you can see that if you inspect the images it loads.
You can also consolidate your CSS files into one file - same with Javascript files.
Also, if you have JavaScript that affects the content of your page when it loads then make sure to use the event that notifies you when the DOM is ready, instead of waiting for the body loadevent which doesn't trigger until all resources, such as images, CSS files, JavaScript etc is loaded.
js files block page loading until they're executed. When possible, include those before closing body
At first make sure that your webhoster has no slow servers. This can happen on very cheap shared site webhosters. Than you should check that you remove all unnessesary stuff from your html output. Than you could check if your content is dynamic or static. If it is dynamic try to convert it to static content.
In some conditions you can simply activate the caching functions of a CMS that should also help to send the website content faster. Just on slow connections it could be better to use gzip to compress the output stream. But this costs time. The server and also the client have to compress/decompress. You have to check that too.
If you use javascript and the execution is delayed you could also use the ready event to execute your javascript after the html document is loaded (and not all images and so on) like using the document.onload event.
You can save your page load time to use few trick like :- CSS image sprites rather than call every single image for every single purpose this will Minimize your website's HTTP Requests, remove unnecessary div tags or unnecessary code from your HTML-Markup & CSS
Where we can get good results through CSS and so we should not use Jscripts there.
Should make always clean HTML-Markup without any irreverent code.
Combined files are a way to reduce the number of HTTP requests by combining all scripts into a single script, and similarly combining all CSS into a single stylesheet. Combining files is more challenging when the scripts and stylesheets vary from page to page, but making this part of your release process improves response times.
The solutions turned out the simple, combine all the different files into a single large file and compress that file using zip. Unfortunately, if you do this manually you are going to run into maintenance problems. That single compressed file is no longer editable. So after editing one of the original source files you will have to re-combine it with the other files and re-compress it.
I have a multiple page website using RequireJS, which loads a boot strap file (boot.js), which then requires app.js.
app.js handles all the logic, and all other module initialization happens through app.initModule() (which is just a require() call wrapper)
I also have a app.loadPageJS() to load page specific JS files (based on window.location.pathname, for example, www.domain.com/path/to/file.html would auto-load /_assets/js/pages/path/to/file.js)
This feature can be turned on/off, and overridden by adding a class of "no-auto-load" or "auto-load" to the body, respectively.
Now, my approach isn't robust enough. For one, url rewriting would break the mechanism, and for two, if loadPageJS is turned off, unless I have access to the body tag, I can't include a page specific JS file (in the case of sites using templating systems, adding a class to the body tag isn't always an option).
What are other ways to include page specific code? I'd rather avoid the following:
adding page specific code to a global.js file and doing if checks and only running certain code sets
using a pageName variable (which would essentially be similar to the above)
Thanks in advance.
If you have different modules on the page sectioned by unique ID's (a newsletter module wrapped within a div with an ID of 'newsletter', etc), you could test for existence of the module element in the DOM and conditionally load in the JS file necessary to run that module. So rather than being page-specific, it is module specific.
In todays modern age, where lots of (popular) javascripts files are loaded externally and locally, does the order in which the javascripts files are called matter especially when all local files are all combined (minified) into one file?
Furthermore, many claim that Javascript should go in the bottom of the page while others say javascript is best left in the head. Which should one do when? Thanks!
google cdn latest jquery js | external
another cdn loaded javascript js | external
TabScript ...js \
GalleryLightbox ...js \
JavascriptMenu ...js \
HTMlFormsBeautifier ...js > all minified and combined into one .js file!
TextFieldResize ...js /
SWFObjects ...js /
Tooltips ...js /
CallFunctions ...js /
Order matters in possibly one or more of the following situations:
When one of your scripts contains dependencies on another script.
If the script is in the BODY and not the HEAD.. UPDATE: HEAD vs BODY doesn't seem to make a difference. Order matters. Period.
When you are running code in the global namespace that requires a dependency on another script.
The best way to avoid these problems is to make sure that code in the global namespace is inside of a $(document).ready() wrapper. Code in the global namespace must be loaded in the order such that executed code must first be defined.
Checking the JavaScript error console in Firebug or Chrome Debugger can possibly tell you what is breaking in the script and let you know what needs to be modified for your new setup.
Order generally doesn't matter if functions are invoked based on events, such as pageload, clicks, nodes inserted or removed, etc. But if function calls are made outside of the events in the global namespace, that is when problems will arise. Consider this code:
JS file: mySourceContainingEvilFunctionDef.js
function evilGlobalFunctionCall() {
alert("I will cause problems because the HTML page is trying to call " +
"me before it knows I exist... It doesn't know I exist, sniff :( ");
}
HTML:
<script>
evilGlobalFunctionCall(); // JS Error - syntax error
</script>
<!-- Takes time to load -->
<script type="text/javascript" src="mySourceContainingEvilFunctionDef.js"></script>
...
In any case, the above tips will help prevent these types of issues.
As a side note, you may want to consider that there are certain speed advantages to utilizing the asynchronous nature of the browser to pull down resources. Web browsers can have up to 4 asynchronous connections open at a time, meaning that it's quite possible that your one massive script might take longer to load than that same script split up into chunks! There is also Yahoo Research that shows combining scripts produces the faster result, so results vary from one situation to another.
Since it's a balance between the time taken to open and close several HTTP connections vs the time lost in limiting yourself to a single connection instead of multiple asynchronous connections, you may need to do some testing on your end to verify what works best in your situation. It may be that the time taken to open all of the connections is offset by the fact that the browser can download all the scripts asynchronously and exceed the delays in opening/closing connections.
With that said, in most cases, combining the script will likely result in the fastest speed gains and is considered a best practice.
Yes, depending very much on what you do.
For example, if a.js had...
var a = function() {
alert('a');
}
...and b.js had...
a()
...then you wouldn't want to include b.js before a.js, or a() won't be available.
This only applies to function expressions; declarations are hoisted to the top of their scope.
As for whether you should combine jQuery, I reckon it would be better to use the Google hosted copy - adding it to your combined file will make it larger when there is a great chance the file is already cached for the client.
Read this post from the webkit team for some valuable information about how browsers load and execute script files.
Normally when the parser encounters an
external script, parsing is paused, a
request is issued to download the
script, and parsing is resumed only
after the script has fully downloaded
and executed.
So normally (without those async or defer attributes), scripts get excuted in the order in which they are specified in the source code. But if the script tags are in the <head>, the browser will first wait for all scripts to load before it starts executing anything.
This means that it makes no difference if the script is splitted into multiple files or not.
If I'm understanding your question I think you're asking if it matters where in a file a function/method is defined, and the answer is no, you can define them anywhere in a single source file. The JavaScript parser will read in all symbols before trying to run the code.
If you have two files that define variables or functions with the same name, the order that they're included will change which one actually is defined