loadlify v4.1.0
Loadlify
Fully customizable, secure, and simple loader for web assets with support for ES6 modules and SRI Hashes. Demo
About Loadlify
It makes use of the native Promise and ES6 classes to make it's job, so is expected to run it on a ES6 capable browser. It's tested on Chrom{e,ium}
and Firefox
, always in the latest version.
Loadlify makes simple the process to load scripts and also, dependencies, don't worry about loading dependencies before running a script, set them like loadlify.deps["myscript.js"]=["jquery", "vue"];
.
Of course you can make sure of a module is loaded in a part of your script that requires it, following the previous line of code, here is an example:
/*myscript.js*/
//Here jquery and vue are loaded
jQuery("#myItem")...
var app=new Vue(...);
//Some lines of code later...
makeSomethingAwesome(...args){
//Some awesome lines...
load("awesomescript.js") //It's not yet loaded, but I'll need it later... the load process is asynchronous, so let's continue doing things...
//Some lines later...
load("awesomescript.js").then(module=>{ //Let's see the progress of the load process and set a handler for the Promise
//Here the script is loaded (and all of its dependencies), in the very expected moment.
module.exports.awesomescript.awesomefunction();
//More of your awesome core
});
}
Basic usage
The function load
, declared in the global scope is a shorthand for loadlify.load
This function has two arguments, one is mandatory:
load(script, flags);
//The first argument can be an array or a string (or an array containing more arrays and so on...)
//The second argument can be a string, an array or undefined. This flags are inherited by default, but this feature can be disabled
//The return is a promise and it's value is an object as defined below
Return value
The return value is a Promise. This is the structure for the first argument in .then
function.
{
apply:[ //This is the return value of the handler for each type of asset. The return value of the built-in application/javascript handler is:
function, //The newly constructed function. Here you can for example run again the function.
{
err: undefined, //If an error occurred in the apply function Promise will be rejected, so this property is commonly undefined.
flags: ["es6", "noflagsindeps"], // Contains the array of flags passed to the 'load' function.
rv: undefined, //Return value from function (undefined is the most common),
url: "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" //URL string from where the asset was loaded
}
],
blob: blob, //This blob contains the loaded asset as a blob
deps:[...], //Array with the dependencies loading progress (all are resolved before the main Promise)
exports: {}, //This object is explained in the 'exports' section of this file
internalURL: "blob:https://hostname/ed6a295a-35e0-44d4-93f9-ab1b045e8ded", //URL created in order to access the asset.
link: URL, //Not the same as the apply[1].url because of this URL is on object created with the URL constructor.
name: string, //Name of the module (taken from the first parameter passed to loadlify.load)
text: string, //Loaded asset in plain text.
type: "application/javascript" //From blob.type. Used to choose the correct handler
}
Examples
Load it with script tags
````html <!-- Minified version --> <script src="https://unpkg.com/loadlify@latest/loadlify.min.js"></script> <!-- Normal version --> <script src="https://unpkg.com/loadlify@latest/loadlify.js"></script> <!-- Please, don't use the unminified version in production environments, it has lots of comments and garbage. Let the browser load the source map. --> ````
- Alternatively, you can use
eval()
or theFunction()
constructor,loadlify
will jump anyway to the global scope (using theself
variable)
- Alternatively, you can use
Now, the
load
function, theloadlify
object and theloadlifyJS
class have jumped to the global scope- To load an asset, just:
````javascript load("bootstrap").then(a=>{ //Code with bootstrap and jQuery (jQuery is loaded as a dependency of bootstrap) }); load(["your/library.js", "your/library.css"]).then(a=>{ //When loading libraries this way, loadlify takes loadlify.props.prefix as a prefix for your path. It defaults to ./lib/ (as defined in loadlify.props.prefix) }); load("https://unpkg.com/vue@latest/vue.min.js").then(a=>{ //When loading libraries this way, loadlify fetches the URL as provided. }); ````
In-Depth Usage
Inside
The loadlify.load
method has control over the load process. It loads the asset and calls the handler for the type of asset.
self.load
is an alias of loadlify.load
. Call it as you like, but keep in mind that self.load
will call self.loadlify
, so if you build a new instance, you will need to call yournewinstance.load
in order to use it instead on the global.
The loadlify
object and FLAGS!
- Use
loadlify.load(asset)
function to load assets- You can modify defs, deps and other variables on the run.
load()
function supports flags.load(asset, [flags])
- Flags are inherited from assets to its dependencies so they will load with the same flags as the main asset.
noflagsindeps
dependencies won't inherit flags from the parent asset.noconcatflags
the global flags won't be concatenated to the ones in the script.nodeps
won't load dependencies.nocache
Loadlify Cache won't be checked and will addcache: no-cache
to the Request (loadlify can't control the caches directly, simply adds the instruction and lets the browser do the rest).force
will load the asset ignoring the warnings and cache (loadlify cache and any who reads the cache-control header).astag
will load the script in a<script>
tag and CSS in a<link>
tag. -reapply
will make a downloaded item to be processed again.noprefix
won't add the prefix (defined atloadlify.props
(orproperties
while instantiating) to the URL.notext
Loadlify won't convert the blob to text (save time if only the blob is needed).requirejs
Only JavaScript. Will put requireJS before the script.type: mimetype
Replace the auto detection of the type with a custom type. For example text/html or application/javascript. Remember that the handler for this type must exist.allowedheader: value
Ifallowedheader
is inloadlify.props.configurable
or in the default array of properties["method", "mode", "cache", "credentials", "redirect", "referrer", "integrity"]
,value
will be added to theinit
object when creating a Request.
The loadlifyJS
class
loadlifyJS
variable contains the constructor. Customize your own loadlify instance by constructing the classloadlifyJS
will take from the object in the first parameter the config values. The not supplied variables, will be taken from defaults
var loader=new loadlifyJS({
defs: yourOwnDefinitions,
deps: yourOwnScriptDependencies,
flags: yourDefaultFlags,
properties: yourOwnProperties
});
Subresource integrity
The Subresource Integrity (better explained in the MDN docs) is a very important security feature on modern browsers. It can avoid unwanted scripts or assets being injected into the Web App. Now Loadlify can handle the SRI Hashes to avoid all of this trouble. Unlike the <script>
or <link>
tags, loadlify can add the SRI to any asset loaded with it (like HTML, images or any other file).
How can be configured
There are two methods to configure a SRI hash for an asset.
//As a header flag (has priority over any other method)
load("jquery", ["integrity: sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT"]);
//This is directly added to the Request init. (Of course this flag will be removed in order to avoid trouble with dependencies)
//This method sets the SRI hash if there isn't a flag with the SRI. This is necessary to set SRI hashes for dependencies.
loadlify.integrity["https://unpkg.com/jquery@3.3.1/dist/jquery.min.js"]="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT";
Modules
Modules are a very important feature in loadlify. They are making a change in the web of today, so are essential on a new loader.
Modules aren't enabled by default. Loadlify, by default exposes the self.exports
object, but the es6
flag is not set, so modules cannot see that object. You must set it in order to work with modules by passing it to determinate modules or enabling it for everything with loadlify.flags.push("es6")
How are modules recognized (Loaded script side)
Loadlify exposes a exports
object in the function. Everything added to this object should be inside a object to keep the compatibility between modules.
Example:
exports["module2"]=functionsToexport;
And this would be the result (a module was loaded before this);
exports: {
module1: {
method1:function(){/*do things...*/}
},
module2: {
method1:function(){/*Same function name in a different module*/} //Those functions are compatible
}
};
How do modules work when loaded from loadlify
A object called exports
is exposed to the global object (it can be prevented with self.noExports=true
).
This object is hotlinked between the two scopes (global and function). Also there is a exports
object in the return value of the load object.
Known bugs and caveats
- Not compatible with NodeJS (Because of the usage of the
self
variable). - Please, avoid dependency loops, will result in a everlasting Promise.
- Don't point to the same dependency twice (solved from Loadlify 3.2.0)
exports
object is not updated inside scripts (was copied from the global exports object) in Loadlify <3.2.0
License
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago