feat(v2): Allow plugins to consume webpack stats (#4021)

* refactor(v2): Allow plugins to consume webpack stats

Signed-off-by: Reece Dunham <me@rdil.rocks>

* Warn level only

* Fix issue

* Revert start.ts change
This commit is contained in:
Reece Dunham 2021-01-11 09:34:42 -05:00 committed by GitHub
parent a406a3c9aa
commit 66cc7364cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 11 deletions

View file

@ -7,7 +7,7 @@
// ESLint doesn't understand types dependencies in d.ts
// eslint-disable-next-line import/no-extraneous-dependencies
import {Loader, Configuration} from 'webpack';
import {Loader, Configuration, Stats} from 'webpack';
import {Command} from 'commander';
import {ParsedUrlQueryInput} from 'querystring';
import {MergeStrategy} from 'webpack-merge';
@ -178,6 +178,13 @@ export interface Props extends LoadContext, InjectedHtmlTags {
plugins: Plugin<any, unknown>[];
}
/**
* Same as `Props` but also has webpack stats appended.
*/
export interface PropsPostBuild extends Props {
stats: Stats.ToJsonOutput;
}
export interface PluginContentLoadedActions {
addRoute(config: RouteConfig): void;
createData(name: string, data: any): Promise<string>;
@ -206,7 +213,7 @@ export interface Plugin<T, U = unknown> {
actions: PluginContentLoadedActions;
}): void;
routesLoaded?(routes: RouteConfig[]): void; // TODO remove soon, deprecated (alpha-60)
postBuild?(props: Props): void;
postBuild?(props: PropsPostBuild): void;
postStart?(props: Props): void;
configureWebpack?(
config: Configuration,
@ -224,6 +231,7 @@ export interface Plugin<T, U = unknown> {
postBodyTags?: HtmlTags;
};
getSwizzleComponentList?(): string[];
// TODO before/afterDevServer implementation
// translations
getTranslationFiles?(): Promise<TranslationFiles>;

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import chalk = require('chalk');
import chalk from 'chalk';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import fs from 'fs-extra';
import path from 'path';
@ -193,7 +193,7 @@ async function buildLocale({
}
// Run webpack to build JS bundle (client) and static html files (server).
await compile([clientConfig, serverConfig]);
const finalCompileResult = await compile([clientConfig, serverConfig]);
// Remove server.bundle.js because it is not needed.
if (
@ -215,7 +215,7 @@ async function buildLocale({
if (!plugin.postBuild) {
return;
}
await plugin.postBuild(props);
await plugin.postBuild({...props, stats: finalCompileResult});
}),
);

View file

@ -198,22 +198,24 @@ function filterWarnings(
return warnings.filter((warning) => !isWarningFiltered(warning));
}
export function compile(config: Configuration[]): Promise<void> {
export function compile(config: Configuration[]): Promise<Stats.ToJsonOutput> {
return new Promise((resolve, reject) => {
const compiler = webpack(config);
compiler.run((err, stats) => {
if (err) {
reject(new Error(err.toString()));
}
// let plugins consume all the stats
const allStats = stats?.toJson('errors-warnings');
if (stats?.hasErrors()) {
stats.toJson('errors-only').errors.forEach((e) => {
allStats.errors.forEach((e) => {
console.error(e);
});
reject(new Error('Failed to compile with errors.'));
}
if (stats?.hasWarnings()) {
// Custom filtering warnings (see https://github.com/webpack/webpack/issues/7841).
let {warnings} = stats.toJson('errors-warnings');
let warnings = [...allStats.warnings];
const warningsFilter = ((config[0].stats as Stats.ToJsonOptionsObject)
?.warningsFilter || []) as WarningFilter[];
@ -226,7 +228,7 @@ export function compile(config: Configuration[]): Promise<void> {
console.warn(warning);
});
}
resolve();
resolve(allStats);
});
});
}

View file

@ -362,20 +362,23 @@ type Props = {
postBodyTags: string;
routesPaths: string[];
plugins: Plugin<any>[];
stats: Stats.ToJsonOutput;
};
```
Example:
```js {4-9} title="docusaurus-plugin/src/index.js"
```js {4-11} title="docusaurus-plugin/src/index.js"
module.exports = function (context, options) {
return {
name: 'docusaurus-plugin',
async postBuild({siteConfig = {}, routesPaths = [], outDir}) {
async postBuild({siteConfig = {}, routesPaths = [], outDir, stats}) {
// Print out to console all the rendered routes.
routesPaths.map((route) => {
console.log(route);
});
// Print out to console all the webpack stats.
console.log(stats);
},
};
};