Static compilation is like pre-computation; most of the dynamism (typically from unchanging data sources) of each web page is rendered server-side one-time, and stored into simpler html files. How does one introduce custom code blocks involving compile-time code into static pages? One example introduced below is to render the date-time of the .md files into their corresponding precomputed pages.
enhanceApp.js again
This file is possibly the only entry point to injecting compile-time code. Here's the snippet on iterating the ./docs folder to discover .md files.
function updatePageModifiedDates(siteData) {
// run this code only during BUILD
if (!process.env.NODE_ENV || process.env.NODE_ENV != 'production')
return null;
let RootPath = process.cwd() + '/docs';
let result = getPageModifiedDate(RootPath);
Object.keys(result).forEach((key) => {
result[key.substring(RootPath.length)] = result[key];
delete result[key];
});
// update siteData.pages.frontmatter.lastUpdated
siteData.pages.forEach((page) => {
if (result[page.path]) {
page.frontmatter.LastModified = result[page.path];
console.log('%s updated', page.path);
}
});
Object.keys(result).forEach((key) => {
console.log('Key %s: %s', key, result[key]);
});
return result;
}
function getPageModifiedDate(ScanPath) {
// no async calls here
let ScanResult = {};
let items = fs.readdirSync(ScanPath);
items.forEach((item) => {
// ignore everything that starts with .
if (!item.match(/^\./)) {
let ItemFullPath = ScanPath + '/' + item;
let FileModifiedDate = getFileModifiedDate(ItemFullPath);
if (FileModifiedDate) {
// only record .md filenames
if (item.match(/\.md$/)) {
let FinalPagePath;
if (item === 'README.md') {
// transform */README.md to */
FinalPagePath = ScanPath + '/';
} else {
// transform */*.md to */*.html
let DotHtml = item.replace(/\.md/,'.html');
FinalPagePath = ScanPath + '/' + DotHtml
}
ScanResult[FinalPagePath] = FileModifiedDate;
}
} else {
let subresult = getPageModifiedDate(ItemFullPath);
Object.keys(subresult).forEach((key) => {
ScanResult[key] = subresult[key];
});
}
}
});
return ScanResult;
}
function getFileModifiedDate(QueryFile) {
let stats = fs.statSync(QueryFile);
if (!stats.isFile())
// not file
return null;
return moment(stats.mtime);
}
Notes
- enhanceApp.js is run for every page generated. In other words if there are 10 .md files enhanceApp.js is run 10 times.
- Vue components still render client-side; this can cause unexpected behaviors and inconsistency between the .html content and the final render on the browser.