@feedzai/feedzai-config
Version:
Feedzai's config for repo-analyzer
188 lines (165 loc) • 6.07 kB
JavaScript
var _ = require("lodash");
const logger = require("pino")({
prettyPrint: { colorize: true },
translateTime: true
});
const {
isInstalled,
METRIC_GROUPS,
executeCommand,
getFileFolder,
} = require("@feedzai/analyzer-utilities");
var fs = require("fs");
const { getRepoName } = require("@feedzai/analyzer-utilities/repoMethods");
const BaseMetric = require("@feedzai/analyzer-utilities/Base.metric");
/**
* BundleSizeMetric
*
* This class implements the coverage metric
*
* @author Henrique Dias (henrique.dias@feedzai.com)
*
* @extends BaseMetric
*/
class BundleSizeMetric extends BaseMetric {
/**
* Used to specify details about this metric.
* @returns {object}
*/
info() {
return {
name: "Bundle size",
group: METRIC_GROUPS.RANDOM
};
}
schema() {
return {
"css": {
"type": "float"
},
"js":
{
"type": "float"
}
}
}
/**
* Decides whether the metric can be ran in current repository or not.
* @returns {boolean}
*/
async verify() {
if (_.isObject(this.getPackage()) && _.isObject(this.getPackage().scripts)
&& _.isString(this.getPackage().scripts.build)) {
if (!isInstalled(this.repoFolder)) {
logger.error(`Must run 'npm install' on '${this.getRepoFolder()}' 1st`);
return false;
}
return true;
}
return false;
}
/**
* Used to execute the bundle size command and parse the results.
* @returns {Object}
*/
async runWebpack() {
let result;
if (this.getPackage().name === "feedzai-ui-kit") {
result = await executeCommand(this.getRepoFolder(),
"npm run clean && npm run build:webpack -- --hide-modules --profile --json > bundlestats.json ");
}
else {
result = await executeCommand(this.getRepoFolder(),
"npm run build -- --hide-modules --profile --json > bundlestats.json");
}
if (!result) {
logger.error("Error executing 'webpack'");
}
let parsedOutput;
return await getFileFolder(`${this.getRepoFolder()}`, "bundlestats.json").then((bundlestats) => {
if (!_.isString(bundlestats)) {
logger.error(`Make sure that webpack is setup correctly on '${this.getRepoFolder()}' `);
return null;
}
try {
parsedOutput = JSON.parse(bundlestats);
} catch (e) {
// JSON format invalid, maybe 1st line incorrect?
// deletes 1st line
bundlestats = bundlestats.substring(bundlestats.indexOf("{"));
if (bundlestats.search("Webpack Bundle Analyzer saved report to ") !== -1) {
const lines = bundlestats.split("\n");
lines.splice(0, 1);
bundlestats = lines.join("\n");
}
// tries to parse again
try {
parsedOutput = JSON.parse(bundlestats);
} catch (e2) {
logger.error("Imposible to parse Webpack output");
}
}
if (_.isObject(parsedOutput)) {
return parsedOutput;
}
return null;
});
}
/**
* Returns the calculated metric.
* @returns {Object}
*/
async execute() {
if (this.getPackage().scripts.build.includes("rollup")) {
const result = await executeCommand(this.getRepoFolder(), "yarn build react/index,react-dom/index --type=UMD");
return await getFileFolder(`${this.getRepoFolder()}`, "./build/bundle-sizes.json").then((fileOutput) => {
try {
const bundlestats = JSON.parse(fileOutput);
let jsbundlesize = 0;
bundlestats.bundleSizes.forEach(element => {
if (element.filename == "react.production.min.js" || element.filename == "react-dom.production.min.js")
jsbundlesize = element.size
});
return {
result: {
// Divide by 1000 to get the kb size
// After having the result in MB, it multiply by 100 and divide by 100 to have decimal palces in the output
js: Math.round((jsbundlesize / 1000 / 1000) * 100) / 100,
css: 0
}
}
} catch (e) {
return {
result: {
js: 0,
css: 0
}
}
}
});
} else {
return await this.runWebpack().then((stats) => {
if (!_.isObject(stats)) {
return null;
}
let sizeCss = 0, sizeJs = 0;
stats.assets.forEach((asset) => {
if (asset.name.includes(".css")) {
sizeCss += asset.size;
} else if (asset.name.includes(".js")) {
sizeJs += asset.size;
}
});
return {
result: {
// here I divide by 1024 to times in order to covert from bytes to MBytes
// After having the result in MB, it multiply by 100 and divide by 100 to have decimal palces in the output
css: Math.round((sizeCss / 1024 / 1024) * 100) / 100,
js: Math.round((sizeJs / 1024 / 1024) * 100) / 100
}
};
});
}
}
}
module.exports = BundleSizeMetric;