Skip to content

Commit 5f09729

Browse files
committed
feat: support named exports with any characters
A proposed change to `css-loader` will allow named exports to be any string, regardless of whether or not it is a valid identifier. The code generation in this project assumes that all exports will be a valid identifier, so the generation stage has been updated to take this into account.
1 parent d5e540b commit 5f09729

File tree

6 files changed

+74
-44
lines changed
  • src
  • test/cases
    • custom-loader-with-functional-exports/expected
    • es-module-concatenation-modules/expected
    • es-named-export/expected
    • es-named-export-output-module/expected
    • export-only-locals-and-es-named-export/expected

6 files changed

+74
-44
lines changed

src/loader.js

+31-15
Original file line numberDiff line numberDiff line change
@@ -242,23 +242,39 @@ function pitch(request) {
242242
return;
243243
}
244244

245-
const result = locals
246-
? namedExport
247-
? Object.keys(locals)
245+
const result = (function makeResult() {
246+
// nb: `locals` is reassigned to const to improve TypeScript narrowing.
247+
const scopeLocals = locals;
248+
if (scopeLocals) {
249+
if (namedExport) {
250+
const identifiers = Array.from(
251+
(function* generateIdentifiers() {
252+
let identifierId = 0;
253+
for (const key of Object.keys(scopeLocals)) {
254+
identifierId += 1;
255+
yield [`_${identifierId.toString(16)}`, key];
256+
}
257+
})()
258+
);
259+
const localsString = identifiers
248260
.map(
249-
(key) =>
250-
`\nexport var ${key} = ${stringifyLocal(
251-
/** @type {Locals} */ (locals)[key]
252-
)};`
261+
([id, key]) =>
262+
`\nvar ${id} = ${stringifyLocal(scopeLocals[key])};`
253263
)
254-
.join("")
255-
: `\n${
256-
esModule ? "export default" : "module.exports ="
257-
} ${JSON.stringify(locals)};`
258-
: esModule
259-
? `\nexport {};`
260-
: "";
261-
264+
.join("");
265+
const exportsString = `export { ${identifiers
266+
.map(([id, key]) => `${id} as ${JSON.stringify(key)}`)
267+
.join(", ")} }`;
268+
return `${localsString};\n${exportsString};\n`;
269+
}
270+
return `\n${
271+
esModule ? "export default" : "module.exports = "
272+
} ${JSON.stringify(locals)};`;
273+
} else if (esModule) {
274+
return "\nexport {};";
275+
}
276+
return "";
277+
})();
262278
let resultSource = `// extracted by ${MiniCssExtractPlugin.pluginName}`;
263279

264280
// only attempt hotreloading if the css is actually used for something other than hash values

test/cases/custom-loader-with-functional-exports/expected/main.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77

88
__webpack_require__.r(__webpack_exports__);
99
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
10-
/* harmony export */ cnA: () => (/* binding */ cnA),
11-
/* harmony export */ cnB: () => (/* binding */ cnB)
10+
/* harmony export */ cnA: () => (/* binding */ _1),
11+
/* harmony export */ cnB: () => (/* binding */ _2)
1212
/* harmony export */ });
1313
// extracted by mini-css-extract-plugin
14-
var cnA = () => "class-name-a";
15-
var cnB = () => "class-name-b";
14+
var _1 = () => "class-name-a";
15+
var _2 = () => "class-name-b";;
16+
17+
1618

1719
/***/ })
1820
/******/ ]);

test/cases/es-module-concatenation-modules/expected/main.js

+13-7
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,21 @@ __webpack_require__.r(__webpack_exports__);
4141
__webpack_require__.d(__webpack_exports__, {
4242
a: () => (/* reexport */ a_namespaceObject),
4343
b: () => (/* reexport */ b_namespaceObject),
44-
c: () => (/* reexport */ c)
44+
c: () => (/* reexport */ c_1)
4545
});
4646

4747
// NAMESPACE OBJECT: ./a.css
4848
var a_namespaceObject = {};
4949
__webpack_require__.r(a_namespaceObject);
5050
__webpack_require__.d(a_namespaceObject, {
51-
a: () => (a)
51+
a: () => (_1)
5252
});
5353

5454
// NAMESPACE OBJECT: ./b.css
5555
var b_namespaceObject = {};
5656
__webpack_require__.r(b_namespaceObject);
5757
__webpack_require__.d(b_namespaceObject, {
58-
b: () => (b)
58+
b: () => (b_1)
5959
});
6060

