Skip to content
This repository has been archived by the owner on Mar 17, 2021. It is now read-only.

Dynamic public path #334

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
92 changes: 92 additions & 0 deletions README.md
Expand Up @@ -269,6 +269,32 @@ module.exports = {
};
```

### `postTransformPublicPath`

Type: `Function`
Default: `undefined`

Specifies a custom function to post-process the generated public path. This can be used to prepend or append dynamic global variables that are only available at runtime, like `__webpack_public_path__`. This would not be possible with just `publicPath`, since it stringifies the values.

**webpack.config.js**

```js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
loader: 'file-loader',
options: {
publicPath: '/some/path/',
postTransformPublicPath: (p) => `__webpack_public_path__ + ${p}`,
},
},
],
},
};
```

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, i forgot, let's add Example use case for this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i pushed an example, is this what you mean?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, i see, just think about additional section in Example in README

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ups, i forgot to push the commit i was talking about 😅
i meant this one: 460127d

### `context`

Type: `String`
Expand Down Expand Up @@ -577,6 +603,72 @@ Result:
path/to/file.png?e43b20c069c4a01867c31e98cbce33c9
```

---
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use heading here instead ---, something like ### Dynamic public path with __webpack_public_path__ (maybe better name for heading)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i added a little paragraph for explaining the use case. makes sense?


**main.js**

```js
const namespace = process.env.NAMESPACE;
const assetPrefixForNamespace = (namespace) => {
switch (namespace) {
case 'prod':
return 'https://cache.myserver.net/web';
case 'uat':
return 'https://cache-uat.myserver.net/web';
case 'st':
return 'https://cache-st.myserver.net/web';
case 'dev':
return 'https://cache-dev.myserver.net/web';
default:
return '';
}
};
__webpack_public_path__ = `${assetPrefixForNamespace(namespace)}/`;
```

**file.js**

```js
import png from './image.png';
```

**webpack.config.js**

```js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
loader: 'file-loader',
options: {
context: '',
emitFile: true,
name: '[name].[hash].[ext]',
publicPath: 'static/assets/',
postTransformPublicPath: (p) => `__webpack_public_path__ + ${p}`,
outputPath: 'static/assets/',
},
},
],
},
};
```

Result when run with `NAMESPACE=prod` env variable:

```bash
# result
https://cache.myserver.net/web/static/assets/image.somehash.png
```

Result when run with `NAMESPACE=dev` env variable:

```bash
# result
https://cache-dev.myserver.net/web/static/assets/image.somehash.png
```

## Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.
Expand Down
4 changes: 4 additions & 0 deletions src/index.js
Expand Up @@ -47,6 +47,10 @@ export default function loader(content) {
publicPath = JSON.stringify(publicPath);
}

if (options.postTransformPublicPath) {
publicPath = options.postTransformPublicPath(publicPath);
}

if (typeof options.emitFile === 'undefined' || options.emitFile) {
this.emitFile(outputPath, content);
}
Expand Down
4 changes: 4 additions & 0 deletions src/options.json
Expand Up @@ -34,6 +34,10 @@
}
]
},
"postTransformPublicPath": {
"description": "A custom transformation function for post-processing the publicPath (https://github.com/webpack-contrib/file-loader#posttransformpublicpath).",
"instanceof": "Function"
},
"context": {
"description": "A custom file context (https://github.com/webpack-contrib/file-loader#context).",
"type": "string"
Expand Down
82 changes: 82 additions & 0 deletions test/__snapshots__/postTransformPublicPath-option.test.js.snap
@@ -0,0 +1,82 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`when applied with \`postTransformPublicPath\` option matches snapshot for appending to input parameter value 1`] = `
Object {
"assets": Array [
"9c87cbf3ba33126ffd25ae7f2f6bbafb.png",
],
"source": "module.exports = __webpack_public_path__ + \\"9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\" + \\"/test\\";",
}
`;

exports[`when applied with \`postTransformPublicPath\` option matches snapshot for returned input parameter value without modification 1`] = `
Object {
"assets": Array [
"9c87cbf3ba33126ffd25ae7f2f6bbafb.png",
],
"source": "module.exports = __webpack_public_path__ + \\"9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";",
}
`;

exports[`when applied with \`publicPath\` and \`postTransformPublicPath\` option \`{Function}\` value matches snapshot for appending to input parameter value 1`] = `
Object {
"assets": Array [
"9c87cbf3ba33126ffd25ae7f2f6bbafb.png",
],
"source": "module.exports = \\"public_path/9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\" + \\"?test=test\\";",
}
`;

exports[`when applied with \`publicPath\` and \`postTransformPublicPath\` option \`{Function}\` value matches snapshot for prefixing with __webpack_public_path__ 1`] = `
Object {
"assets": Array [
"9c87cbf3ba33126ffd25ae7f2f6bbafb.png",
],
"source": "module.exports = __webpack_public_path__ + \\"public_path/9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";",
}
`;

exports[`when applied with \`publicPath\` and \`postTransformPublicPath\` option \`{Function}\` value matches snapshot for prefixing with string 1`] = `
Object {
"assets": Array [
"9c87cbf3ba33126ffd25ae7f2f6bbafb.png",
],
"source": "module.exports = \\"path_prefix/\\" + \\"public_path/9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";",
}
`;

