Skip to content

Commit

Permalink
ensure plugins don't interact negatively with clean-webpack-plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
spalger committed Feb 5, 2021
1 parent b706987 commit 48a2448
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 15 deletions.
2 changes: 1 addition & 1 deletion packages/kbn-optimizer/src/common/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export class Bundle {
this.banner = spec.banner;
this.pageLoadAssetSizeLimit = spec.pageLoadAssetSizeLimit;

this.cache = new BundleCache(Path.resolve(this.outputDir, '.kbn-optimizer-cache'));
this.cache = new BundleCache(this.outputDir);
}

/**
Expand Down
14 changes: 7 additions & 7 deletions packages/kbn-optimizer/src/common/bundle_cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ beforeEach(() => {
});

it(`doesn't complain if files are not on disk`, () => {
const cache = new BundleCache('/foo/bar.json');
const cache = new BundleCache('/foo');
expect(cache.get()).toEqual({});
});

it(`updates files on disk when calling set()`, () => {
const cache = new BundleCache('/foo/bar.json');
const cache = new BundleCache('/foo');
cache.set(SOME_STATE);
expect(mockReadFileSync).not.toHaveBeenCalled();
expect(mockMkdirSync.mock.calls).toMatchInlineSnapshot(`
Expand All @@ -46,7 +46,7 @@ it(`updates files on disk when calling set()`, () => {
expect(mockWriteFileSync.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"/foo/bar.json",
"/foo/.kbn-optimizer-cache",
"{
\\"cacheKey\\": \\"abc\\",
\\"files\\": [
Expand All @@ -61,7 +61,7 @@ it(`updates files on disk when calling set()`, () => {
});

it(`serves updated state from memory`, () => {
const cache = new BundleCache('/foo/bar.json');
const cache = new BundleCache('/foo');
cache.set(SOME_STATE);
jest.clearAllMocks();

Expand All @@ -72,7 +72,7 @@ it(`serves updated state from memory`, () => {
});

it('reads state from disk on get() after refresh()', () => {
const cache = new BundleCache('/foo/bar.json');
const cache = new BundleCache('/foo');
cache.set(SOME_STATE);
cache.refresh();
jest.clearAllMocks();
Expand All @@ -83,15 +83,15 @@ it('reads state from disk on get() after refresh()', () => {
expect(mockReadFileSync.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"/foo/bar.json",
"/foo/.kbn-optimizer-cache",
"utf8",
],
]
`);
});

it('provides accessors to specific state properties', () => {
const cache = new BundleCache('/foo/bar.json');
const cache = new BundleCache('/foo');

expect(cache.getModuleCount()).toBe(undefined);
expect(cache.getReferencedFiles()).toEqual(undefined);
Expand Down
22 changes: 21 additions & 1 deletion packages/kbn-optimizer/src/common/bundle_cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import Fs from 'fs';
import Path from 'path';

import webpack from 'webpack';
import { RawSource } from 'webpack-sources';

export interface State {
optimizerCacheKey?: unknown;
cacheKey?: unknown;
Expand All @@ -20,13 +23,17 @@ export interface State {

const DEFAULT_STATE: State = {};
const DEFAULT_STATE_JSON = JSON.stringify(DEFAULT_STATE);
const CACHE_FILENAME = '.kbn-optimizer-cache';

/**
* Helper to read and update metadata for bundles.
*/
export class BundleCache {
private state: State | undefined = undefined;
constructor(private readonly path: string | false) {}
private readonly path: string | false;
constructor(outputDir: string | false) {
this.path = outputDir === false ? false : Path.resolve(outputDir, CACHE_FILENAME);
}

refresh() {
this.state = undefined;
Expand Down Expand Up @@ -63,6 +70,7 @@ export class BundleCache {

set(updated: State) {
this.state = updated;

if (this.path) {
const directory = Path.dirname(this.path);
Fs.mkdirSync(directory, { recursive: true });
Expand Down Expand Up @@ -107,4 +115,16 @@ export class BundleCache {
}
}
}

public writeWebpackAsset(compilation: webpack.compilation.Compilation) {
if (!this.path) {
return;
}

const source = new RawSource(JSON.stringify(this.state, null, 2));

// see https://github.com/jantimon/html-webpack-plugin/blob/33d69f49e6e9787796402715d1b9cd59f80b628f/index.js#L266
// @ts-expect-error undocumented, used to add assets to the output
compilation.emitAsset(CACHE_FILENAME, source);
}
}
19 changes: 13 additions & 6 deletions packages/kbn-optimizer/src/worker/emit_stats_plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@ export class EmitStatsPlugin {
constructor(private readonly bundle: Bundle) {}

public apply(compiler: webpack.Compiler) {
compiler.hooks.done.tap('EmitStatsPlugin', (stats) => {
Fs.writeFileSync(
Path.resolve(this.bundle.outputDir, 'stats.json'),
JSON.stringify(stats.toJson())
);
});
compiler.hooks.done.tap(
{
name: 'EmitStatsPlugin',
// run at the very end, ensure that it's after clean-webpack-plugin
stage: 10,
},
(stats) => {
Fs.writeFileSync(
Path.resolve(this.bundle.outputDir, 'stats.json'),
JSON.stringify(stats.toJson())
);
}
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ export class PopulateBundleCachePlugin {
workUnits,
files,
});

// write the cache to the compilation so that it isn't cleaned by clean-webpack-plugin
bundle.cache.writeWebpackAsset(compilation);
}
);
}
Expand Down

0 comments on commit 48a2448

Please sign in to comment.