SkillAgentSearch skills...

Assetgraph

Optimization framework for web pages and applications

Install / Use

/learn @assetgraph/Assetgraph
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

AssetGraph

NPM version Build Status Coverage Status Dependencies Status

AssetGraph is an extensible, <a href="http://nodejs.org/">node.js</a>-based framework for manipulating and optimizing web pages and web applications. The main core is a dependency graph model of your entire website, where all assets are treated as first class citizens. It can automatically discover assets based on your declarative code, reducing the configuration needs to a minimum.

If you just want to get started with the basics, read Peter Müller - Getting started with Assetgraph.

If you are looking for a prepackaged build system take a look at <a href="https://github.com/assetgraph/assetgraph-builder">Assetgraph-builder</a>.

Tools built with AssetGraph

  • assetgraph-builder - A static web page build system that post-processes your website with extremely little configuration
  • subfont - A tool that supercharges your webfont loading by automatically applying all best practice loading techniques and generating optimal font subsets
  • hyperlink - A link checker tool that will ensure all your internal and external links are intact and up to date
  • seespee - A Content-Security Policy generator. Point it at a webpage and it will tell you what policy you need as a minimum
  • trackingdog - cli for finding the original source location of a line+column in a generated file, utilizing the source map
  • bringhome - cli for downloading a web page and its assets to a local directory.

Assets and relations

All web build tools, even those that target very specific problems, have to get a bunch of boring stuff right just to get started, such as loading files from disc, parsing and serializing them, charsets, inlining, finding references to other files, resolution of and updating urls, etc.

The observation that inspired the project is that most of these tasks can be viewed as graph problems, where the nodes are the assets (HTML, CSS, images, JavaScript...) and the edges are the relations between them, e.g. anchor tags, image tags, favorite icons, css background-image properties and so on.

An example illustration of an asset graph representing a web page

An AssetGraph object is a collection of assets (nodes) and the relations (edges) between them. It's a basic data model that allows you to populate, query, and manipulate the graph at a high level of abstraction. For instance, if you change the url of an asset, all relations pointing at it are automatically updated.

Additionally, each individual asset can be inspected and massaged using a relevant API: <a href="https://github.com/tmpvar/jsdom">jsdom</a> for HTML, <a href="https://github.com/postcss/postcss">PostCSS</a> for CSS, and an <a href="http://esprima.org/">Esprima</a> AST for Javascript.

AssetGraph represents inline assets the same way as non-inline ones, so eg. inline scripts, stylesheets, and images specified as data: urls are also first-class nodes in the graph. This means that you don't need to dig into the HTML of the containing asset to manipulate them. An extreme example would be an Html asset with a conditional comment with an inline stylesheet with an inline image, which are modelled as 4 separate assets:

<!DOCTYPE html>
<html>
  <head>
    <!--[if !IE]> -->
    <style type="text/css">
      body {
        background-image: url(data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==);
      }
    </style>
    <!-- <![endif]-->
  </head>
  <body></body>
</html>

These are some of the supported assets and associated relation types:

HTML

<a>, <link rel="stylesheet|shortcut icon|fluid-icon|alternate|serviceworker">, <script>, <style>, <html manifest="..."> <img>, <video>, <audio>, <applet>, <embed>, <esi:include>, <iframe>, <svg>, <meta property="og:...">

SVG

<style>, inline style=... attributes, event handlers, <?xml-stylesheet href=...>, <font-face-src>

CSS

//# sourceMappingURL=..., background-image: url(...), @import url(...), behavior: url(...), filter: AlphaImageLoader(src='...'), @font-face { src: url(...) }

JavaScript

//# sourceMappingURL=..., homegrown 'foo/bar.png'.toString('url') syntax for referencing external files

Web manifest

Icon urls, related_applications, start_url, etc.

Cache manifest (appcache)

Entries in the CACHE, NETWORK and FALLBACK sections

JSON, XML, PNG, GIF, JPEG, ICO

(none)