exports[`when applied with \`publicPath\` and \`postTransformPublicPath\` option \`{Function}\` value matches snapshot for returned input parameter value without modification 1`] = `
Object {
"assets": Array [
"9c87cbf3ba33126ffd25ae7f2f6bbafb.png",
],
"source": "module.exports = \\"public_path/9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";",
}
`;

exports[`when applied with \`publicPath\` and \`postTransformPublicPath\` option \`{String}\` value matches snapshot for appending to input parameter value 1`] = `
Object {
"assets": Array [
"9c87cbf3ba33126ffd25ae7f2f6bbafb.png",
],
"source": "module.exports = \\"public_path/9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\" + \\"?test=test\\";",
}
`;

exports[`when applied with \`publicPath\` and \`postTransformPublicPath\` option \`{String}\` value matches snapshot for prefixing with __webpack_public_path__ 1`] = `
Object {
"assets": Array [
"9c87cbf3ba33126ffd25ae7f2f6bbafb.png",
],
"source": "module.exports = __webpack_public_path__ + \\"public_path/9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";",
}
`;

exports[`when applied with \`publicPath\` and \`postTransformPublicPath\` option \`{String}\` value matches snapshot for returned input parameter value without modification 1`] = `
Object {
"assets": Array [
"9c87cbf3ba33126ffd25ae7f2f6bbafb.png",
],
"source": "module.exports = \\"public_path/9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";",
}
`;
173 changes: 173 additions & 0 deletions test/postTransformPublicPath-option.test.js
@@ -0,0 +1,173 @@
import webpack from './helpers/compiler';

describe('when applied with `postTransformPublicPath` option', () => {
it('matches snapshot for returned input parameter value without modification', async () => {
const config = {
loader: {
test: /(png|jpg|svg)/,
options: {
postTransformPublicPath: (p) => p,
},
},
};

const stats = await webpack('fixture.js', config);
const [module] = stats.toJson().modules;
const { assets, source } = module;

expect({ assets, source }).toMatchSnapshot();
});

it('matches snapshot for appending to input parameter value', async () => {
const config = {
loader: {
test: /(png|jpg|svg)/,
options: {
postTransformPublicPath: (p) => `${p} + "/test"`,
},
},
};

const stats = await webpack('fixture.js', config);
const [module] = stats.toJson().modules;
const { assets, source } = module;

expect({ assets, source }).toMatchSnapshot();
});
});

describe('when applied with `publicPath` and `postTransformPublicPath` option', () => {
describe('`{String}` value', () => {
it('matches snapshot for returned input parameter value without modification', async () => {
const config = {
loader: {
test: /(png|jpg|svg)/,
options: {
publicPath: 'public_path/',
postTransformPublicPath: (p) => p,
},
},
};

const stats = await webpack('fixture.js', config);
const [module] = stats.toJson().modules;
const { assets, source } = module;

expect({ assets, source }).toMatchSnapshot();
});

it('matches snapshot for appending to input parameter value', async () => {
const config = {
loader: {
test: /(png|jpg|svg)/,
options: {
publicPath: 'public_path/',
postTransformPublicPath: (p) => `${p} + "?test=test"`,
},
},
};

const stats = await webpack('fixture.js', config);
const [module] = stats.toJson().modules;
const { assets, source } = module;

expect({ assets, source }).toMatchSnapshot();
});

it('matches snapshot for prefixing with __webpack_public_path__', async () => {
const config = {
loader: {
test: /(png|jpg|svg)/,
options: {
publicPath: 'public_path/',
postTransformPublicPath: (p) => `__webpack_public_path__ + ${p}`,
},
},
};

const stats = await webpack('fixture.js', config);
const [module] = stats.toJson().modules;
const { assets, source } = module;

expect({ assets, source }).toMatchSnapshot();
});
});

describe('`{Function}` value', () => {
it('matches snapshot for returned input parameter value without modification', async () => {
const config = {
loader: {
test: /(png|jpg|svg)/,
options: {
publicPath(url) {
return `public_path/${url}`;
},
postTransformPublicPath: (p) => p,
},
},
};

const stats = await webpack('fixture.js', config);
const [module] = stats.toJson().modules;
const { assets, source } = module;

expect({ assets, source }).toMatchSnapshot();
});

it('matches snapshot for appending to input parameter value', async () => {
const config = {
loader: {
test: /(png|jpg|svg)/,
options: {
publicPath(url) {
return `public_path/${url}`;
},
postTransformPublicPath: (p) => `${p} + "?test=test"`,
},
},
};

const stats = await webpack('fixture.js', config);
const [module] = stats.toJson().modules;
const { assets, source } = module;

expect({ assets, source }).toMatchSnapshot();
});

it('matches snapshot for prefixing with string', async () => {
const config = {
loader: {
test: /(png|jpg|svg)/,
options: {
publicPath: 'public_path/',
postTransformPublicPath: (p) => `"path_prefix/" + ${p}`,
},
},
};

const stats = await webpack('fixture.js', config);
const [module] = stats.toJson().modules;
const { assets, source } = module;

expect({ assets, source }).toMatchSnapshot();
});

it('matches snapshot for prefixing with __webpack_public_path__', async () => {
const config = {
loader: {
test: /(png|jpg|svg)/,
options: {
publicPath: 'public_path/',
postTransformPublicPath: (p) => `__webpack_public_path__ + ${p}`,
},
},
};

const stats = await webpack('fixture.js', config);
const [module] = stats.toJson().modules;
const { assets, source } = module;

expect({ assets, source }).toMatchSnapshot();
});
});
});