ichigoo
Version:
Static site generator with React and GraphQL
145 lines (122 loc) • 3.92 kB
JavaScript
/**
* Programatically build a static site with parcel
*/
const path = require("path");
const transpile = require("../ops/transpile.js");
const manifest = require("../ops/manifest.js");
const ora = require("ora");
const chalk = require("chalk");
const Bundler = require("parcel-bundler");
const directory = path.resolve(".");
const utils = require("../ops/utils.js");
const static = require("../ops/static.js");
const fs = require("fs");
const scrub = require("../ops/scrub.js");
const gqlData = require("../ops/data.js").generateData;
const processInitialData = require("../ops/data.js").processInitialData;
/**
* Generate SSR file and add it to main project
*/
const generateSSR = () => {
return new Promise((resolve, reject) => {
fs.copyFile(
path.join(__dirname, `../ops/templates/ssr.js`),
path.join(utils.dir(), `src/ssr.js`),
(err) => {
if (err) {
reject(new Error(err));
} else {
resolve();
}
}
);
});
};
/**
* Transpile main project and routes so that we can
* access and execute ES6 code when we want to create the static HTML
*/
const transpileSource = async () => {
const spinner = ora(chalk.grey.bold("Transpiling source files")).start();
await generateSSR();
await transpile.transformDir(path.join(directory, "src"), path.join(directory, "build/src"));
await transpile.transform("routes.js", path.join(directory), path.join(directory, "build"));
await utils.timeout(() => {
spinner.succeed(chalk.green.bold("Source files transpiled!"));
}, 2000);
};
/**
* Generate graphql data file
*/
const createGqlDataFile = async () => {
const spinner = ora(chalk.grey.bold("Generating static data")).start();
const [err, data] = await utils.promiseResolver(gqlData());
await utils.timeout(() => {
utils.spinUtil(spinner, err, {
error: `Trouble generating static data - ${err}`,
success: "Static data created!",
});
}, 2000);
};
/**
* Generate manifest file
*/
const createManifest = async () => {
const spinner = ora(chalk.grey.bold("Generating manifest")).start();
const [err, data] = await utils.promiseResolver(manifest.generateManifest());
await utils.timeout(() => {
utils.spinUtil(spinner, err, {
error: `Trouble generating manifest - ${err}`,
success: "Manifest created!",
});
}, 2000);
};
/**
* Create static HTML files
*
* @param {*} hashedCollections - Collection of bundled files with hash (e.g about.3453ed.js)
*/
const createStatic = async (hashedCollections) => {
const spinner = ora(chalk.grey.bold("Generating static files")).start();
const [err, data] = await utils.promiseResolver(static.generateStatic(hashedCollections));
await utils.timeout(() => {
utils.spinUtil(spinner, err, {
error: err,
success: "Static files successfully generated!",
});
}, 2000);
return data;
};
/**
* Bundle manifest and create static file
*/
const runBundle = async () => {
return new Promise(async (resolve, reject) => {
const bundling = new Bundler([path.join(utils.dir(), "./manifest.html")], {
watch: false,
});
bundling.on("bundled", async (bundle) => {
const hashedCollections = {};
for (let asset of bundle.childBundles) {
hashedCollections[asset.entryAsset.basename] = asset.name.match(/[^\\/]+$/)[0];
}
const data = await createStatic(hashedCollections);
await scrub();
if (data) {
console.log("");
for (let [key, value] of Object.entries(data)) {
console.log(`${chalk.grey(`dist/`)}${chalk.cyan.bold(`${data[key].name}.html`)}`);
}
}
});
const bundle = await bundling.bundle();
});
};
const build = async () => {
await processInitialData();
await transpileSource();
await createGqlDataFile();
await createManifest();
await runBundle();
};
module.exports = build;