Asset & Helpers Plugins
Examine the static asset loader and SSR require manifest builder files inside the Rollup setup.
Key Files Location:
• Asset Loader:./dinou/rollup/rollup-plugins/dinou-asset-plugin.js
• Chunk Mapper:./dinou/rollup/rollup-plugins/manifest-generator-plugin.js
💡 Overview
In a custom React Server Component framework, assets (like images or stylesheets) must be copied to the public directory and mapped appropriately.
The asset plugin intercepts asset imports, copies them to the final build location with a content hash, and changes imports to return the public path string. The manifest generator outputs mapping metadata files so that references can be dynamically reconstructed on client runs.
📊 Assets Plugin Flow
The flowchart below shows how static files are intercepted, scoped, and resolved from JavaScript chunks:
📊 Manifest Generator Flow
The flowchart below shows how entrypoint names are mapped to final hashed filenames in the build manifest:
⚙️ dinou-asset-plugin.js Walkthrough
Below is the full code of the Rollup assets extraction plugin:
const fs = require("fs");
const path = require("path");
const createScopedName = require("../../core/createScopedName.js");
const { regex } = require("../../core/asset-extensions.js");
function dinouAssetPlugin({ include = regex } = {}) {
return {
name: "dinou-asset-plugin",
async load(id) {
if (!include.test(id)) return null;
const source = await fs.promises.readFile(id);
const base = path.basename(id, path.extname(id));
const scoped = createScopedName(base, id);
const ext = path.extname(id);
const fileName = `assets/${scoped}${ext}`;
this.emitFile({
type: "asset",
fileName,
source,
});
return `export default '/assets/${scoped}${ext}';`;
},
};
}
module.exports = dinouAssetPlugin;⚙️ manifest-generator-plugin.js Walkthrough
Below is the full code of the build manifest generator plugin:
let manifestData = {};
function manifestGeneratorPlugin() {
return {
name: "manifest-generator",
generateBundle(options, bundle) {
for (const [fileName, info] of Object.entries(bundle)) {
if (info.type === "chunk" && info.name) {
const cleanName = info.name + ".js";
manifestData[cleanName] = fileName;
}
}
this.emitFile({
type: "asset",
fileName: "manifest.json",
source: JSON.stringify(manifestData, null, 2),
});
},
};
}
manifestGeneratorPlugin.manifestData = manifestData;
module.exports = manifestGeneratorPlugin;