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

Commit

Permalink
feat: support the query template for the name option
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Feb 19, 2020
1 parent 5703c58 commit cb6fafc
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 16 deletions.
57 changes: 55 additions & 2 deletions README.md
Expand Up @@ -102,7 +102,10 @@ module.exports = {
test: /\.(png|jpe?g|gif)$/i,
loader: 'file-loader',
options: {
name(file) {
name(resourcePath, resourceQuery) {
// `resourcePath` - `/absolute/path/to/file.js`
// `resourceQuery` - `?foo=bar`

if (process.env.NODE_ENV === 'development') {
return '[path][name].[ext]';
}
Expand Down Expand Up @@ -439,6 +442,13 @@ Default: `file.folder`

The folder of the resource is in.

### `[query]`

Type: `String`
Default: `file.query`

The query of the resource, i.e. `?foo=bar`.

### `[emoji]`

Type: `String`
Expand Down Expand Up @@ -619,14 +629,55 @@ Result:
path/to/file.png?e43b20c069c4a01867c31e98cbce33c9
```

### CDN

The following examples show how to use `file-loader` for CDN uses query params.

**file.js**

```js
import png from './directory/image.png?width=300&height=300';
```

**webpack.config.js**

```js
module.exports = {
output: {
publicPath: 'https://cdn.example.com/',
},
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[path][name].[ext][query]',
},
},
],
},
],
},
};
```

Result:

```bash
# result
https://cdn.example.com/directory/image.png?width=300&height=300
```

### Dynamic public path depending on environment variable at run time

An application might want to configure different CDN hosts depending on an environment variable that is only available when running the application. This can be an advantage, as only one build of the application is necessary, which behaves differntly depending on environment variables of the deployment environment. Since file-loader is applied when compiling the application, and not when running it, the environment variable cannot be used in the file-loader configuration. A way around this is setting the `__webpack_public_path__` to the desired CDN host depending on the environment variable at the entrypoint of the application. The option `postTransformPublicPath` can be used to configure a custom path depending on a variable like `__webpack_public_path__`.

**main.js**

```js
const namespace = process.env.NAMESPACE;
const assetPrefixForNamespace = (namespace) => {
switch (namespace) {
case 'prod':
Expand All @@ -641,6 +692,8 @@ const assetPrefixForNamespace = (namespace) => {
return '';
}
};
const namespace = process.env.NAMESPACE;

__webpack_public_path__ = `${assetPrefixForNamespace(namespace)}/`;
```

Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -41,7 +41,7 @@
"webpack": "^4.0.0 || ^5.0.0"
},
"dependencies": {
"loader-utils": "^1.2.3",
"loader-utils": "^1.4.0",
"schema-utils": "^2.5.0"
},
"devDependencies": {
Expand Down
10 changes: 8 additions & 2 deletions test/__snapshots__/name-option.test.js.snap
@@ -1,14 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`"name" option should work for CDN support query params: errors 1`] = `Array []`;

exports[`"name" option should work for CDN support query params: result 1`] = `"https://cdn.example.com/nested/file.png?foo=bar"`;

exports[`"name" option should work for CDN support query params: warnings 1`] = `Array []`;

exports[`"name" option should work with "Function" value: errors 1`] = `Array []`;

exports[`"name" option should work with "Function" value: result 1`] = `"9c87cbf3ba33126ffd25ae7f2f6bbafb.function.png"`;
exports[`"name" option should work with "Function" value: result 1`] = `"9c87cbf3ba33126ffd25ae7f2f6bbafb.function.png?foo=bar"`;

exports[`"name" option should work with "Function" value: warnings 1`] = `Array []`;

exports[`"name" option should work with "String" value: errors 1`] = `Array []`;

exports[`"name" option should work with "String" value: result 1`] = `"9c87cbf3ba33126ffd25ae7f2f6bbafb.string.png"`;
exports[`"name" option should work with "String" value: result 1`] = `"9c87cbf3ba33126ffd25ae7f2f6bbafb.string.png?foo=bar"`;

exports[`"name" option should work with "String" value: warnings 1`] = `Array []`;

Expand Down
6 changes: 6 additions & 0 deletions test/fixtures/cdn.js
@@ -0,0 +1,6 @@
/* eslint-disable */
import png from './nested/file.png?foo=bar#hash';

__export__ = png;

export default png;
Binary file added test/fixtures/nested/file.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/fixtures/simple.js
@@ -1,5 +1,5 @@
/* eslint-disable */
import png from './file.png';
import png from './file.png?foo=bar';

__export__ = png;

Expand Down
37 changes: 34 additions & 3 deletions test/name-option.test.js
@@ -1,3 +1,5 @@
import path from 'path';

import {
compile,
execute,
Expand All @@ -22,7 +24,7 @@ describe('"name" option', () => {

it('should work with "String" value', async () => {
const compiler = getCompiler('simple.js', {
name: '[hash].string.[ext]',
name: '[hash].string.[ext][query]',
});
const stats = await compile(compiler);

Expand All @@ -37,8 +39,11 @@ describe('"name" option', () => {

it('should work with "Function" value', async () => {
const compiler = getCompiler('simple.js', {
name() {
return '[hash].function.[ext]';
name(resourcePath, resourceQuery) {
expect(resourcePath).toBeDefined();
expect(resourceQuery).toBeDefined();

return '[hash].function.[ext][query]';
},
});
const stats = await compile(compiler);
Expand All @@ -51,4 +56,30 @@ describe('"name" option', () => {
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work for CDN support query params', async () => {
const compiler = getCompiler(
'cdn.js',
{
name: '[path][name].[ext][query]',
},
{
output: {
path: path.resolve(__dirname, './outputs'),
publicPath: 'https://cdn.example.com/',
filename: '[name].bundle.js',
chunkFilename: '[name].chunk.js',
},
}
);
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});
});

0 comments on commit cb6fafc

Please sign in to comment.