Features

  • Build an AssetGraph programmatically or load it from disk or a remote server via http.
  • Find explicit dependencies between JavaScript and CSS and roll them out as <script> and <link rel='stylesheet'> tags in your HTML.
  • Bundle and inline CSS and JavaScript.
  • Create a cache manifest with references to all the assets your web app needs to be usable offline.
  • Move all CSS, JavaScript, image assets etc. to a static dir and rename them to md5.extension so the web server can be configured to set a far-future Cache-Control.
  • Help getting your static assets on a CDN by allowing you to easily rewrite all references to them.
  • Use Graphviz to visualize your dependencies at any step.
  • Using the separate <a href="https://github.com/assetgraph/assetgraph-sprite">assetgraph-sprite transform</a>: Optimize CSS background images by creating sprite images. The spriting is guided by a set of custom CSS properties with a -ag-sprite prefix.

Installation

Make sure you have <a href="http://nodejs.org/">node.js</a> and <a href="http://npmjs.org/">npm</a> installed, then run:

$ npm install assetgraph

Querying the graph

AssetGraph supports a flexible syntax for finding assets and relations in a populated graph using the findAssets and findRelations methods. Both methods take a query object as the first argument. The query engine uses MongoDB-like queries via the sift module. Please consult that to learn about the advanced querying features. Below are some basic examples.

Get an array containing all assets in the graph:

var allAssets = assetGraph.findAssets();

Find assets by type:

var htmlAssets = assetGraph.findAssets({ type: 'Html' });

Find assets of different named types:

var jsAndCss = assetGraph.findAssets({ type: { $in: ['Css', 'JavaScript' ] });

Find assets by matching a regular expression against the url:

var localImageAssets = assetGraph.findAssets({
  url: { $regex: /^file:.*\.(?:png|gif|jpg)$/ },
});

Find assets by predicate function:

var orphanedJavaScriptAssets = assetGraph.findAssets(function (asset) {
  return (
    asset.type === 'JavaScript' &&
    assetGraph.findRelations({ to: asset }).length === 0
  );
});

Find all HtmlScript (<script src=...> and inline <script>) relations:

var allHtmlScriptRelations = assetGraph.findRelations({ type: 'HtmlScript' });

Query objects have "and" semantics, so all conditions must be met for a multi-criteria query to match:

var textBasedAssetsOnGoogleCom = assetGraph.findAssets({
  isText: true,
  url: { $regex: /^https?:\/\/(?:www\.)google\.com\// },
});

Find assets by existence of incoming relations:

var importedCssAssets = assetGraph.findAssets({
  type: 'Css',
  incomingRelations: { $elemMatch: { type: 'CssImport' } },
});

Relation queries can contain nested asset queries when querying the to and from properties.

Find all HtmlAnchor (<a href=...>) relations pointing at local images:

assetGraph.findRelations({
  type: 'HtmlAnchor',
  to: { isImage: true, url: { $regex: /^file:/ } },
});

Transforms and workflows

AssetGraph comes with a collection of premade "transforms" that you can use as high level building blocks when putting together your build procedure. Most transforms work on a set of assets or relations and usually accept a query object so they can be scoped to work on only a specific subset of the graph.

Usually you'll start by loading some initial assets from disc or via http using the loadAssets transform, then get the related assets added using the populate transform, then do the actual processing. Eventually you'll probably write the resulting assets back to disc.

Thus the skeleton looks something like this:

var AssetGraph = require('assetgraph');

const assetGraph = new AssetGraph({ root: '/the/root/directory/' });

await assetGraph.loadAssets('*.html'); // Load all Html assets in the root dir
await assetGraph.populate({ followRelations: { type: 'HtmlAnchor' } }); // Follow <a href=...>
// More work...
await assetGraph.writeAssetsToDisc({ type: 'Html' }); // Overwrite existing files

// Done!

In the following sections the built-in transforms are documented individually:

assetGraph.addCacheManifest([queryObj])

Add a CacheManifest asset to each Html asset in the graph (or to all Html assets matched by queryObj if provided). The cache manifests will contain relations to all assets reachable by traversing the graph through relations other than HtmlAnchor.

assetGraph.bundleRelations(queryObj[, strategyName

Related Skills

View on GitHub
GitHub Stars898
CategoryDevelopment
Updated29d ago
Forks55

Languages

JavaScript

Security Score

95/100

Audited on Mar 5, 2026

No findings