
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
@style.tools/async
Advanced tools
A lightweight and high performance async CSS and script loader for frontend optimization.
$async Async CSS and Script LoaderA lightweight and high performance async CSS and script loader with state of the art features for frontend optimization (FEO).
npm install @style.tools/async --save
composer require styletools/async
$async([
'sheet.css',
'script.js'
]).then(function() { /* ready */ });
$async can be controlled from a HTML attribute which enables strict security.
<!-- config via an HTML attribute -->
<script async src="js/async-iife.js" data-c='[
[
"css/sheet1.css",
"js/script.js",
{
"href": "https://cdn.com/css/sheet2.css",
"attributes": {
"integrity": "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC",
"crossorigin": "anonymous"
}
},
{
"src": "https://cdn.com/js/script2.js",
"attributes": {
"integrity": "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC",
"crossorigin": "anonymous"
},
"load_timing": "domReady",
"ref": "x"
},
{
"src": "js/script3.js",
"dependencies": "x"
}
],
{
"render_timing": "requestAnimationFrame",
"exec_timing": {
"type": "requestIdleCallback",
"timeout": 1000
}
}
]'></script>
The JSON configuration can be compressed to save size in the HTML (online compressor).
<script async src="js/async-iife.js" data-c='[["css/sheet1.css","js/script.js",{"4":"https://cdn.com/css/sheet2.css","14":{"integrity":"sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC","crossorigin":"anonymous"}},{"5":"https://cdn.com/js/script2.js","14":{"integrity":"sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC","crossorigin":"anonymous"},"16":"x","48":54},{"5":"js/script3.js","15":"x"}],{"49":52,"60":{"2":53,"57":1000}}]'></script>
Documentation is available on docs.style.tools/async.
$async is designed as the ultimate CSS and script loader for modern frontend optimization (FEO). It provides state of the art features, the absolute best performance and the tiniest HTML footprint. $async supports all browsers including IE9+.
$async is modular and easy to use: select only the features that are needed to achieve the tiniest script size.
!function(){/* stitched modules */}();. Follow the module order in package.json.$async
.on('load',function(sheet, sheetEl){
// sheet.css or other-sheet.css loaded
})
.on('sheet-ref',function() { }) // sheet with ref-name loaded
.on('sheet.css', function() {}); // sheet with href loaded
.load({
href: 'sheet.css',
ref: 'sheet-ref'
})
.then(function() { }) // sheet.css loaded
.load('other-sheet.css');
$async supports a strict Content-Security-Policy (CSP) and SRI security by using a HTML attribute on the script element. The data-c attribute accepts JSON config.
<script async src="js/async.js" data-c='[
[
"css/sheet1.css",
{
"href": "https://cdn.com/css/sheet2.css",
"attributes": {
"integrity": "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC",
"crossorigin": "anonymous"
}
}
]
]'></script>
$async provides advanced loading and timing techniques.
requestAnimationFrame, requestIdleCallback and $lazy (Intersection Observer).Media Query based loading with cross-browser support for viewport changes.just-in-time loading using a custom javascript method.$async(
[
"sheet.css",
{
href:"other-sheet.css",
dependencies: ["sheet.css"], // wait for sheet.css via dependencies
load_timing: {
type: "lazy", // use $lazy for timing (Intersection Observer)
config: [".selector-in-view", 0, "200px"], // visible within 200 pixels
},
ref: "other"
},
{
href:"mobile-sheet.css",
dependencies: "other", // dependency by ref
target: {
after: "meta[charset]" // control insert target
},
load_timing: {
type: "media", // download stylesheet based on a media query (works with viewport changes, e.g. viewport rotate)
media: "screen and (max-width: 600px)"
}
},
{
inline: "inline_script_with_timing_and_dependency();",
ref: "inline-code"
},
{
src: "script.js",
exec_timing: "requestIdleCallback",
dependencies: "inline-code"
}
],
/* global options: applied to all stylesheets */
{
// base directory for relative sheet URLs
base: "/long/path/to/css/",
// render timing: paint sheet with requestAnimationFrame
render_timing: "requestAnimationFrame"
}
)
.then(function() { /* ready */ });
just-in-time loading$async(
{
href:"popup-css.css",
load_timing: {
type: "method", // trigger download using custom javascript method
method: "load_popup_css"
}
},{
src:"popup-script.js",
load_timing: {
type: "method",
method: "load_popup_js"
}
}
);
// just-in-time loading
jQuery('button.popup').on('click', function() {
// user clicks a button
// load popup script/css just-in-time
load_popup_css().then(function() {
alert('popup CSS loaded');
});
load_popup_js().then(function() {
alert('popup script loaded');
});
});
$async provides API's for access to the dependency resolver and timing methods.
// dependency resolver
$async.dependencies(['name'], function() { /* dependency loaded */ });
// timing method
$async.time("requestAnimationFrame", function() { /* callback */ });
$async.time(48, function() {}); // the same using the JSON compression index key for 'requestAnimationFrame'
localStorage cache$async enables to load stylesheets and script from localStorage or Cache API cache which is much faster than browser cache.
For a demo, see css-art.com.
$async({
href: "sheet.css",
cache: {
type: "localstorage",
max_size: 10000, // cache only <10kb
fallback: "cache-api", // fallback to Cache-API for bigger sheets
update: {
head: true, // use HTTP HEAD request to check for 304 - Not Modified
interval: 86400 // update once per day
},
// control the source methods
source: ["cssText","xhr","cors"], // default
// optional: CORS proxy for retrieving the source code from external stylesheet URLs
cors: {
proxy: "https://cors-anywhere.herokuapp.com/", // more proxies on https://gist.github.com/jimmywarting/ac1be6ea0297c16c477e17f8fbe51347
},
// custom XHR config
xhr: {
headers: {
"x-special-header": "secret-key" // request header to include in XHR requests
}
}
}
});
$async provides a JSON compression technique to minimize the size of configuration.
Online compressor | Node.js/CLI
/* original config:
{
"href":"other-sheet.css",
"dependencies": ["sheet.css"],
"load_timing":{
"type":"lazy",
"config": [".selector-in-view",0,"200px"]
},
"ref":"other"
} */
// compressed
$async({"4":"other-sheet.css","15":["sheet.css"],"16":"other","48":{"2":62,"89":[".selector-in-view",0,"200px"]}});
$async provides an innovation to capture and rewrite, remove or modify/optimize script-injected stylesheets and scripts. The solution supports both native DOM insert method rewriting and MutationObserver.
// capture and remove async script-injected sheet
$async.capture(
[
{
match: "bloated-sheet.css",
action: {
"type": "remove"
}
},
{
match: "/<script[^>]+bloated-script-id[^>]+>/",
regex: true,
match_type: "node",
action: {
"type": "remove"
}
},
{
match: "external-widget.com",
action: {
type: "rewrite",
search: '/^.*cdn\.external-widget\.com/(.*).css$',
regex: true,
replace: "/local-nginx-proxy/$1.css",
async: {
"load_timing": "requestIdleCallback",
"target": {
"after": "media[charset]"
},
"attributes": {
"data-cdn": "external-widget.com"
}
}
}
},
{
match: "customer-review.js",
action: {
async: {
"load_timing": {
type: 'lazy',
config: '#customer-review' // load script when customer review widget enters viewport
}
}
}
}
],
{
insert: true // use DOM insert method rewriting
// observer: true // alternative: use MutationObserver
}
);
$async provides a debug mode with advanced Performance API timings that enables to analyse and optimize the CSS and script loading performance.

$async is in use on www.e-scooter.co (demo website) and css-art.com (test environment).
FAQs
A lightweight and high performance async CSS and script loader for frontend optimization.
We found that @style.tools/async 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.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.