From 1f6b3b46ef929987b84f207ea2cd74bc5db234c4 Mon Sep 17 00:00:00 2001 From: Ivar Oja Date: Thu, 22 Nov 2018 10:38:42 +0200 Subject: [PATCH 1/3] feat: accept function as publicPath option --- src/extractLoader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extractLoader.js b/src/extractLoader.js index 1d04fd0..05e5670 100644 --- a/src/extractLoader.js +++ b/src/extractLoader.js @@ -173,7 +173,7 @@ function rndNumber() { */ function getPublicPath(options, context) { if ("publicPath" in options) { - return options.publicPath; + return typeof options.publicPath === 'function' ? options.publicPath(context) : options.publicPath; } if (context.options && context.options.output && "publicPath" in context.options.output) { From 608d1d0f9af2704258db314622390dc2a973cb3f Mon Sep 17 00:00:00 2001 From: Ivar Oja Date: Thu, 22 Nov 2018 14:47:19 +0200 Subject: [PATCH 2/3] chore: add test for publicPath as a function; lint fixes --- src/extractLoader.js | 2 +- test/extractLoader.test.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/extractLoader.js b/src/extractLoader.js index 05e5670..c39d15a 100644 --- a/src/extractLoader.js +++ b/src/extractLoader.js @@ -173,7 +173,7 @@ function rndNumber() { */ function getPublicPath(options, context) { if ("publicPath" in options) { - return typeof options.publicPath === 'function' ? options.publicPath(context) : options.publicPath; + return typeof options.publicPath === "function" ? options.publicPath(context) : options.publicPath; } if (context.options && context.options.output && "publicPath" in context.options.output) { diff --git a/test/extractLoader.test.js b/test/extractLoader.test.js index 390069a..a830b32 100644 --- a/test/extractLoader.test.js +++ b/test/extractLoader.test.js @@ -155,6 +155,24 @@ describe("extractLoader", () => { // ); })); + it("should execute options.publicPath if it's defined as a function", done => { + let publicPathCalledWithContext = false; + const loaderContext = { + async: () => () => done(), + cacheable() {}, + query: { + publicPath: context => { + publicPathCalledWithContext = context === loaderContext; + + return ""; + }, + }, + }; + + extractLoader.call(loaderContext, ""); + + expect(publicPathCalledWithContext).to.equal(true); + }); it("should support explicit loader chains", () => compile({testModule: "loader.html"}).then(() => { const loaderHtml = path.resolve(__dirname, "dist/loader-dist.html"); const errJs = path.resolve(__dirname, "dist/err.js"); From 62f42b1f6a3a8b75301ecc81530fc85dfc941435 Mon Sep 17 00:00:00 2001 From: Ivar Oja Date: Fri, 23 Nov 2018 12:03:58 +0200 Subject: [PATCH 3/3] chore: update README with intel on how to use publicPath option as a function --- README.md | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0b5afd5..5fa6b74 100644 --- a/README.md +++ b/README.md @@ -171,9 +171,9 @@ Options ------------------------------------------------------------------------ There is currently exactly one option: `publicPath`. -If you are using a relative `publicPath` in webpack's [output options](https://webpack.js.org/configuration/output/#output-publicpath) and extracting to a file with the `file-loader`, you might need this to account for the location of your extracted file. +If you are using a relative `publicPath` in webpack's [output options](https://webpack.js.org/configuration/output/#output-publicpath) and extracting to a file with the `file-loader`, you might need this to account for the location of your extracted file. `publicPath` may be defined as a string or a function that accepts current [loader context](https://webpack.js.org/api/loaders/#the-loader-context) as single argument. -Example: +Example with publicPath option as a string: ```js module.exports = { @@ -208,6 +208,42 @@ module.exports = { }; ``` +Example with publicPath option as a function: + +```js +module.exports = { + output: { + path: path.resolve("./dist"), + publicPath: "dist/" + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: "file-loader", + options: { + name: "assets/[name].[ext]", + }, + }, + { + loader: "extract-loader", + options: { + // dynamically return a relative publicPath based on how deep in directory structure the loaded file is in /src/ directory + publicPath: (context) => '../'.repeat(path.relative(path.resolve('src'), context.context).split('/').length), + } + }, + { + loader: "css-loader", + }, + ], + } + ] + } +}; +``` + You need another option? Then you should think about: