useref HTML Build Block Parser
useref is a JavaScript library designed to parse HTML files and replace special "build blocks" with optimized references. Extracted from the `grunt-useref` plugin, it provides a standalone utility for integrating into web build processes. The current stable version is 1.4.4, with releases appearing to be on an as-needed basis, focusing on stability and bug fixes as indicated by the versioning. Its primary differentiator is its ability to identify and process `<!-- build:<type> <path> -->...<!-- endbuild -->` comments, consolidating multiple script or link tags into a single optimized reference, and supporting custom block types for advanced processing. It also preserves IE conditional comments. This functionality is crucial for web performance optimization workflows where assets are concatenated and minified.
Common errors
-
useref is not a function
cause Attempting to use `useref` as an ES module default import in a CommonJS context, or vice-versa, or incorrect `require` syntax.fixEnsure you are using `const useref = require('useref');` for CommonJS environments, or configure your build system for proper CommonJS interop if using ES modules. -
TypeError: Cannot read property 'assets' of undefined
cause Occurs when trying to access the second element of the array returned by `useref` (the assets map), but `useref` failed to parse any blocks or the block types were not recognized, leading to an empty or malformed assets object.fixVerify that your HTML contains correctly formatted `<!-- build:<type> ... -->` and `<!-- endbuild -->` blocks, and that the `type` (js, css, remove, or custom) is recognized by `useref`. -
SyntaxError: Unexpected token '<'
cause Passing malformed or non-string HTML content to `useref`, or an issue with internal HTML parsing.fixEnsure the input to `useref()` is a valid HTML string. Check for unclosed tags, invalid comments, or non-string inputs.
Warnings
- gotcha Implementing custom block handlers requires careful attention to the returned HTML. The function must return a valid HTML string that will replace the entire build block content. Incorrectly formatted HTML or unexpected values can lead to malformed output.
- gotcha The 'alternate search path' in build blocks specifies a base path for input files within that block. Misunderstanding its scope or how it interacts with relative paths can lead to incorrect asset resolution in the `assetsMap`.
- gotcha Parameters specified in build blocks (e.g., `async data-foo='bar'`) are directly applied to the generated tag. Overwriting default attributes like `rel` for CSS links should be done carefully to avoid unexpected styling or loading behavior.
Install
-
npm install useref -
yarn add useref -
pnpm add useref
Imports
- useref
import useref from 'useref';
const useref = require('useref');
Quickstart
const useref = require('useref');
const sampleHtml = `
<html>
<head>
<!-- build:css css/combined.css -->
<link href="css/one.css" rel="stylesheet">
<link href="css/two.css" rel="stylesheet">
<!-- endbuild -->
</head>
<body>
<!-- build:js scripts/combined.js -->
<script type="text/javascript" src="scripts/one.js"></script>
<script type="text/javascript" src="scripts/two.js"></script>
<!-- endbuild -->
<!-- build:js scripts/async.js async data-foo="bar" -->
<script type="text/javascript" src="scripts/three.js"></script>
<script type="text/javascript" src="scripts/four.js"></script>
<!-- endbuild -->
</body>
</html>
`;
const [resultHtml, assetsMap] = useref(sampleHtml);
console.log("Transformed HTML:");
console.log(resultHtml);
console.log("\nIdentified Assets:");
console.log(JSON.stringify(assetsMap, null, 2));
/*
Example resultHtml output:
<html>
<head>
<link rel="stylesheet" href="css/combined.css"/>
</head>
<body>
<script src="scripts/combined.js"></script>
<script src="scripts/async.js" async data-foo="bar" ></script>
</body>
</html>
*/
/*
Example assetsMap output:
{
"css": {
"css/combined.css": {
"assets": [
"css/one.css",
"css/two.css"
]
}
},
"js": {
"scripts/combined.js": {
"assets": [
"scripts/one.js",
"scripts/two.js"
]
},
"scripts/async.js": {
"assets": [
"scripts/three.js",
"scripts/four.js"
]
}
}
}
*/