6161
// NAMESPACE OBJECT: ./index.js
@@ -64,18 +64,24 @@ __webpack_require__.r(index_namespaceObject);
6464
__webpack_require__.d(index_namespaceObject, {
6565
a: () => (a_namespaceObject),
6666
b: () => (b_namespaceObject),
67-
c: () => (c)
67+
c: () => (c_1)
6868
});
6969

7070
;// CONCATENATED MODULE: ./a.css
7171
// extracted by mini-css-extract-plugin
72-
var a = "foo__a";
72+
var _1 = "foo__a";;
73+
74+
7375
;// CONCATENATED MODULE: ./b.css
7476
// extracted by mini-css-extract-plugin
75-
var b = "foo__b";
77+
var b_1 = "foo__b";;
78+
79+
7680
;// CONCATENATED MODULE: ./c.css
7781
// extracted by mini-css-extract-plugin
78-
var c = "foo__c";
82+
var c_1 = "foo__c";;
83+
84+
7985
;// CONCATENATED MODULE: ./index.js
8086
/* eslint-disable import/no-namespace */
8187

test/cases/es-named-export-output-module/expected/main.mjs

+8-6
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55

66
__webpack_require__.r(__webpack_exports__);
77
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
8-
/* harmony export */ aClass: () => (/* binding */ aClass),
9-
/* harmony export */ bClass: () => (/* binding */ bClass),
10-
/* harmony export */ cClass: () => (/* binding */ cClass)
8+
/* harmony export */ aClass: () => (/* binding */ _1),
9+
/* harmony export */ bClass: () => (/* binding */ _2),
10+
/* harmony export */ cClass: () => (/* binding */ _3)
1111
/* harmony export */ });
1212
// extracted by mini-css-extract-plugin
13-
var aClass = "foo__style__a-class";
14-
var bClass = "foo__style__b__class";
15-
var cClass = "foo__style__cClass";
13+
var _1 = "foo__style__a-class";
14+
var _2 = "foo__style__b__class";
15+
var _3 = "foo__style__cClass";;
16+
17+
1618

1719
/***/ })
1820
/******/ ]);

test/cases/es-named-export/expected/main.js

+8-6
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77

88
__webpack_require__.r(__webpack_exports__);
99
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
10-
/* harmony export */ aClass: () => (/* binding */ aClass),
11-
/* harmony export */ bClass: () => (/* binding */ bClass),
12-
/* harmony export */ cClass: () => (/* binding */ cClass)
10+
/* harmony export */ aClass: () => (/* binding */ _1),
11+
/* harmony export */ bClass: () => (/* binding */ _2),
12+
/* harmony export */ cClass: () => (/* binding */ _3)
1313
/* harmony export */ });
1414
// extracted by mini-css-extract-plugin
15-
var aClass = "foo__style__a-class";
16-
var bClass = "foo__style__b__class";
17-
var cClass = "foo__style__cClass";
15+
var _1 = "foo__style__a-class";
16+
var _2 = "foo__style__b__class";
17+
var _3 = "foo__style__cClass";;
18+
19+
1820

1921
/***/ })
2022
/******/ ]);

test/cases/export-only-locals-and-es-named-export/expected/main.js

+8-6
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77

88
__webpack_require__.r(__webpack_exports__);
99
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
10-
/* harmony export */ aClass: () => (/* binding */ aClass),
11-
/* harmony export */ bClass: () => (/* binding */ bClass),
12-
/* harmony export */ cClass: () => (/* binding */ cClass)
10+
/* harmony export */ aClass: () => (/* binding */ _1),
11+
/* harmony export */ bClass: () => (/* binding */ _2),
12+
/* harmony export */ cClass: () => (/* binding */ _3)
1313
/* harmony export */ });
1414
// extracted by mini-css-extract-plugin
15-
var aClass = "foo__style__a-class";
16-
var bClass = "foo__style__b__class";
17-
var cClass = "foo__style__cClass";
15+
var _1 = "foo__style__a-class";
16+
var _2 = "foo__style__b__class";
17+
var _3 = "foo__style__cClass";;
18+
19+
1820

1921
/***/ })
2022
/******/ ]);

0 commit comments

Comments
 (0)