Refine the build directory cleaning logic (#577)

Summary:
We were asking the `clean-webpack-plugin` to remove the `build/`
directory in all cases. However, Webpack accepts a command-line
parameter `--output-path`. When such a parameter is passed, we would be
removing the wrong directory.

The proper behavior is to remove “whatever the actual output path is”.
Webpack exposes this information, but it appears that the
`clean-webpack-plugin` does not take advantage of it. Therefore, this
commit includes a small Webpack plugin to do the right thing.

Test Plan:
Test that the behavior is correct when no output directory is specified:
```
mkdir -p build && touch build/wat && yarn build && ! [ -e build/wat ]
```

Test that the behavior is correct with an explicit `--output-path`:
```
outdir="$(mktemp -d)" && touch "${outdir}/wat" && \
    yarn build --output-path "${outdir}" && \
    ! [ -e "${outdir}/wat" ]
```

Test that the plugin refuses to remove the root directory:

```
! yarn build --output-path . && \
    sed -i '/path: /d' config/makeWebpackConfig.js && ! yarn build
```

(Feel free to comment out the actual `rimraf.sync` line in the plugin
when testing this.)

wchargin-branch: clean-actual-build-directory
This commit is contained in:
William Chargin 2018-07-31 15:27:32 -07:00 committed by GitHub
parent 8009cd279b
commit 480bdf1bc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 3 deletions

View File

@ -0,0 +1,39 @@
// @flow
const fs = require("fs");
const path = require("path");
const rimraf = require("rimraf");
// Note: the following type-import just resolves to `any`.
/*:: import type {Compiler} from "webpack"; */
module.exports = class RemoveBuildDirectoryPlugin {
apply(compiler /*: Compiler */) {
if (compiler.hooks) {
console.warn(
"" +
"You appear to be running Webpack >= 4. " +
"The RemoveBuildDirectoryPlugin should be forward-compatible, " +
"but you should update it to use the new APIs. See " +
"<https://github.com/webpack/webpack/releases/tag/v4.0.0-beta.0> " +
"for details."
);
}
compiler.plugin("compile", () => {
const outputPath = compiler.options.output.path;
// If a build config has no `output.path` property, and no
// `--output-path` is passed on the command line, then Webpack
// will default to building into the current directory. Removing
// the whole Git repository would be mighty rude, so we protect
// against that case.
if (fs.existsSync(path.join(outputPath, ".git"))) {
throw new Error(
"Refusing to remove build directory with a Git repository: " +
outputPath
);
}
console.warn("Removing build directory: " + outputPath);
rimraf.sync(outputPath);
});
}
};

View File

@ -4,7 +4,7 @@ const express = require("express");
const os = require("os");
const path = require("path");
const webpack = require("webpack");
const CleanPlugin = require("clean-webpack-plugin");
const RemoveBuildDirectoryPlugin = require("./RemoveBuildDirectoryPlugin");
const ManifestPlugin = require("webpack-manifest-plugin");
const SWPrecacheWebpackPlugin = require("sw-precache-webpack-plugin");
const StaticSiteGeneratorPlugin = require("static-site-generator-webpack-plugin");
@ -259,7 +259,7 @@ function plugins(mode /*: "development" | "production" */) {
];
const prodOnlyPlugins = [
// Remove the output directory before starting the build.
new CleanPlugin([paths.appBuild], {root: paths.root}),
new RemoveBuildDirectoryPlugin(),
// Minify the code.
new webpack.optimize.UglifyJsPlugin({
compress: {

View File

@ -60,6 +60,7 @@
"prettier": "^1.13.4",
"raf": "3.4.0",
"react-dev-utils": "^5.0.0",
"rimraf": "^2.6.2",
"static-site-generator-webpack-plugin": "^3.4.1",
"style-loader": "0.19.0",
"sw-precache-webpack-plugin": "0.11.4",

View File

@ -6749,7 +6749,7 @@ right-align@^0.1.1:
dependencies:
align-text "^0.1.1"
rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1:
rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
dependencies: