Skip to content

Commit cb56358

Browse files
authored
Add printing asset stats to Webpack plugin (#32)
* webpack-plugin: add webpack build for testing * webpack-plugin: add asset stats printing * webpack plugin: changes info logs to log --------- Co-authored-by: Sebastian Alex <sebastian.alex@saucelabs.com>
1 parent e16e076 commit cb56358

File tree

7 files changed

+134
-22
lines changed

7 files changed

+134
-22
lines changed

package-lock.json

Lines changed: 10 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/webpack-plugin/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
webpackBuild/

tools/webpack-plugin/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
},
1010
"scripts": {
1111
"build": "tsc -b ./tsconfig.build.json",
12+
"build:webpack": "webpack",
1213
"clean": "tsc -b ./tsconfig.build.json --clean && rimraf \"lib\"",
1314
"format": "prettier --write '**/*.ts'",
1415
"lint": "eslint . --ext .ts",
@@ -45,9 +46,11 @@
4546
"jest": "^29.5.0",
4647
"ts-jest": "^29.1.0",
4748
"ts-loader": "^9.4.3 || ^8.4.0",
49+
"ts-loader-webpack-4": "npm:ts-loader@^8.4.0",
4850
"typescript": "^5.0.4",
4951
"webpack-4": "npm:webpack@^4.46.0",
50-
"ts-loader-webpack-4": "npm:ts-loader@^8.4.0",
52+
"webpack-cli": "^5.1.4",
53+
"webpack-node-externals": "^3.0.0",
5154
"webpack-sources-webpack-4": "npm:webpack-sources@^1.4.1"
5255
},
5356
"dependencies": {

tools/webpack-plugin/src/BacktracePlugin.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { DebugIdGenerator, SourceMapUploader, SourceProcessor } from '@backtrace/sourcemap-tools';
22
import path from 'path';
33
import webpack, { WebpackPluginInstance } from 'webpack';
4+
import { statsPrinter } from './helpers/statsPrinter';
5+
import { AssetStats } from './models/AssetStats';
46
import { BacktracePluginOptions } from './models/BacktracePluginOptions';
57

68
export class BacktracePlugin implements WebpackPluginInstance {
@@ -15,6 +17,8 @@ export class BacktracePlugin implements WebpackPluginInstance {
1517
}
1618

1719
public apply(compiler: webpack.Compiler) {
20+
const assetStats = new Map<string, AssetStats>();
21+
1822
compiler.hooks.afterEmit.tapPromise(BacktracePlugin.name, async (compilation) => {
1923
const logger = compilation.getLogger(BacktracePlugin.name);
2024
if (!compilation.outputOptions.path) {
@@ -48,33 +52,47 @@ export class BacktracePlugin implements WebpackPluginInstance {
4852
logger.log(`received ${entries.length} files for processing`);
4953

5054
for (const [asset, sourcePath, sourceMapPath] of entries) {
55+
const stats: AssetStats = {};
56+
assetStats.set(asset, stats);
57+
5158
let debugId: string;
5259

5360
logger.time(`[${asset}] process source and sourcemap`);
5461
try {
5562
debugId = await this._sourceProcessor.processSourceAndSourceMapFiles(sourcePath, sourceMapPath);
63+
stats.debugId = debugId;
64+
stats.processSource = true;
65+
logger.timeEnd(`[${asset}] process source and sourcemap`);
5666
} catch (err) {
5767
logger.error(`[${asset}] process source and sourcemap failed:`, err);
68+
stats.processSource = err instanceof Error ? err : new Error('Unknown error.');
5869
continue;
5970
} finally {
6071
logger.timeEnd(`[${asset}] process source and sourcemap`);
6172
}
6273

6374
if (!this._sourceMapUploader) {
64-
logger.info(`[${asset}] file processed`);
75+
logger.log(`[${asset}] file processed`);
6576
continue;
6677
}
6778

6879
logger.time(`[${asset}] upload sourcemap`);
6980
try {
70-
await this._sourceMapUploader.upload(sourceMapPath, debugId);
71-
logger.info(`[${asset}] file processed and sourcemap uploaded`);
81+
const result = await this._sourceMapUploader.upload(sourceMapPath, debugId);
82+
stats.sourceMapUpload = result;
83+
logger.log(`[${asset}] file processed and sourcemap uploaded`);
7284
} catch (err) {
7385
logger.error(`[${asset}] upload sourcemap failed:`, err);
86+
stats.sourceMapUpload = err instanceof Error ? err : new Error('Unknown error.');
7487
} finally {
7588
logger.timeEnd(`[${asset}] upload sourcemap`);
7689
}
7790
}
91+
92+
const printer = statsPrinter(compilation.getLogger(BacktracePlugin.name));
93+
for (const [key, stats] of assetStats) {
94+
printer(key, stats);
95+
}
7896
});
7997
}
8098
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import webpack from 'webpack';
2+
import { AssetStats } from '../models/AssetStats';
3+
4+
function statToString(stat: boolean | string | Error) {
5+
if (typeof stat === 'string') {
6+
return stat;
7+
}
8+
9+
if (typeof stat === 'boolean') {
10+
return stat ? 'successful' : 'skipped';
11+
}
12+
13+
return stat.message;
14+
}
15+
16+
export function statsPrinter(logger: webpack.Compilation['logger']) {
17+
return function printStats(key: string, stats: AssetStats) {
18+
const errors = [stats.sourceMapUpload, stats.processSource].some((v) => v instanceof Error);
19+
20+
const infoLog = errors
21+
? (...args: unknown[]) => logger.error(...args)
22+
: (...args: unknown[]) => logger.info(...args);
23+
24+
const debugLog = (...args: unknown[]) => logger.log(...args);
25+
26+
if (!errors) {
27+
if (!!stats.sourceMapUpload && !(stats.sourceMapUpload instanceof Error)) {
28+
infoLog(`[${key}] processed file and uploaded sourcemap successfully`);
29+
} else {
30+
infoLog(`[${key}] processed file successfully`);
31+
}
32+
} else {
33+
infoLog(`[${key}] processed file with errors`);
34+
}
35+
36+
debugLog(`\tdebugId: ${stats.debugId ?? '<not generated>'}`);
37+
38+
if (stats.processSource != null) {
39+
debugLog(`\tsource snippet append: ${statToString(stats.processSource) ?? '<disabled>'}`);
40+
}
41+
42+
if (stats.sourceMapUpload != null) {
43+
if (stats.sourceMapUpload === false || stats.sourceMapUpload instanceof Error) {
44+
debugLog(`\tsourcemap upload: ${statToString(stats.sourceMapUpload)}`);
45+
} else {
46+
debugLog(
47+
`\tsourcemap upload: yes, rxid: ${stats.sourceMapUpload.rxid}, debugId: ${stats.sourceMapUpload.debugId}`,
48+
);
49+
}
50+
}
51+
};
52+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { UploadResult } from '@backtrace/sourcemap-tools';
2+
3+
export interface AssetStats {
4+
debugId?: string;
5+
processSource?: boolean | string | Error;
6+
sourceMapUpload?: false | UploadResult | Error;
7+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const path = require('path');
2+
const { BacktracePlugin } = require('./lib');
3+
const nodeExternals = require('webpack-node-externals');
4+
5+
/** @type {import('webpack').Configuration} */
6+
module.exports = {
7+
entry: './src/index.ts',
8+
devtool: 'source-map',
9+
mode: 'production',
10+
target: 'node',
11+
externalsPresets: { node: true },
12+
resolve: {
13+
extensions: ['.ts', '.js'],
14+
},
15+
stats: {
16+
logging: 'verbose',
17+
},
18+
module: {
19+
rules: [
20+
{
21+
test: /.ts$/,
22+
loader: 'ts-loader',
23+
options: {
24+
configFile: 'tsconfig.build.json',
25+
},
26+
},
27+
],
28+
},
29+
output: {
30+
path: path.join(__dirname, './webpackBuild'),
31+
filename: '[name].js',
32+
},
33+
externals: [
34+
nodeExternals({
35+
additionalModuleDirs: ['../../node_modules'],
36+
}),
37+
],
38+
plugins: [new BacktracePlugin({})],
39+
};

0 commit comments

Comments
 (0)