mirror of https://github.com/webpack/webpack.git
Merge pull request #10017 from webpack/feat-getOptions-util-for-loader
feat: getOptions util for loader
This commit is contained in:
commit
bd08639607
|
|
@ -5,7 +5,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const parseJson = require("json-parse-better-errors");
|
||||
const { getContext, runLoaders } = require("loader-runner");
|
||||
const querystring = require("querystring");
|
||||
const validateOptions = require("schema-utils");
|
||||
const { SyncHook } = require("tapable");
|
||||
const {
|
||||
CachedSource,
|
||||
|
|
@ -49,6 +52,13 @@ const makeSerializable = require("./util/makeSerializable");
|
|||
/** @typedef {import("./util/Hash")} Hash */
|
||||
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
|
||||
|
||||
/**
|
||||
* @typedef {Object} LoaderItem
|
||||
* @property {string} loader
|
||||
* @property {any} options
|
||||
* @property {string?} ident
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string} context absolute context path
|
||||
* @param {string} source a source path
|
||||
|
|
@ -166,7 +176,7 @@ class NormalModule extends Module {
|
|||
* @param {string} options.request request string
|
||||
* @param {string} options.userRequest request intented by user (without loaders from config)
|
||||
* @param {string} options.rawRequest request without resolving
|
||||
* @param {TODO[]} options.loaders list of loaders
|
||||
* @param {LoaderItem[]} options.loaders list of loaders
|
||||
* @param {string} options.resource path + query of the real resource
|
||||
* @param {string | undefined} options.matchResource path + query of the matched resource (virtuel
|
||||
* @param {Parser} options.parser the parser used
|
||||
|
|
@ -204,7 +214,7 @@ class NormalModule extends Module {
|
|||
this.resource = resource;
|
||||
/** @type {string | undefined} */
|
||||
this.matchResource = matchResource;
|
||||
/** @type {TODO[]} */
|
||||
/** @type {LoaderItem[]} */
|
||||
this.loaders = loaders;
|
||||
if (resolveOptions !== undefined) {
|
||||
// already declared in super class
|
||||
|
|
@ -350,6 +360,44 @@ class NormalModule extends Module {
|
|||
};
|
||||
const loaderContext = {
|
||||
version: 2,
|
||||
getOptions: schema => {
|
||||
const loader = this.getCurrentLoader(loaderContext);
|
||||
|
||||
let { options } = loader;
|
||||
|
||||
if (typeof options === "string") {
|
||||
if (options.substr(0, 1) === "{" && options.substr(-1) === "}") {
|
||||
try {
|
||||
options = parseJson(options);
|
||||
} catch (e) {
|
||||
throw new Error(`Cannot parse string options: ${e.message}`);
|
||||
}
|
||||
} else {
|
||||
options = querystring.parse(options, "&", "=", {
|
||||
maxKeys: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (options === null || options === undefined) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (schema) {
|
||||
let name = "Loader";
|
||||
let baseDataPath = "options";
|
||||
let match;
|
||||
if (schema.title && (match = /^(.+) (.+)$/.exec(schema.title))) {
|
||||
[, name, baseDataPath] = match;
|
||||
}
|
||||
validateOptions(schema, options, {
|
||||
name,
|
||||
baseDataPath
|
||||
});
|
||||
}
|
||||
|
||||
return options;
|
||||
},
|
||||
emitWarning: warning => {
|
||||
if (!(warning instanceof Error)) {
|
||||
warning = new NonErrorEmittedError(warning);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
module.exports = [
|
||||
{ code: /DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING/ },
|
||||
{ code: /DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING/ },
|
||||
{ code: /DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING/ },
|
||||
{ code: /DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING/ },
|
||||
{ code: /DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING/ },
|
||||
{ code: /DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING/ },
|
||||
{ code: /DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING/ }
|
||||
];
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
module.exports = [
|
||||
[
|
||||
/\.\/loader-1\.js/,
|
||||
/Loader has been/,
|
||||
/options\.arg6\.bar\.baz should be a string/
|
||||
],
|
||||
[
|
||||
/\.\/loader-2\.js/,
|
||||
/Custom Loader Name has been/,
|
||||
/configuration\.arg should be true/
|
||||
]
|
||||
];
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
it("should get options", function() {
|
||||
expect(require("./a")).toStrictEqual({
|
||||
arg: true,
|
||||
arg1: null,
|
||||
arg3: 1234567890,
|
||||
arg4: "string",
|
||||
arg5: [1, 2, 3],
|
||||
arg6: { foo: "value", bar: { baz: "other-value" } }
|
||||
});
|
||||
expect(require("./b")).toStrictEqual({
|
||||
arg: true,
|
||||
arg1: null,
|
||||
arg3: 1234567890,
|
||||
arg4: "string",
|
||||
arg5: [1, 2, 3],
|
||||
arg6: { foo: "value", bar: { baz: "other-value" } }
|
||||
});
|
||||
expect(require("./c")).toStrictEqual({
|
||||
arg: true,
|
||||
arg1: null,
|
||||
arg3: 1234567890,
|
||||
arg4: "string",
|
||||
arg5: [1, 2, 3],
|
||||
arg6: { foo: "value", bar: { baz: "other-value" } }
|
||||
});
|
||||
expect(require("./d")).toStrictEqual({
|
||||
arg4: "text"
|
||||
});
|
||||
expect(require("./e")).toStrictEqual({});
|
||||
expect(require("./f")).toStrictEqual({
|
||||
delicious: "",
|
||||
name: "cheesecake",
|
||||
slices: "8",
|
||||
warm: "false"
|
||||
});
|
||||
expect(require("./g")).toStrictEqual({
|
||||
"=": "="
|
||||
});
|
||||
expect(require("./h")).toStrictEqual({
|
||||
foo: "bar"
|
||||
});
|
||||
expect(require("./i")).toStrictEqual({
|
||||
foo: "bar"
|
||||
});
|
||||
});
|
||||
|
||||
const never = false;
|
||||
if (never) {
|
||||
require("./error1");
|
||||
require("./error2");
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
const schema = require("./loader-1.options");
|
||||
|
||||
module.exports = function() {
|
||||
const options = this.getOptions(schema);
|
||||
|
||||
const json = JSON.stringify(options)
|
||||
.replace(/\u2028/g, "\\u2028")
|
||||
.replace(/\u2029/g, "\\u2029");
|
||||
|
||||
return `module.exports = ${json}`;
|
||||
};
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"arg": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"arg1": {
|
||||
"type": "null"
|
||||
},
|
||||
"arg2": {},
|
||||
"arg3": {
|
||||
"type": "number"
|
||||
},
|
||||
"arg4": {
|
||||
"type": "string"
|
||||
},
|
||||
"arg5": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"arg6": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"foo": {
|
||||
"type": "string"
|
||||
},
|
||||
"bar": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"baz": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
const schema = require("./loader-2.options");
|
||||
|
||||
module.exports = function() {
|
||||
const options = this.getOptions(schema);
|
||||
|
||||
const json = JSON.stringify(options)
|
||||
.replace(/\u2028/g, "\\u2028")
|
||||
.replace(/\u2029/g, "\\u2029");
|
||||
|
||||
return `module.exports = ${json}`;
|
||||
};
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"title": "Custom Loader Name configuration",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"arg": {
|
||||
"enum": [true]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
module.exports = function() {
|
||||
const options = this.getOptions();
|
||||
|
||||
const json = JSON.stringify(options)
|
||||
.replace(/\u2028/g, '\\u2028')
|
||||
.replace(/\u2029/g, '\\u2029');
|
||||
|
||||
return `module.exports = ${json}`;
|
||||
};
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
module.exports = {
|
||||
mode: "none",
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /a\.js$/,
|
||||
loader: "./loader",
|
||||
options: {
|
||||
arg: true,
|
||||
arg1: null,
|
||||
arg2: undefined,
|
||||
arg3: 1234567890,
|
||||
arg4: "string",
|
||||
arg5: [1, 2, 3],
|
||||
arg6: { foo: "value", bar: { baz: "other-value" } }
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /b\.js$/,
|
||||
loader: "./loader-1",
|
||||
options: {
|
||||
arg: true,
|
||||
arg1: null,
|
||||
arg2: undefined,
|
||||
arg3: 1234567890,
|
||||
arg4: "string",
|
||||
arg5: [1, 2, 3],
|
||||
arg6: { foo: "value", bar: { baz: "other-value" } }
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /c\.js$/,
|
||||
loader: "./loader-1",
|
||||
options: JSON.stringify({
|
||||
arg: true,
|
||||
arg1: null,
|
||||
arg2: undefined,
|
||||
arg3: 1234567890,
|
||||
arg4: "string",
|
||||
arg5: [1, 2, 3],
|
||||
arg6: { foo: "value", bar: { baz: "other-value" } }
|
||||
})
|
||||
},
|
||||
{
|
||||
test: /d\.js$/,
|
||||
loader: "./loader-1",
|
||||
options: "arg4=text"
|
||||
},
|
||||
{
|
||||
test: /d\.js$/,
|
||||
loader: "./loader",
|
||||
options: ""
|
||||
},
|
||||
{
|
||||
test: /f\.js$/,
|
||||
loader: "./loader",
|
||||
options: "name=cheesecake&slices=8&delicious&warm=false"
|
||||
},
|
||||
{
|
||||
test: /g\.js$/,
|
||||
loader: "./loader",
|
||||
options: "%3d=%3D"
|
||||
},
|
||||
{
|
||||
test: /h\.js$/,
|
||||
loader: "./loader",
|
||||
options: "foo=bar"
|
||||
},
|
||||
{
|
||||
test: /i\.js$/,
|
||||
loader: "./loader",
|
||||
options: `${JSON.stringify({
|
||||
foo: "bar"
|
||||
})}`
|
||||
},
|
||||
{
|
||||
test: /error1\.js$/,
|
||||
loader: "./loader-1",
|
||||
options: {
|
||||
arg6: { foo: "value", bar: { baz: 42 } }
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /error2\.js$/,
|
||||
loader: "./loader-2",
|
||||
options: {
|
||||
arg: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
Loading…
Reference in New Issue