mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-19 11:12:36 +02:00
perf(v2): fork clean-webpack-plugin to reduce memory (#1839)
* chore: fork clean-webpack-plugin * deps
This commit is contained in:
parent
7f3146a902
commit
bdb129252c
5 changed files with 336 additions and 10 deletions
|
@ -1,5 +1,8 @@
|
||||||
# Docusaurus 2 Changelog
|
# Docusaurus 2 Changelog
|
||||||
|
|
||||||
|
## 2.0.0-alpha.28
|
||||||
|
- Further reduce memory usage to avoid heap memory allocation failure.
|
||||||
|
|
||||||
## 2.0.0-alpha.27
|
## 2.0.0-alpha.27
|
||||||
|
|
||||||
- Add `@theme/Tabs` which can be used to implement multi-language code tabs.
|
- Add `@theme/Tabs` which can be used to implement multi-language code tabs.
|
||||||
|
|
|
@ -43,10 +43,10 @@
|
||||||
"chalk": "^2.4.2",
|
"chalk": "^2.4.2",
|
||||||
"chokidar": "^3.0.2",
|
"chokidar": "^3.0.2",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"clean-webpack-plugin": "^2.0.1",
|
|
||||||
"commander": "^2.20.0",
|
"commander": "^2.20.0",
|
||||||
"copy-webpack-plugin": "^5.0.4",
|
"copy-webpack-plugin": "^5.0.4",
|
||||||
"css-loader": "^3.1.0",
|
"css-loader": "^3.1.0",
|
||||||
|
"del": "^4.1.1",
|
||||||
"ejs": "^2.6.2",
|
"ejs": "^2.6.2",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import CleanWebpackPlugin from 'clean-webpack-plugin';
|
|
||||||
import CopyWebpackPlugin from 'copy-webpack-plugin';
|
import CopyWebpackPlugin from 'copy-webpack-plugin';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
@ -20,6 +19,7 @@ import {CLIOptions, Props} from '@docusaurus/types';
|
||||||
import {createClientConfig} from '../webpack/client';
|
import {createClientConfig} from '../webpack/client';
|
||||||
import {createServerConfig} from '../webpack/server';
|
import {createServerConfig} from '../webpack/server';
|
||||||
import {applyConfigureWebpack} from '../webpack/utils';
|
import {applyConfigureWebpack} from '../webpack/utils';
|
||||||
|
import CleanWebpackPlugin from '../webpack/plugins/CleanWebpackPlugin';
|
||||||
|
|
||||||
function compile(config: Configuration[]): Promise<any> {
|
function compile(config: Configuration[]): Promise<any> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
330
packages/docusaurus/src/webpack/plugins/CleanWebpackPlugin.ts
Normal file
330
packages/docusaurus/src/webpack/plugins/CleanWebpackPlugin.ts
Normal file
|
@ -0,0 +1,330 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2017-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Compiler, Stats} from 'webpack';
|
||||||
|
import path from 'path';
|
||||||
|
import {sync as delSync} from 'del';
|
||||||
|
|
||||||
|
export interface Options {
|
||||||
|
/**
|
||||||
|
* Simulate the removal of files
|
||||||
|
*
|
||||||
|
* default: false
|
||||||
|
*/
|
||||||
|
dry?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write Logs to Console
|
||||||
|
* (Always enabled when dry is true)
|
||||||
|
*
|
||||||
|
* default: false
|
||||||
|
*/
|
||||||
|
verbose?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically remove all unused webpack assets on rebuild
|
||||||
|
*
|
||||||
|
* default: true
|
||||||
|
*/
|
||||||
|
cleanStaleWebpackAssets?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not allow removal of current webpack assets
|
||||||
|
*
|
||||||
|
* default: true
|
||||||
|
*/
|
||||||
|
protectWebpackAssets?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes files once prior to Webpack compilation
|
||||||
|
* Not included in rebuilds (watch mode)
|
||||||
|
*
|
||||||
|
* Use !negative patterns to exclude files
|
||||||
|
*
|
||||||
|
* default: ['**\/*']
|
||||||
|
*/
|
||||||
|
cleanOnceBeforeBuildPatterns?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes files after every build (including watch mode) that match this pattern.
|
||||||
|
* Used for files that are not created directly by Webpack.
|
||||||
|
*
|
||||||
|
* Use !negative patterns to exclude files
|
||||||
|
*
|
||||||
|
* default: disabled
|
||||||
|
*/
|
||||||
|
cleanAfterEveryBuildPatterns?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow clean patterns outside of process.cwd()
|
||||||
|
*
|
||||||
|
* requires dry option to be explicitly set
|
||||||
|
*
|
||||||
|
* default: false
|
||||||
|
*/
|
||||||
|
dangerouslyAllowCleanPatternsOutsideProject?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CleanWebpackPlugin {
|
||||||
|
private readonly dry: boolean;
|
||||||
|
private readonly verbose: boolean;
|
||||||
|
private readonly cleanStaleWebpackAssets: boolean;
|
||||||
|
private readonly protectWebpackAssets: boolean;
|
||||||
|
private readonly cleanAfterEveryBuildPatterns: string[];
|
||||||
|
private readonly cleanOnceBeforeBuildPatterns: string[];
|
||||||
|
private readonly dangerouslyAllowCleanPatternsOutsideProject: boolean;
|
||||||
|
private currentAssets: string[];
|
||||||
|
private initialClean: boolean;
|
||||||
|
private outputPath: string;
|
||||||
|
|
||||||
|
constructor(options: Options = {}) {
|
||||||
|
if (typeof options !== 'object' || Array.isArray(options) === true) {
|
||||||
|
throw new Error(`clean-webpack-plugin only accepts an options object. See:
|
||||||
|
https://github.com/johnagan/clean-webpack-plugin#options-and-defaults-optional`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
if (options.allowExternal) {
|
||||||
|
throw new Error(
|
||||||
|
'clean-webpack-plugin: `allowExternal` option no longer supported. Use `dangerouslyAllowCleanPatternsOutsideProject`',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
options.dangerouslyAllowCleanPatternsOutsideProject === true &&
|
||||||
|
options.dry !== true &&
|
||||||
|
options.dry !== false
|
||||||
|
) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.warn(
|
||||||
|
'clean-webpack-plugin: dangerouslyAllowCleanPatternsOutsideProject requires dry: false to be explicitly set. Enabling dry mode',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dangerouslyAllowCleanPatternsOutsideProject =
|
||||||
|
options.dangerouslyAllowCleanPatternsOutsideProject === true || false;
|
||||||
|
|
||||||
|
this.dry =
|
||||||
|
options.dry === true || options.dry === false
|
||||||
|
? options.dry
|
||||||
|
: this.dangerouslyAllowCleanPatternsOutsideProject === true || false;
|
||||||
|
|
||||||
|
this.verbose = this.dry === true || options.verbose === true || false;
|
||||||
|
|
||||||
|
this.cleanStaleWebpackAssets =
|
||||||
|
options.cleanStaleWebpackAssets === true ||
|
||||||
|
options.cleanStaleWebpackAssets === false
|
||||||
|
? options.cleanStaleWebpackAssets
|
||||||
|
: true;
|
||||||
|
|
||||||
|
this.protectWebpackAssets =
|
||||||
|
options.protectWebpackAssets === true ||
|
||||||
|
options.protectWebpackAssets === false
|
||||||
|
? options.protectWebpackAssets
|
||||||
|
: true;
|
||||||
|
|
||||||
|
this.cleanAfterEveryBuildPatterns = Array.isArray(
|
||||||
|
options.cleanAfterEveryBuildPatterns,
|
||||||
|
)
|
||||||
|
? options.cleanAfterEveryBuildPatterns
|
||||||
|
: [];
|
||||||
|
|
||||||
|
this.cleanOnceBeforeBuildPatterns = Array.isArray(
|
||||||
|
options.cleanOnceBeforeBuildPatterns,
|
||||||
|
)
|
||||||
|
? options.cleanOnceBeforeBuildPatterns
|
||||||
|
: ['**/*'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store webpack build assets
|
||||||
|
*/
|
||||||
|
this.currentAssets = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only used with cleanOnceBeforeBuildPatterns
|
||||||
|
*/
|
||||||
|
this.initialClean = false;
|
||||||
|
|
||||||
|
this.outputPath = '';
|
||||||
|
|
||||||
|
this.apply = this.apply.bind(this);
|
||||||
|
this.handleInitial = this.handleInitial.bind(this);
|
||||||
|
this.handleDone = this.handleDone.bind(this);
|
||||||
|
this.removeFiles = this.removeFiles.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(compiler: Compiler) {
|
||||||
|
if (!compiler.options.output || !compiler.options.output.path) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.warn(
|
||||||
|
'clean-webpack-plugin: options.output.path not defined. Plugin disabled...',
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.outputPath = compiler.options.output.path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* webpack 4+ comes with a new plugin system.
|
||||||
|
*
|
||||||
|
* Check for hooks in-order to support old plugin system
|
||||||
|
*/
|
||||||
|
const hooks = compiler.hooks;
|
||||||
|
|
||||||
|
if (this.cleanOnceBeforeBuildPatterns.length !== 0) {
|
||||||
|
if (hooks) {
|
||||||
|
hooks.compile.tap('clean-webpack-plugin', () => {
|
||||||
|
this.handleInitial();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
compiler.plugin('compile', () => {
|
||||||
|
this.handleInitial();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hooks) {
|
||||||
|
hooks.done.tap('clean-webpack-plugin', stats => {
|
||||||
|
this.handleDone(stats);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
compiler.plugin('done', stats => {
|
||||||
|
this.handleDone(stats);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initially remove files from output directory prior to build.
|
||||||
|
*
|
||||||
|
* Only happens once.
|
||||||
|
*
|
||||||
|
* Warning: It is recommended to initially clean your build directory outside of webpack to minimize unexpected behavior.
|
||||||
|
*/
|
||||||
|
handleInitial() {
|
||||||
|
if (this.initialClean) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialClean = true;
|
||||||
|
|
||||||
|
this.removeFiles(this.cleanOnceBeforeBuildPatterns);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDone(stats: Stats) {
|
||||||
|
/**
|
||||||
|
* Do nothing if there is a webpack error
|
||||||
|
*/
|
||||||
|
if (stats.hasErrors()) {
|
||||||
|
if (this.verbose) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.warn('clean-webpack-plugin: pausing due to webpack errors');
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch Webpack's output asset files
|
||||||
|
*/
|
||||||
|
const statsAssets =
|
||||||
|
stats.toJson(
|
||||||
|
{
|
||||||
|
all: false,
|
||||||
|
assets: true,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
).assets || [];
|
||||||
|
const assets = statsAssets.map((asset: {name: string}) => {
|
||||||
|
return asset.name;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all files that were in the previous build but not the current
|
||||||
|
*
|
||||||
|
* (relies on del's cwd: outputPath option)
|
||||||
|
*/
|
||||||
|
const staleFiles = this.currentAssets.filter(previousAsset => {
|
||||||
|
const assetCurrent = assets.includes(previousAsset) === false;
|
||||||
|
|
||||||
|
return assetCurrent;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save assets for next compilation
|
||||||
|
*/
|
||||||
|
this.currentAssets = assets.sort();
|
||||||
|
|
||||||
|
const removePatterns: string[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove unused webpack assets
|
||||||
|
*/
|
||||||
|
if (this.cleanStaleWebpackAssets === true && staleFiles.length !== 0) {
|
||||||
|
removePatterns.push(...staleFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove cleanAfterEveryBuildPatterns
|
||||||
|
*/
|
||||||
|
if (this.cleanAfterEveryBuildPatterns.length !== 0) {
|
||||||
|
removePatterns.push(...this.cleanAfterEveryBuildPatterns);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removePatterns.length !== 0) {
|
||||||
|
this.removeFiles(removePatterns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFiles(patterns: string[]) {
|
||||||
|
try {
|
||||||
|
const deleted = delSync(patterns, {
|
||||||
|
force: this.dangerouslyAllowCleanPatternsOutsideProject,
|
||||||
|
// Change context to build directory
|
||||||
|
cwd: this.outputPath,
|
||||||
|
dryRun: this.dry,
|
||||||
|
dot: true,
|
||||||
|
ignore: this.protectWebpackAssets ? this.currentAssets : [],
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log if verbose is enabled
|
||||||
|
*/
|
||||||
|
if (this.verbose) {
|
||||||
|
deleted.forEach(file => {
|
||||||
|
const filename = path.relative(process.cwd(), file);
|
||||||
|
|
||||||
|
const message = this.dry ? 'dry' : 'removed';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use console.warn over .log
|
||||||
|
* https://github.com/webpack/webpack/issues/1904
|
||||||
|
* https://github.com/johnagan/clean-webpack-plugin/issues/11
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.warn(`clean-webpack-plugin: ${message} ${filename}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
const needsForce = /Cannot delete files\/folders outside the current working directory\./.test(
|
||||||
|
error.message,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (needsForce) {
|
||||||
|
const message =
|
||||||
|
'clean-webpack-plugin: Cannot delete files/folders outside the current working directory. Can be overridden with the `dangerouslyAllowCleanPatternsOutsideProject` option.';
|
||||||
|
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CleanWebpackPlugin;
|
|
@ -4486,13 +4486,6 @@ clean-stack@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
|
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
|
||||||
integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
|
integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
|
||||||
|
|
||||||
clean-webpack-plugin@^2.0.1:
|
|
||||||
version "2.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/clean-webpack-plugin/-/clean-webpack-plugin-2.0.2.tgz#805a19ff20d46a06125298a25eb31142ecad2166"
|
|
||||||
integrity sha512-pi1111o4OBd9qvacbgs+NRqClfVPKVIc66B4d8kx6Ho/L+i9entQ/NpK600CsTYTPu3kWvKwwyKarsYMvC2xeA==
|
|
||||||
dependencies:
|
|
||||||
del "^4.0.0"
|
|
||||||
|
|
||||||
cli-cursor@^2.0.0, cli-cursor@^2.1.0:
|
cli-cursor@^2.0.0, cli-cursor@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
|
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
|
||||||
|
@ -5543,7 +5536,7 @@ define-property@^2.0.2:
|
||||||
is-descriptor "^1.0.2"
|
is-descriptor "^1.0.2"
|
||||||
isobject "^3.0.1"
|
isobject "^3.0.1"
|
||||||
|
|
||||||
del@^4.0.0, del@^4.1.1:
|
del@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4"
|
resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4"
|
||||||
integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==
|
integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue