Outlined below are three common approaches to integrating an asset manifest like the one gulp-rev outputs into an application.
For our examples, we'll assume the following rev-manifest.json
:
{
"js/app.js": "js/app-5c41412f32.js",
"js/lib.js": "js/lib-6d94673e3d.js",
"css/app.css": "css/app-a4ae3dfa4d.css"
}
One approach to working with rev-manifest.json
is to use a templating language, such as handlebars, to generate an index.html
file which contained your fingerprinted files embedded into the page.
The idea is to read in your app's rev-manifest.json
, and use the non-fingerprinted path to read in the fingerprinted path and inject it into the page. Note, this approach requires the 'compile-index-html'
task to be run as part of your build process.
<!doctype html>
<html>
<head>
<title>My App</title>
<link rel="stylesheet" href="{{ assetPath "css/app.css" }}">
</head>
<body>
<script src="{{ assetPath "js/lib.js" }}"></script>
<script src="{{ assetPath "js/app.js" }}"></script>
</body>
</html>
import fs from 'node:fs';
import gulp from 'gulp';
import handlebars from 'gulp-compile-handlebars';
import rename from 'gulp-rename';
// Create a handlebars helper to look up
// fingerprinted asset by non-fingerprinted name
const handlebarOptions = {
helpers: {
assetPath: (path, context) => ['/assets', context.data.root[path]].join('/')
}
};
export const compileIndexHtml = () => {
// Read in our manifest file
const manifest = JSON.parse(fs.readFileSync('path/to/rev-manifest', 'utf8'));
// Read in our handlebars template, compile it using
// our manifest, and output it to index.html
return gulp.src('index.hbs')
.pipe(handlebars(manifest, handlebarOptions))
.pipe(rename('index.html'))
.pipe(gulp.dest('public'));
};
Another approach would be to make a AJAX request to get the manifest JSON blob, then use the manifest to programmatically find the fingerprinted path to any given asset.
For example, if you wanted to include your JavaScript files into the page:
$.getJSON('/path/to/rev-manifest.json', manifest => {
const s = document.getElementsByTagName('script')[0];
const assetPath = source => {
source = `js/${source}.js`;
return ['/assets', manifest[source]].join('/');
};
for (const source of ['lib', 'app']) {
const element = document.createElement('script');
element.async = true;
element.src = assetPath(source);
s.parentNode.insertBefore(element, s);
}
})
The above example assumes your assets live under /assets
on your server.
This example PHP function provides the correct filename by reading it from the JSON manifest.
If the file is not present in the manifest it will return the original filename.
/**
* @param string $filename
* @return string
*/
function asset_path($filename) {
$manifest_path = 'assets/rev-manifest.json';
if (file_exists($manifest_path)) {
$manifest = json_decode(file_get_contents($manifest_path), TRUE);
} else {
$manifest = [];
}
if (array_key_exists($filename, $manifest)) {
return $manifest[$filename];
}
return $filename;
}
You can then call asset_path
to get the rev'd path of your assets: echo asset_path('js/main.js');
Using blade your templates would look like this:
<!doctype html>
<html>
<head>
<title>My App</title>
<link rel="stylesheet" href="{{ asset_path('css/app.css') }}">
</head>
<body>
<script src="{{ asset_path('js/lib.js') }}"></script>
<script src="{{ asset_path('js/app.js') }}"></script>
</body>
</html>