diff --git a/src/loader.js b/src/loader.js
index 6dac3261..75dcef13 100644
--- a/src/loader.js
+++ b/src/loader.js
@@ -188,6 +188,11 @@ export function pitch(request) {
if (publicPath === "auto") {
publicPath = AUTO_PUBLIC_PATH;
+ } else if (typeof publicPath === "function") {
+ // `hash` property is not available in this context, Webpack itself just set `hash` with
+ // an arbitrary value.
+ // See: https://github.com/webpack/webpack/blob/main/lib/runtime/PublicPathRuntimeModule.js#L19-L27
+ publicPath = publicPath({ hash: "XXXX" });
}
if (
diff --git a/test/__snapshots__/public-path.test.js.snap b/test/__snapshots__/public-path.test.js.snap
new file mode 100644
index 00000000..bae6db28
--- /dev/null
+++ b/test/__snapshots__/public-path.test.js.snap
@@ -0,0 +1,19 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`public path should work with function output.publicPath: DOM 1`] = `
+"
+ style-loader test
+
+
+
+ Body
+
+
+
+
+"
+`;
+
+exports[`public path should work with function output.publicPath: errors 1`] = `Array []`;
+
+exports[`public path should work with function output.publicPath: warnings 1`] = `Array []`;
diff --git a/test/public-path.test.js b/test/public-path.test.js
new file mode 100644
index 00000000..33c5eeaf
--- /dev/null
+++ b/test/public-path.test.js
@@ -0,0 +1,43 @@
+/* eslint-env browser */
+import path from "path";
+
+import MiniCssExtractPlugin from "../src/cjs";
+
+import {
+ compile,
+ getCompiler,
+ getErrors,
+ getWarnings,
+ runInJsDom,
+} from "./helpers/index";
+
+describe("public path", () => {
+ it("should work with function output.publicPath", async () => {
+ const compiler = getCompiler(
+ "simple.js",
+ {},
+ {
+ output: {
+ publicPath() {
+ return "";
+ },
+ path: path.resolve(__dirname, "../outputs"),
+ filename: "[name].bundle.js",
+ },
+ plugins: [
+ new MiniCssExtractPlugin({
+ filename: "[name].css",
+ }),
+ ],
+ }
+ );
+ const stats = await compile(compiler);
+
+ runInJsDom("main.bundle.js", compiler, stats, (dom) => {
+ expect(dom.serialize()).toMatchSnapshot("DOM");
+ });
+
+ expect(getWarnings(stats)).toMatchSnapshot("warnings");
+ expect(getErrors(stats)).toMatchSnapshot("errors");
+ });
+});