diff --git a/crates/rspack_plugin_copy/src/lib.rs b/crates/rspack_plugin_copy/src/lib.rs index aa489fce4cc..3f51d1f5a71 100644 --- a/crates/rspack_plugin_copy/src/lib.rs +++ b/crates/rspack_plugin_copy/src/lib.rs @@ -439,10 +439,17 @@ impl CopyRspackPlugin { } FromType::Glob => { need_add_context_to_dependency = true; - if Path::new(orig_from).is_absolute() { + let glob_query = if Path::new(orig_from).is_absolute() { orig_from.into() } else { context.join(orig_from).as_str().to_string() + }; + // A glob pattern ending with /** should match all files within a directory, not just the directory itself. + // Since the standard glob only matches directories, we append /* to align with webpack's behavior. + if glob_query.ends_with("/**") { + format!("{glob_query}/*") + } else { + glob_query } } }; diff --git a/tests/plugin-test/copy-plugin/CopyPlugin.test.js b/tests/plugin-test/copy-plugin/CopyPlugin.test.js index 05dfc230370..03b5d185e73 100644 --- a/tests/plugin-test/copy-plugin/CopyPlugin.test.js +++ b/tests/plugin-test/copy-plugin/CopyPlugin.test.js @@ -264,6 +264,22 @@ describe("CopyPlugin", () => { .catch(done); }); + it('should work when "from" is a glob ending with /**', done => { + runEmit({ + expectedAssetKeys: [ + "directory/nested/nestedfile.txt", + "directory/nested/deep-nested/deepnested.txt" + ], + patterns: [ + { + from: "directory/nested/**" + } + ] + }) + .then(done) + .catch(done); + }); + it.skip("should exclude path with linux path segment separators", done => { runEmit({ expectedAssetKeys: [