Skip to content

Commit 678933e

Browse files
ipsipsjhnns
authored andcommitted
feat: Accept function as publicPath option (#51)
Allow `publicPath` option to be a function that returns the publicPath string that could be determined based on current context.
1 parent fb7139a commit 678933e

File tree

3 files changed

+57
-3
lines changed

3 files changed

+57
-3
lines changed

README.md

+38-2
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,9 @@ Options
171171
------------------------------------------------------------------------
172172

173173
There is currently exactly one option: `publicPath`.
174-
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.
174+
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.
175175

176-
Example:
176+
Example with publicPath option as a string:
177177

178178
```js
179179
module.exports = {
@@ -208,6 +208,42 @@ module.exports = {
208208
};
209209
```
210210

211+
Example with publicPath option as a function:
212+
213+
```js
214+
module.exports = {
215+
output: {
216+
path: path.resolve("./dist"),
217+
publicPath: "dist/"
218+
},
219+
module: {
220+
rules: [
221+
{
222+
test: /\.css$/,
223+
use: [
224+
{
225+
loader: "file-loader",
226+
options: {
227+
name: "assets/[name].[ext]",
228+
},
229+
},
230+
{
231+
loader: "extract-loader",
232+
options: {
233+
// dynamically return a relative publicPath based on how deep in directory structure the loaded file is in /src/ directory
234+
publicPath: (context) => '../'.repeat(path.relative(path.resolve('src'), context.context).split('/').length),
235+
}
236+
},
237+
{
238+
loader: "css-loader",
239+
},
240+
],
241+
}
242+
]
243+
}
244+
};
245+
```
246+
211247
You need another option? Then you should think about:
212248

213249
<br>

src/extractLoader.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ function rndNumber() {
173173
*/
174174
function getPublicPath(options, context) {
175175
if ("publicPath" in options) {
176-
return options.publicPath;
176+
return typeof options.publicPath === "function" ? options.publicPath(context) : options.publicPath;
177177
}
178178

179179
if (context.options && context.options.output && "publicPath" in context.options.output) {

test/extractLoader.test.js

+18
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,24 @@ describe("extractLoader", () => {
155155
/<img src="\/other\/hi-dist\.jpg">/
156156
);
157157
}));
158+
it("should execute options.publicPath if it's defined as a function", done => {
159+
let publicPathCalledWithContext = false;
160+
const loaderContext = {
161+
async: () => () => done(),
162+
cacheable() {},
163+
query: {
164+
publicPath: context => {
165+
publicPathCalledWithContext = context === loaderContext;
166+
167+
return "";
168+
},
169+
},
170+
};
171+
172+
extractLoader.call(loaderContext, "");
173+
174+
expect(publicPathCalledWithContext).to.equal(true);
175+
});
158176
it("should support explicit loader chains", () => compile({testModule: "loader.html"}).then(() => {
159177
const loaderHtml = path.resolve(__dirname, "dist/loader-dist.html");
160178
const errJs = path.resolve(__dirname, "dist/err.js");

0 commit comments

Comments
 (0)