Skip to content

Commit

Permalink
Merge branch 'v2' into mszczepanski/migrate-to-swc-core
Browse files Browse the repository at this point in the history
  • Loading branch information
alshdavid authored Jul 16, 2023
2 parents d009ad6 + d84385d commit 5f4fe64
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 1 deletion.
2 changes: 1 addition & 1 deletion flow-libs/commander.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ declare module 'commander' {
[key: string]: any;
}

declare class commander$Command {
declare export class commander$Command {
constructor(name?: string): commander$Command;

args: string[];
Expand Down
4 changes: 4 additions & 0 deletions packages/dev/bundle-stats-cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# bundle-stats-cli

- Run `yarn link` in `packages/dev/bundle-stats-cli`
- Run `parcel-bundle-stats` in the project root, a `parcel-bundle-reports` directory will be created with the stats file inside
12 changes: 12 additions & 0 deletions packages/dev/bundle-stats-cli/bin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#! /usr/bin/env node

/* eslint-disable no-console */
// @flow strict-local
'use strict';

// $FlowFixMe[untyped-import]
require('@parcel/babel-register');

const cli = require('./src/cli');

cli.command.parse();
25 changes: 25 additions & 0 deletions packages/dev/bundle-stats-cli/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "@parcel/bundle-stats-cli",
"version": "2.9.3",
"private": true,
"main": "lib/cli.js",
"source": "src/cli.js",
"bin": {
"parcel-bundle-stats": "bin.js"
},
"engines": {
"node": ">= 12.0.0",
"parcel": "^2.9.3"
},
"dependencies": {
"@parcel/reporter-bundle-stats": "^2.9.3",
"@parcel/core": "^2.9.3",
"@parcel/utils": "^2.9.3",
"commander": "^7.0.0",
"parcel-query": "^2.9.3"
},
"devDependencies": {
"@parcel/babel-register": "^2.9.3",
"@parcel/types": "^2.9.3"
}
}
84 changes: 84 additions & 0 deletions packages/dev/bundle-stats-cli/src/cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/* eslint-disable no-console, monorepo/no-internal-import */
// @flow strict-local

import type {PackagedBundle} from '@parcel/types';
import type {ParcelOptions} from '@parcel/core/src/types';

// $FlowFixMe[untyped-import]
import {version} from '../package.json';

import commander from 'commander';
import fs from 'fs';
import path from 'path';

import {DefaultMap} from '@parcel/utils';

import {loadGraphs} from 'parcel-query/src/index.js';
import {getBundleStats} from '@parcel/reporter-bundle-stats/src/BundleStatsReporter';
import {PackagedBundle as PackagedBundleClass} from '@parcel/core/src/public/Bundle';
import type {commander$Command} from 'commander';

function run({cacheDir, outDir}) {
// 1. load bundle graph and info via parcel~query
let {bundleGraph, bundleInfo} = loadGraphs(cacheDir);

if (bundleGraph == null) {
console.error('Bundle Graph could not be found');
process.exit(1);
throw new Error();
}

if (bundleInfo == null) {
console.error('Bundle Info could not be found');
process.exit(1);
throw new Error();
}

// 2. generate stats files for each target
fs.mkdirSync(outDir, {recursive: true});

let projectRoot = process.cwd();

// $FlowFixMe[unclear-type]
let parcelOptions: ParcelOptions = ({projectRoot}: any);

let bundlesByTarget: DefaultMap<
string /* target name */,
Array<PackagedBundle>,
> = new DefaultMap(() => []);
for (let bundle of bundleGraph.getBundles()) {
bundlesByTarget
.get(bundle.target.name)
.push(
PackagedBundleClass.getWithInfo(
bundle,
bundleGraph,
parcelOptions,
bundleInfo.get(bundle.id),
),
);
}

for (let [targetName, bundles] of bundlesByTarget) {
fs.writeFileSync(
path.join(outDir, `${targetName}-stats.json`),
JSON.stringify(getBundleStats(bundles, parcelOptions), null, 2),
);
}
}

export const command: commander$Command = new commander.Command()
.version(version, '-V, --version')
.description('Generate a stats report for a Parcel build')
.option('-v, --verbose', 'Print verbose output')
.option(
'-c, --cache-dir <path>',
'Directory to the parcel cache',
'.parcel-cache',
)
.option(
'-o, --out-dir <path>',
'Directory to write the stats to',
'parcel-bundle-reports',
)
.action(run);
24 changes: 24 additions & 0 deletions packages/reporters/bundle-stats/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "@parcel/reporter-bundle-stats",
"version": "2.9.3",
"publishConfig": {
"access": "public"
},
"main": "lib/BundleStatsReporter.js",
"source": "src/BundleStatsReporter.js",
"bin": {
"parcel-bundle-stats": "bin.js"
},
"engines": {
"node": ">= 12.0.0",
"parcel": "^2.3.1"
},
"dependencies": {
"@parcel/core": "^2.9.3",
"@parcel/plugin": "^2.9.3",
"@parcel/utils": "^2.9.3"
},
"devDependencies": {
"@parcel/types": "^2.9.3"
}
}
99 changes: 99 additions & 0 deletions packages/reporters/bundle-stats/src/BundleStatsReporter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// @flow strict-local

import type {PackagedBundle, PluginOptions} from '@parcel/types';

import {Reporter} from '@parcel/plugin';
import {DefaultMap} from '@parcel/utils';

import assert from 'assert';
import path from 'path';

export type AssetStat = {|
size: number,
name: string,
bundles: Array<string>,
|};

export type BundleStat = {|
size: number,
id: string,
assets: Array<string>,
|};

export type BundleStats = {|
bundles: {[key: string]: BundleStat},
assets: {[key: string]: AssetStat},
|};

export default (new Reporter({
async report({event, options}) {
if (event.type !== 'buildSuccess') {
return;
}

let bundlesByTarget: DefaultMap<
string /* target name */,
Array<PackagedBundle>,
> = new DefaultMap(() => []);
for (let bundle of event.bundleGraph.getBundles()) {
bundlesByTarget.get(bundle.target.name).push(bundle);
}

let reportsDir = path.join(options.projectRoot, 'parcel-bundle-reports');
await options.outputFS.mkdirp(reportsDir);

await Promise.all(
[...bundlesByTarget.entries()].map(([targetName, bundles]) =>
options.outputFS.writeFile(
path.join(reportsDir, `${targetName}-stats.json`),
JSON.stringify(getBundleStats(bundles, options), null, 2),
),
),
);
},
}): Reporter);

export function getBundleStats(
bundles: Array<PackagedBundle>,
options: PluginOptions,
): BundleStats {
let bundlesByName = new Map<string, BundleStat>();
let assetsById = new Map<string, AssetStat>();

// let seen = new Map();

for (let bundle of bundles) {
let bundleName = path.relative(options.projectRoot, bundle.filePath);

// If we've already seen this bundle, we can skip it... right?
if (bundlesByName.has(bundleName)) {
// Sanity check: this is the same bundle, right?
assert(bundlesByName.get(bundleName)?.size === bundle.stats.size);
continue;
}

let assets = [];
bundle.traverseAssets(({id, filePath, stats: {size}}) => {
assets.push(id);
let assetName = path.relative(options.projectRoot, filePath);
if (assetsById.has(id)) {
assert(assetsById.get(id)?.name === assetName);
assert(assetsById.get(id)?.size === size);
assetsById.get(id)?.bundles.push(bundleName);
} else {
assetsById.set(id, {name: assetName, size, bundles: [bundleName]});
}
});

bundlesByName.set(bundleName, {
id: bundle.id,
size: bundle.stats.size,
assets,
});
}

return {
bundles: Object.fromEntries(bundlesByName),
assets: Object.fromEntries(assetsById),
};
}

0 comments on commit 5f4fe64

Please sign in to comment.