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

Commit 08a7a59

Browse files
fix: fallback options behaviour
1 parent e4d10a2 commit 08a7a59

17 files changed

+279
-233
lines changed

src/index.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,18 @@ export default function loader(src) {
4242
}
4343

4444
// Normalize the fallback.
45-
const { loader: fallbackLoader, query: fallbackQuery } = normalizeFallback(
46-
options.fallback,
47-
options
48-
);
45+
const {
46+
loader: fallbackLoader,
47+
options: fallbackOptions,
48+
} = normalizeFallback(options.fallback, options);
4949

5050
// Require the fallback.
5151
const fallback = require(fallbackLoader);
5252

5353
// Call the fallback, passing a copy of the loader context. The copy has the query replaced. This way, the fallback
5454
// loader receives the query which was intended for it instead of the query which was intended for url-loader.
5555
const fallbackLoaderContext = Object.assign({}, this, {
56-
query: fallbackQuery,
56+
query: fallbackOptions,
5757
});
5858

5959
return fallback.call(fallbackLoaderContext, src);

src/utils/normalizeFallback.js

Lines changed: 18 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,27 @@
1-
function normalizeFallbackString(fallbackString, originalOptions) {
2-
const index = fallbackString.indexOf('?');
3-
if (index >= 0) {
4-
return {
5-
loader: fallbackString.substr(0, index),
6-
query: fallbackString.substr(index),
7-
};
8-
}
1+
import loaderUtils from 'loader-utils';
92

10-
// To remain consistent with version 1.0.1, pass any other options which were provided to url-loader to the fallback loader.
11-
const { fallback, limit, mimetype, ...otherOptions } = originalOptions;
3+
export default function normalizeFallback(fallback, originalOptions) {
4+
let loader = 'file-loader';
5+
let options = {};
126

13-
return {
14-
loader: fallbackString,
15-
query: otherOptions,
16-
};
17-
}
7+
if (typeof fallback === 'string') {
8+
loader = fallback;
189

19-
function normalizeFallbackObject(fallbackObject) {
20-
return {
21-
loader: fallbackObject.loader,
22-
query: fallbackObject.options,
23-
};
24-
}
10+
const index = fallback.indexOf('?');
2511

26-
/**
27-
* Converts the fallback option, which can be a string or an object, to an object with a loader and a query. The result
28-
* has this form:
29-
* {
30-
* loader: 'file-loader',
31-
* query: '?name=[name].[ext]'
32-
* }
33-
* Note that the returned query can be either a string or an object.
34-
*/
35-
export default function normalizeFallback(fallback, originalOptions) {
36-
// If no fallback was provided, use file-loader.
37-
if (!fallback) {
38-
return normalizeFallbackString('file-loader', originalOptions);
12+
if (index >= 0) {
13+
loader = fallback.substr(0, index);
14+
options = loaderUtils.parseQuery(fallback.substr(index));
15+
}
3916
}
4017

41-
if (typeof fallback === 'string') {
42-
return normalizeFallbackString(fallback, originalOptions);
18+
if (fallback !== null && typeof fallback === 'object') {
19+
({ loader, options } = fallback);
4320
}
4421

45-
return normalizeFallbackObject(fallback);
22+
options = Object.assign({}, originalOptions, options);
23+
24+
delete options.fallback;
25+
26+
return { loader, options };
4627
}

test/__snapshots__/limit-option.test.js.snap

Lines changed: 9 additions & 0 deletions
Large diffs are not rendered by default.

test/__snapshots__/mimetype-option.test.js.snap

Lines changed: 5 additions & 0 deletions
Large diffs are not rendered by default.

test/cjs.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import loader from '../src';
2+
import CJSLoader from '../src/cjs';
3+
4+
describe('CJS', () => {
5+
it('should exported loader', () => {
6+
expect(CJSLoader).toEqual(loader);
7+
});
8+
});

test/fallback-option.test.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/* eslint-disable
2+
prefer-destructuring,
3+
*/
4+
import path from 'path';
5+
6+
import webpack from '@webpack-contrib/test-utils';
7+
8+
describe('fallback option', () => {
9+
test('{undefined}', async () => {
10+
const config = {
11+
rules: [
12+
{
13+
test: /\.png$/,
14+
use: {
15+
loader: path.join(__dirname, '../src'),
16+
options: {},
17+
},
18+
},
19+
],
20+
};
21+
22+
const stats = await webpack('fixture.js', config);
23+
const { source } = stats.toJson().modules[0];
24+
25+
expect(source).toMatchSnapshot();
26+
});
27+
28+
test('{String}', async () => {
29+
const config = {
30+
rules: [
31+
{
32+
test: /\.png$/,
33+
use: {
34+
loader: path.join(__dirname, '../src'),
35+
options: {
36+
limit: Number.MIN_SAFE_INTEGER,
37+
name: '[name].[hash].[ext]',
38+
unknown: 'value',
39+
fallback: path.join(__dirname, 'fixtures/x-custom-loader'),
40+
},
41+
},
42+
},
43+
],
44+
};
45+
46+
const stats = await webpack('fixture.js', config);
47+
const { source } = stats.toJson().modules[0];
48+
49+
expect(source).toMatchSnapshot();
50+
});
51+
52+
test('{String} (with query)', async () => {
53+
const config = {
54+
rules: [
55+
{
56+
test: /\.png$/,
57+
use: {
58+
loader: path.join(__dirname, '../src'),
59+
options: {
60+
limit: Number.MIN_SAFE_INTEGER,
61+
name: '[name].[hash].[ext]',
62+
unknown: 'value',
63+
fallback: `${path.join(
64+
__dirname,
65+
'fixtures/x-custom-loader'
66+
)}?name=fallback-[hash].[ext]&unknown=fallback-value`,
67+
},
68+
},
69+
},
70+
],
71+
};
72+
73+
const stats = await webpack('fixture.js', config);
74+
const { source } = stats.toJson().modules[0];
75+
76+
expect(source).toMatchSnapshot();
77+
});
78+
79+
test('{Object}', async () => {
80+
const config = {
81+
rules: [
82+
{
83+
test: /\.png$/,
84+
use: {
85+
loader: path.join(__dirname, '../src'),
86+
options: {
87+
limit: Number.MIN_SAFE_INTEGER,
88+
name: '[name].[hash].[ext]',
89+
unknown: 'value',
90+
fallback: {
91+
loader: path.join(__dirname, 'fixtures/x-custom-loader'),
92+
options: {
93+
name: 'fallback-[hash].[ext]',
94+
unknown: 'fallback-other-value',
95+
},
96+
},
97+
},
98+
},
99+
},
100+
],
101+
};
102+
103+
const stats = await webpack('fixture.js', config);
104+
const { source } = stats.toJson().modules[0];
105+
106+
expect(source).toMatchSnapshot();
107+
});
108+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const utils = require('loader-utils');
2+
3+
module.exports = function loader() {
4+
const options = utils.getOptions(this);
5+
6+
return `module.exports=${JSON.stringify(options)}`;
7+
};

test/limit-option.test.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* eslint-disable
2+
prefer-destructuring,
3+
*/
4+
import webpack from '@webpack-contrib/test-utils';
5+
6+
describe('limit option', () => {
7+
test('{undefined}', async () => {
8+
const config = {
9+
loader: {
10+
test: /\.png$/,
11+
options: {},
12+
},
13+
};
14+
15+
const stats = await webpack('fixture.js', config);
16+
const { source } = stats.toJson().modules[0];
17+
18+
expect(source).toMatchSnapshot();
19+
});
20+
21+
test('{Number} (big)', async () => {
22+
const config = {
23+
loader: {
24+
test: /\.png$/,
25+
options: {
26+
limit: Number.MAX_SAFE_INTEGER,
27+
},
28+
},
29+
};
30+
31+
const stats = await webpack('fixture.js', config);
32+
const { source } = stats.toJson().modules[0];
33+
34+
expect(source).toMatchSnapshot();
35+
});
36+
37+
test('{Number} (less)', async () => {
38+
const config = {
39+
loader: {
40+
test: /\.png$/,
41+
options: {
42+
limit: Number.MIN_SAFE_INTEGER,
43+
},
44+
},
45+
};
46+
47+
const stats = await webpack('fixture.js', config);
48+
const { source } = stats.toJson().modules[0];
49+
50+
expect(source).toMatchSnapshot();
51+
});
52+
53+
test('{String} (big)', async () => {
54+
const config = {
55+
loader: {
56+
test: /\.png$/,
57+
options: {
58+
limit: '8192',
59+
},
60+
},
61+
};
62+
63+
const stats = await webpack('fixture.js', config);
64+
const { source } = stats.toJson().modules[0];
65+
66+
expect(source).toMatchSnapshot();
67+
});
68+
});

test/mimetype-option.test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* eslint-disable
2+
prefer-destructuring,
3+
*/
4+
import webpack from '@webpack-contrib/test-utils';
5+
6+
describe('mimetype option', () => {
7+
test('{undefined}', async () => {
8+
const config = {
9+
loader: {
10+
test: /\.png$/,
11+
options: {},
12+
},
13+
};
14+
15+
const stats = await webpack('fixture.js', config);
16+
const { source } = stats.toJson().modules[0];
17+
18+
expect(source).toMatchSnapshot();
19+
});
20+
21+
test('{String}', async () => {
22+
const config = {
23+
loader: {
24+
test: /\.png$/,
25+
options: {
26+
mimetype: 'image/x-custom',
27+
},
28+
},
29+
};
30+
31+
const stats = await webpack('fixture.js', config);
32+
const { source } = stats.toJson().modules[0];
33+
34+
expect(source).toMatchSnapshot();
35+
});
36+
});

test/options/__snapshots__/fallback.test.js.snap

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)