Can A Javascript File Load Itself Asynchronously? - javascript

I use Squarespace as my CMS. I'd like to know if there's a way to have the actual .JS file load itself asynchronously to ultimately reduce the site load time.
For those who don't know, Squarespace gives very limited access to backend content and files. So I'd like to know if there are any alternatives to reduce render-blocking resources.
The file is located in [websitename]/scripts/site-bundle.js found through SFTP.
EDIT: Here's the full code https://codepen.io/anon/pen/MMKZyQ, as you can see I can't find any script tags to insert the defer or async values.
!function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={exports:{},id:o,loaded:!1};return e[o].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}n(2);var r=n(6),i=o(r),a=n(60),u=n(65),c=o(u),l=n(85),s=o(l);n(86);var d=n(87),f=o(d),p=n(100),h=o(p),v=n(101),y=o(v),m=n(104),A=o(m),g=n(121),b=o(g),w=n(189),_=o(w),x=n(190),E=o(x),k=n(191),S=o(k),T=n(192),L=o(T),O=n(193),M=o(O),P=n(194),j=o(P),C=n(195),R=o(C),I=n(103),F=o(I),V=n(196),N=o(V),D=n(199),B=o(D),G=n(200),U=o(G),H=n(207),z=o(H);i.default.register("AncillaryLayout",f.default),i.default.register("FooterBreakpoints",h.default),i.default.register("HashManager",y.default),i.default.register("IndexFirstSectionHeight",A.default),i.default.register("IndexGallery",b.default),i.default.register("IndexGalleryVideo",_.default),i.default.register("IndexNavigation",E.default),i.default.register("HeaderNavFolderTouch",S.default),i.default.register("HeaderOverlay",L.default),i.default.register("MobileClassname",M.default),i.default.register("MobileOverlayFolders",j.default),i.default.register("MobileOffset",R.default),i.default.register("MobileOverlayToggle",F.default),i.default.register("Parallax",N.default),i.default.register("ScrollIndicator",B.default),i.default.register("SiteLoader",U.default),i.default.register("UserAccountLink",z.default),i.default.register("VideoBackground",function(e){return(0,c.default)(e,function(e){var t=e.handleResize,n=e.handleTweak;(0,s.default)(t,105),a.Tweak.watch("tweak-overlay-parallax-enabled",n)})}),window.addEventListener("controller:refresh",i.default.refresh)},function(e,t,n){n(3).polyfill()},function(e,t,n){(function(t){for(var o=n(4),r="undefined"==typeof window?t:window,i=["moz","webkit"],a="AnimationFrame",u=r["request"+a],c=r["cancel"+a]||r["cancelRequest"+a],l=0;!u&&l<i.length;l++)u=r[i[l]+"Request"+a],c=r[i[l]+"Cancel"+a]||r[i[l]+"CancelRequest"+a];if(!u||!c){var s=0,d=0,f=[],p=1e3/60;u=function(e){if(0===f.length){var t=o(),n=Math.max(0,p-(t-s));s=n+t,setTimeout(function(){var e=f.slice(0);f.length=0;for(var t=0;t<e.length;t++)if(!e[t].cancelled)try{e[t].callback(s)}catch(e){setTimeout(function(){throw e},0)}},Math.round(n))}return f.push({handle:++d,callback:e,cancelled:!1}),d},c=function(e){for(var t=0;t<f.length;t++)f[t].handle===e&&(f[t].cancelled=!0)}}e.exports=function(e){return u.call(r,e)},e.exports.cancel=function()

This can be accomplished for the Brine/Wright family of templates by doing the following:
Enable Developer Mode (Settings > Advanced > Developer Mode)
Using SFTP or Git, obtain access to the template files.
Within site.region file, change:
<squarespace:script src="site-bundle.js" combo="false" />
to
<squarespace:script src="site-bundle.js" combo="false" async="true"/>
Use SFTP or Git to update your template files on Squarespace's servers.
You may also use <script src="/scripts/site-bundle.js" async></script> instead of using Squarespace's script loader. Simply replace the aforementioned line in step 3.
As an aside, the unbundled code can be found in Squarespace's Wright GitHub repository.
For other templates not in the Brine/Wright family, similar steps may apply, though file names may differ.

There are two properties on a script tag to do exactly what you want to do:
specifying defer will defer the loading of the script until the page has been fully parsed (and rendered)
specifying async will indicate to the browser that this script can be loaded asynchronously at any point of its choosing.
Those two properties are both well supported (defer, async) and as such, you can and should make use of them to achieve this.

Related

Obtain content of <script src="..."> tag in HTML

I have an HTML file with Javascript, that is supposed to load and process an XML file. The main obstacle is that the script may also be run locally, without an HTTP server, and also has to support Internet Explorer (11).
In normal case, I would use XMLHttpRequest, but as far as I know, it cannot be used with locally stored files (or at least doesn't work in my test cases for Chrome and IE).
I tried using <script> blocks with set src and type="text/xml" attributes and it successfully loads the content of the xml "somewhere" (the content is loaded and is visible in the network trace), but I cannot find a way, to extract the content of the xml from the <script> node.
Most sources (e.g. Getting content of <script> tag) suggests using XHR, but AFAIK it cannot be done in this case.
Is there a sensible option to implement this, without minimal http server?
I am looking for a clean solution without jQuery.

collect all the js css and img resources used in a html file

I want to write a npm package to localize an html url.
1. using the html url download the html page
2. parse the html file, extract all the js, css and img files used in the html and local these resources.
3. If these js, css and img files using some external resources, localize these resources. For example, extract background image in the css.
The first and second requirements are easy to meet. But I have no idea about the last one.
I can parse the all the css files and localize the resources used in it. But how can I parse the js files?
For example:
If the js adds a 'script src = XXX' tag into the html dom, how can I extract the src?
I think I would try to use a headless browser to catch every network calls instead of trying to parse the code.
I didn't used it personally but PhantomJS seems to fit the bill.
It can be used to load a webpage then execute any script / css that would normally happen on the request and execute stuff once the page is loaded.
The network monitoring features are probably what you'll want to use.

Use a chrome://myAddon/content/ URL in Firefox Add-on SDK extension

I am trying to load a frame script following this tutorial:
mm.loadFrameScript("chrome://myextension/content/content.js", true);
My extension is an Add-on SDK type. The tutorial says I need to specify content in chrome.manifest first. I did not even have that file (only package.json and index.js). So I've created myextension/chrome.manifest with a single line:
content content.js
And created a file myextension/content/content.js:
console.log("content script executed");
The problem is, when mm.loadFrameScript("chrome://myextension/content/content.js", true); is executed in index.js, I get error:
No chrome package registered for chrome://myextension/content/content.js
I guess it is because the manifest file is wrong or not being registered all together? But I couldn't find any clues to my problem on the chrome registration page.
That tutorial is generally targeted towards XUL or restartless/bootstrap add-ons. A more appropriate tutorial in that hierarchy is: Multiprocess Firefox and the SDK. The gist of that page is that if you stay with the Add-on SDK APIs your extension should just work in multiprocess Firefox, and that if it doesn't then it is a bug in the Add-on SDK.
In general, Add-on SDK extensions will use one of the High Level APIs to load content scripts. The primary APIs which would be used are tabs and page-mod, but there are others (e.g. context-menu and page-worker). There are also the Low-Level APIs of remote/parent and remote/child which deal with processes and frames.
However, you can use frame scripts if you desire to do so. Add-on SDK extensions are actually restartless/bootstrapped extensions which are wrapped by the add-on SDK. Thus, you can do most things which can be done in a bootstrapped extension within an Add-on SDK extension if you really want to do so. However, it is better to stay within the APIs provided by the Add-on SDK. If you go around those APIs then you loose some of the advantages which the Add-on SDK exists to provide to you (e.g. hiding the actual implementation behind APIs which are intended not to change).
Frame scripts and content scripts exist to perform the same function: access the content (e.g. HTML pages) which has been loaded into an area that is potentially under the control of a different process (e10s). Largely, the things that are referred to by the two different names are very similar. However, you will almost exclusively see the term "frame scripts" used only for XUL and bootstrap extensions while "content scripts" will almost always be referring to Add-on SDK scripts.
Again, you are probably better off using the Add-on SDK APIs to load the scripts you are using to access content that is potentially in another process.
Add-on SDK: Using the data directory:
For an Add-on SDK extension, instead of using a chrome:// URL it is more appropriate to use the [add-on base directory]/data/ directory and obtain the URL reference to your file using the sdk/self API. You would do this with:
var self = require("sdk/self");
let frameScriptUrl = self.data.url("content.js")
Then your loadFrameScript() line would be:
mm.loadFrameScript(frameScriptUrl, true);
Using chrome.manifest:
content lines:
The content line of the chrome.manifest file is:
content packagename uri/to/files/ [flags]
This is a minimum of 3 fields separated by whitespace with one or more optional additional fields for flags.
The first field is content which indicates that this is a line that defines how a chrome://packagename/content URL will be resolved.
The second field is a packagename. This is a name that you make up which must not conflict with other package names already in use by Firefox or those added by other extensions. Usually, this will be the name you are using for your add-on, or some permutation of the name, or id, if using multiple content lines. The name and ID of your Add-on SDK are usually the value of the name and id properties you included in your package.json file, but may be somewhat different. The packagename does not need to be your name or ID, it just needs to be unique to everything that was loaded into Firefox.
The third field is the URL to the directory which contains the files you are going to be referencing. This URL can either be absolute, or relative to the location of the chrome.manifest file. This URL must end with a /.
Firefox looks for the chrome.manifest file in the base directory of your add-on (the same one in which package.json is located). While it is possible to have additional chrome.manifest files using the manifest keyword, that would be unusual.
The prototypical add-on chrome.manifest would contain a line such as:
content packagename chrome/content
When using the chrome URLs made valid by that content line in your chrome.manifest you would use something like chrome://packagename/content/myScriptFile.js. This would reference a file called myScriptFile.js that is in the [add-on base directory]/chrome/content/ directory.
Another example:
chrome.manifest:
content myAddOnName my/special/directory/
In this case, chrome://myAddOnName/content/myScriptFile.js would reference the file [add-on base directory]/my/special/directory/myScriptFile.js.
Your specific issue:
While you stated you were following the tutorial, you did not actually do so for the contents of your chrome.manifest file. Nor when you changed what that file contained did you follow the description of what the content line should contain. However, even if you had followed the tutorial exactly, you would not have ended up with a functioning add-on because the tutorial was incorrect as to what should be in that file. The line in the tutorial was actually invalid. I have corrected that line in the MDN documentation.
What you need to use as the line in your chrome.manifest will depend on the directory structure you desire to use for your extension.
If you wanted your content.js to exist in a directory [add-on base directory]/chrome/content/ and be referenced by chrome://myAddOnName/content/content.js then the content line of your chrome.manifest would be:
content myAddOnName chrome/content/
Note: Even though you used myextension in your question (in your chrome:// URL only) for your packagename, I have not used it here to try to more clearly indicate that the packagename should be a name you choose which is unique to your add-on. It is not clear to me that you are using myextension in your question as a placeholder for what you are really using within your extension. If that is the actual text you are using rather than a placeholder for your question, then I would caution you that the packagename myextension is not very unique and has a reasonable chance to exist in some other random extension. If it does, it may, or may not, cause either or both of your extensions to malfunction.
The SDK provides an abstraction for frame scripts and process scripts (beyond the page-mod and tab attach mechanisms which also rely on frame scripts under the hood), the remote/parent and remote/child modules. You can use remote_require to load a process script and then use remote/child in the process script to enumerate the sdk wrappers for the frame script global objects.

Load OpenLayers library with it's dependencies (Google and OSM) async possible?

I build a AJAX application and have a dedicated part of my application that uses OpenLayers.
At the moment I have the following in my Application.html file, so it gets included at application start:
<script src="http://openlayers.org/api/2.11/OpenLayers.js"></script>
<script src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script src="http://www.openstreetmap.org/openlayers/OpenStreetMap.js"></script>
Now I want to load all this stuff when it's needed, because it has about 500-1000kb size. But I don't know how to do it.
What I've tried:
Load OpenLayers.js and in its callback: ...
... Load GoogleMaps.js and OpenStreetMap.js. And when these both are finished: ...
... Display my map.
Sometimes it works, but most of the time it doesn't, because: GoogleMaps.js and OpenStreetMap.js have some additional .js, .css, .png, etc. dependencies that load independently from my callbacks.
This means: The 3 .js files have finished loading, the callback tells my application to display the map, but in the background those .js files still fetch additional content that's necessary for using OpenLayers.
Is there a way to solve this problem?
You might be interested in using either of the following approaches or combination of them.
1) https://developers.google.com/web-toolkit/doc/latest/DevGuideServerCommunication#DevGuideHttpRequests
2) https://developers.google.com/web-toolkit/doc/latest/tutorial/Xsite
Maybe you can try GWT-OpenLayers instead.
https://bitbucket.org/gwtopenlayers/gwt-openlayers

Send head before body to load CSS and JS asap

I wonder if anyone has found a way to send at mid rendering the head tag so CSS and Javascript are loaded before the page render has finished? Our page takes about 523ms to be rendered and resources aren't loaded until the page is received. I've done a lot of PHP and it is possible to flush the buffer before the end of the script. I've tried to add a Response.flush() at the end of the Masterpage page_load, but the page layout is horribly broken afterward. I've seen a lot of people using an update panel to send the content using AJAX afterward but I don't quite know what impact it would have on the SEO.
If I don't find a solution I guess I'd have to go the reverse proxy route and find a way to invalidate the proxy cache when the pages content change.
Do not place the Flush on code behind but on your html page as:
</head>
<%Response.Flush();%>
<body >
This can make something like fleekering effect on the page, so you can try to move the flush even a little lower to the page.
Also on Yahoo tips page at Flush the Buffer Early
http://developer.yahoo.com/performance/rules.html
Cache on Static
Additionally you can add client cache on static content like the css and javascript. In this page have all the ways for all iis versions.
http://www.iis.net/ConfigReference/system.webServer/staticContent/clientCache
Follow up
One more think that I suggest you to do after I see your pages is to place all css and javascript in one file each. And also use minified to minimize them.
I use this minified http://www.asp.net/ajaxlibrary/Download.ashx with very good results and real time minified.
Consider using a content-delivery-network (CDN) to host your images, CSS and JS files. Browsers have either an eight or four connection limit per domain - so once you use those up the browser has to wait for the resources to be freed up.
By hosting some files on the CDN you get another set of connections to use concurrently, allowing everything to load faster.
Also consider enabling GZIP on your server if you haven't already. This compresses files on the fly, resulting in smaller transfers.
You could use jQuery to execute your js as soon as it is loaded.
$.fn.ready(function(){
//Your code here
})
Or you could just take the standalone ready function -> $(document).ready equivalent without jQuery
You could do a fade-in or show once the document has been loaded. Just set body display:none;

Categories

Resources