You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过CopyWebpackPlugin过滤Webpack已打包文件仅复制未打包文件?

Answer

Great question! I’ve run into this exact need before when working on projects where I wanted to avoid duplicating files that Webpack already handled. Here are two reliable approaches to make CopyWebpackPlugin only copy unbundled files:

Approach 1: Use the filter Option with Compilation Assets

CopyWebpackPlugin’s filter function lets you skip files conditionally, and you can leverage Webpack’s compilation object to check which files have already been bundled. This works because the compilation tracks all assets that Webpack has processed.

Here’s a concrete example:

const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  plugins: [
    new CopyWebpackPlugin({
      patterns: [
        {
          from: 'src/assets/',
          to: 'assets/',
          filter: async (resourcePath, context) => {
            // Grab the compilation object from the plugin context
            const compilation = context.compilation;
            
            // Generate the expected output path for the current file
            // Adjust this logic to match your project's file structure and output rules
            const relativeFromPath = resourcePath.replace(context.context, '').slice(1);
            const outputPath = `assets/${relativeFromPath.split('src/assets/')[1]}`;
            
            // Return true to copy the file, false to skip it
            return !compilation.assets[outputPath];
          }
        }
      ]
    })
  ]
};

How it works:

  • The filter function runs for every file matched by your from pattern.
  • We retrieve the compilation object, which holds all assets Webpack has already bundled (stored in compilation.assets).
  • We generate the path the file would take in your output directory, then check if that path already exists in the bundled assets. If not, we copy it; if yes, we skip it.

Pro tip: If your Webpack config uses hashes in filenames (like [contenthash]), you’ll need to adjust the path matching logic to account for that—for example, stripping the hash from bundled asset keys to compare against the original file path.

Approach 2: Collect Bundled Files First with a Custom Hook

If you need more control over which files are considered "bundled," you can use a custom Webpack hook to collect all bundled files before CopyWebpackPlugin runs, then use that list to filter files.

Example configuration:

const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  plugins: [
    // Custom plugin to collect bundled files
    {
      apply: (compiler) => {
        compiler.hooks.afterCompile.tap('TrackBundledFiles', (compilation) => {
          // Store all bundled asset paths in a custom property on compilation
          compilation.bundledAssets = Object.keys(compilation.assets);
        });
      }
    },
    new CopyWebpackPlugin({
      patterns: [
        {
          from: 'src/assets/',
          to: 'assets/',
          filter: (resourcePath, context) => {
            // Map the source file path to its expected output path
            const assetOutputPath = resourcePath.replace(
              `${context.context}/src/assets/`,
              'assets/'
            );
            
            // Skip if the file is already in the bundled assets list
            return !context.compilation.bundledAssets.includes(assetOutputPath);
          }
        }
      ]
    })
  ]
};

How it works:

  • We use Webpack’s afterCompile hook to run code right after Webpack finishes compiling. This hook gives us access to the final list of bundled assets.
  • We store the list of bundled asset paths in a custom property on the compilation object.
  • In CopyWebpackPlugin’s filter function, we check if the current file’s expected output path is in that list—if not, we copy it.

Key Notes

  • Always test your path matching logic thoroughly, especially if your project has nested directories or custom output rules.
  • If you’re using Webpack 5+, make sure you’re on a recent version of CopyWebpackPlugin (v6 or higher) to ensure the filter function and context work as expected.

内容的提问来源于stack exchange,提问作者Simme Nilsson

火山引擎 最新活动