Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
lockandload
Advanced tools
Lockandload is a minimalist AMD-loader-compatible boilerplate to kickstart your website. It includes special support for single-page-apps.
Gzipped, the essential script content amounts to roughly 849 bytes of code. Without compression it blows up to about 1449 bytes. Further minifying this code does not result in any significant gains (773 vs 849 bytes), it would just hinder readability.
After reviewing the javascript-loader landscape, looking for a loader that satisfies the following criteria:
$(function(){...})
constructs, yet I insist on loading
jQuery late and asynchronously to speed things up.I came to the conclusion that (apparently?) none of the existing loaders
fit the bill. So I wrote lockandload
back in 2014 and used it in
various internal projects, but decided to open-source
it now in case others find it useful. As always, when open-sourcing something,
actually writing documentation takes most of the time. The documentation
can always be improved. Suggestions are welcome!
require
, exports
, module
and domready
.<script>
, HTTP2 and friends do the heavy lifting).$(...)
jQuery riddled synchronous code.It runs inside any webbrowser environment (supporting ES2018 and up).
Running npm install lockandload
in the webroot of your site,
should create the following file and directory structure:
node_modules
lockandload
lockandload_master.inc
: Placed right after the charset definition
on the page.lockandload_headready.inc
: The start of the headready-script that
lives at the end of the <head>
.lockandload_trailer.inc
: The end of the headready-script that lives
at the end of the <head>
.lockandload_master_debug.inc
: Alternate debugging version of
lockandload_master.inc
.index.php
: PHP boilerplate.index_inlined.html
: High performance HTML only boilerplate.lockandload_master.js
: For lazy <script>
loading.lockandload_master_debug.js
: Alternate debugging version of
lockandload_master.js
.lockandload_headready.js
: Boilerplate for lazy <script>
loading.index_extern.html
: Lazy HTML only boilerplate.main.js
: Example SPA (Single Page Application).Copy the boilerplate node_modules/lockandload/index.php
file to your
webroot; then customise the copied file to taste.
Look at the PHP boilerplate node_modules/lockandload/index.php
, and
translate this to your own scripting language.
Copy the node_modules/lockandload/index_extern.html
boilerplate
file to your webroot; then customise the copied file to taste.
Copy the node_modules/lockandload/lockandload_headready.js
file
to your javascript directory and customise it taste. Do not forget
to change the path of the script
directive in index_extern.html
to point to the new location of the headready script.
Copy the node_modules/lockandload/index_inlined.html
boilerplate
file to your webroot; then customise the copied file to taste.
The index_inlined.html
contains two <script>
sections. The first section
should not be preceded by any other <script>
tags and should be left
verbatim.
The second section should be placed at or close to the end of the <head>
,
and should not precede any direct <link type="stylesheet">
tags.
Inside this second section there is a clearly marked section that is
your configuration area.
The basic structure of a page should be:
lockandload
master script.<title>
.<head>
.lockandload
headready-script.
The index_inlined.html
file is a production-stripped version
of annotated.html
. Look at annotated.html
to understand the code and
read additional inline documentation. These index.*
, lockandload_*.inc
and lockandload_*.js
files are not present in the git source repository, they can only be found in
the npm repository (or after running npm run prepublish
).
Module ids are short strings that uniquely identify a module.
In lockandload
these ids typically do not contain parts of a path.
If a module id is derived from the javascript filename that is being
loaded, it will only refer to the final path component without
.js
or version extension (i.e. anything after the last /
and
before the first .
).
define(id?, dependencies?, factory)
The standard AMD global
entrypoint.
id
declares the module id we are defining. If omitted, we derive
a module id from the name of the javascript file we are loading.dependencies
is an array of strings of module ids this module depends on.
If the parameter is missing, a default dependency list of
["require", "exports", "module"]
is supplied.factory
is the callback function that gets called as soon as
all dependencies have been loaded. The factory function gets
references to all the exported symbols from its dependencies, and
should subsequently return its own symbols it wants to export to
other modules. The factory can be a function or a static object.require(dependencies, callback)
Allows you to load dependencies (an array of strings of module ids)
asynchronously, the callback is called
as soon as all dependencies have loaded. Parameters to the callback
are references to the dependencies just as in the factory function
in define
.
In the secondary lockandload
headready-script; all url arguments
are used verbatim in <link href="url">
or <script src="url">
tags:
css(url, id?)
id
dependency.js(url, "async"?, noCORS?)
"async"
is
provided, the load will be asynchronous. If the third optional
argument is true, the script will be loaded without crossOrigin
parameter (typically needed to load GTM).jsa(alias, path)
require.load(alias)
to load the file on demand.If you use "require"
in your dependencylist, you get a reference to the
internal require-module (which behaves identical to the global require()
).
It supports the following functionality:
require(id)
id
. Beware:
this will not trigger loading that module, if the module is not loaded
because it was already in your dependencylist, or if the module is
not being requested by other modules, this will return zero.
As such, it can be used to find out if a certain module is being loaded
at all.require.undef(id)
id
exported symbols list. This allows the module
to be hot-reloaded by a subsequent require.load()
. Beware that existing
references to the old module are not overwritten. Any modules using
require(id)
before the require.load()
will return zero, any modules
using require(id)
after the require.load()
will return a reference
to the exports of the reloaded module.require.load(file)
jsa()
calls in the
headready section to declare aliases for javascript files which can
be used instead of actual file paths in the require.load()
calls.In order to support legacy code that uses inline $(function(){...})
scattered
throughout pages, this loader allows you to use that construct even before
the jQuery library has been loaded,
and thus enables you to load jQuery in an asynchronous and non-blocking fashion.
N.B. Use the jQuery
dependency instead of plain jquery
to avoid a race
for an undefined window.$
object.
To ease SPA development, the loader defines a
$$(function(jquery_document){...})
function which registers functions
for execution on every SPA-controlled page refresh. The registered functions
receive a convenience argument $(document)
when executed.
To run the registered functions, one needs to make a call to the entrypoint
of the AMD-dependency on domready
without parameters or with exactly
one parameter; if not provided, this single parameter will default to
$(document)
(the jquery object/scope referring to the whole document).
Convention states that if provided the argument should normally be the jquery
object referring to the element tree that contains the changes.
Ultimately you decide what your $$(function(argument){...})
scheduled
scripts will use the argument for. All domready()
calls before domready(1)
has been run will be silently ignored.
E.g. in your application, you could use code like this:
!function(){
// Preamble
define("main", ["domready"], function (domready) {
// Your main application
function refreshpage() {
// The function that gets called on virtual page refreshes
var newdiv = $("#contentdiv");
newdiv.html("your glorious new page content");
domready(newdiv); // This will call all registered $$(...) functions
// with the newdiv as argument to potentially
// limit the scope of the changes
}
});
}();
Other AMD-loaders:
Card-carrying member of the zerodeps
movement.
FAQs
Minimalist AMD-compliant Javascript and CSS loader
We found that lockandload demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.