如何在Webpack构建完成后运行插件?解决webpack-version-file目录问题
Hey there, let's work through this problem you're facing with webpack-version-file. The core issue here is that the plugin tries to write its output file before the target directory exists (on first builds), but works fine once the directory is already there from a prior build.
Here are a couple of solid solutions to either ensure the directory exists before the plugin runs, or force the version file generation to happen after the build completes (when the output directory is guaranteed to exist):
Solution 1: Pre-Create the Target Directory with a Custom Webpack Plugin
This approach adds a tiny custom plugin that runs early in the Webpack lifecycle to make sure your version file's directory exists before webpack-version-file tries to use it. We'll use fs-extra (a more user-friendly wrapper around Node's fs module) to handle directory creation reliably across platforms.
First, install fs-extra if you don't have it already:
npm install fs-extra --save-dev
Then update your Webpack config:
const fs = require('fs-extra'); const VersionFilePlugin = require('webpack-version-file'); module.exports = { // ... your existing Webpack config (entry, output, module rules, etc.) plugins: [ // Custom plugin to create the version directory first { apply: (compiler) => { // Hook into the "beforeRun" event (runs before Webpack starts compiling) compiler.hooks.beforeRun.tap('EnsureVersionDirectory', async () => { // Replace this path with your actual target directory for the version file const targetDir = './dist/version'; await fs.ensureDir(targetDir); // Creates the directory if it doesn't exist }); } }, // Now run the webpack-version-file plugin as usual new VersionFilePlugin({ output: './dist/version/version.json', // Match your target path package: './package.json', // ... any other config options you're using }) ] };
Solution 2: Generate the Version File After Build Completes (afterEmit Hook)
If you specifically want to run the version file logic after the build finishes (when all output directories are already created), you can skip the webpack-version-file plugin entirely and implement the same functionality yourself using Webpack's afterEmit hook. This gives you full control over timing.
Here's how to set that up:
const fs = require('fs-extra'); const packageJson = require('./package.json'); // Pull version from your package.json module.exports = { // ... your existing Webpack config plugins: [ { apply: (compiler) => { // Hook into "afterEmit" - runs after all assets are emitted to disk compiler.hooks.afterEmit.tapAsync('GenerateVersionFile', async (compilation, callback) => { // Define your version file content const versionContent = { version: packageJson.version, buildTimestamp: new Date().toISOString(), // Add any other metadata you need (git commit hash, etc.) }; const outputPath = './dist/version/version.json'; await fs.ensureFile(outputPath); // Creates the file if it doesn't exist await fs.writeJson(outputPath, versionContent, { spaces: 2 }); // Pretty-print JSON callback(); // Signal Webpack we're done }); } } ] };
Bonus: Cross-Platform NPM Script Pre-Build Step
If you prefer a simpler approach without adding custom Webpack logic, you can add a pre-build script to your package.json that creates the directory before Webpack runs. Just note this requires handling cross-platform commands (Unix vs. Windows):
{ "scripts": { "prebuild": "mkdir -p dist/version || true", // For Unix/macOS "prebuild:windows": "if not exist dist\\version mkdir dist\\version", // For Windows "build": "webpack", "build:windows": "npm run prebuild:windows && npm run build" } }
For better cross-platform support, you could use a tool like mkdirp instead of raw shell commands to avoid platform-specific syntax.
内容的提问来源于stack exchange,提问作者Joesy_Mosk

