Skip to content

Commit c6d2066

Browse files
feat: added the exportType option
1 parent bce2c17 commit c6d2066

22 files changed

+3441
-129
lines changed

README.md

+180-12
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,15 @@ If, for one reason or another, you need to extract CSS as a file (i.e. do not st
8787

8888
## Options
8989

90-
| Name | Type | Default | Description |
91-
| :-----------------------------------: | :-------------------------: | :----------------: | :----------------------------------------------------------------------------------------------------------------------- |
92-
| **[`url`](#url)** | `{Boolean\|Object}` | `true` | Allows to enables/disables `url()`/`image-set()` functions handling |
93-
| **[`import`](#import)** | `{Boolean\|Object}` | `true` | Allows to enables/disables `@import` at-rules handling |
94-
| **[`modules`](#modules)** | `{Boolean\|String\|Object}` | `{auto: true}` | Allows to enables/disables or setup CSS Modules options |
95-
| **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps |
96-
| **[`importLoaders`](#importloaders)** | `{Number}` | `0` | Allows enables/disables or setups number of loaders applied before CSS loader for `@import`/CSS Modules and ICSS imports |
97-
| **[`esModule`](#esmodule)** | `{Boolean}` | `true` | Use ES modules syntax |
90+
| Name | Type | Default | Description |
91+
| :-----------------------------------: | :------------------------------: | :----------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
92+
| **[`url`](#url)** | `{Boolean\|Object}` | `true` | Allows to enables/disables `url()`/`image-set()` functions handling |
93+
| **[`import`](#import)** | `{Boolean\|Object}` | `true` | Allows to enables/disables `@import` at-rules handling |
94+
| **[`modules`](#modules)** | `{Boolean\|String\|Object}` | `{auto: true}` | Allows to enables/disables or setup CSS Modules options |
95+
| **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps |
96+
| **[`importLoaders`](#importloaders)** | `{Number}` | `0` | Allows enables/disables or setups number of loaders applied before CSS loader for `@import`/CSS Modules and ICSS imports |
97+
| **[`esModule`](#esmodule)** | `{Boolean}` | `true` | Use ES modules syntax |
98+
| **[`exportType`](#exporttype)** | `{'array' \| 'css-style-sheet'}` | `array` | Allows exporting styles as array with modules or [constructable stylesheet](https://developers.google.com/web/updates/2019/02/constructable-stylesheets) (i.e. [`CSSStyleSheet`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet)) |
9899

99100
### `url`
100101

@@ -1269,6 +1270,173 @@ module.exports = {
12691270
};
12701271
```
12711272

1273+
### `exportType`
1274+
1275+
Type: `'array' | 'css-style-sheet'`
1276+
Default: `'array'`
1277+
1278+
Allows exporting styles as array with modules or [constructable stylesheet](https://developers.google.com/web/updates/2019/02/constructable-stylesheets) (i.e. [`CSSStyleSheet`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet)).
1279+
Default value is `'array'`, i.e. loader exports array of modules with specific API which is used in `style-loader` or other.
1280+
1281+
**webpack.config.js**
1282+
1283+
```js
1284+
module.exports = {
1285+
module: {
1286+
rules: [
1287+
{
1288+
assert: { type: "css" },
1289+
loader: "css-loader",
1290+
options: {
1291+
exportType: "css-style-sheet",
1292+
},
1293+
},
1294+
],
1295+
},
1296+
};
1297+
```
1298+
1299+
**src/index.js**
1300+
1301+
```js
1302+
import sheet from "./styles.css" assert { type: "css" };
1303+
1304+
document.adoptedStyleSheets = [sheet];
1305+
shadowRoot.adoptedStyleSheets = [sheet];
1306+
```
1307+
1308+
#### `'array'`
1309+
1310+
The default export is array of modules with specific API which is used in `style-loader` or other.
1311+
1312+
**webpack.config.js**
1313+
1314+
```js
1315+
module.exports = {
1316+
module: {
1317+
rules: [
1318+
{
1319+
test: /\.(sa|sc|c)ss$/i,
1320+
use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"],
1321+
},
1322+
],
1323+
},
1324+
};
1325+
```
1326+
1327+
**src/index.js**
1328+
1329+
```js
1330+
// `style-loader` applies styles to DOM
1331+
import "./styles.css";
1332+
```
1333+
1334+
#### `'css-style-sheet'`
1335+
1336+
> `@import` rules not yet allowed, more [information](https://web.dev/css-module-scripts/#@import-rules-not-yet-allowed)
1337+
> ⚠ You don't need [`style-loader`](https://github.com/webpack-contrib/style-loader) anymore, please remove it.
1338+
> ⚠ The `esModules` option should be enabled if you want to use it with [`CSS modules`](https://github.com/webpack-contrib/css-loader#modules), by default for locals will be used [named export](https://github.com/webpack-contrib/css-loader#namedexport).
1339+
> ⚠ Source maps are not currently supported in `Chrome` due [bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1174094&q=CSSStyleSheet%20source%20maps&can=2)
1340+
1341+
The default export is a [constructable stylesheet](https://developers.google.com/web/updates/2019/02/constructable-stylesheets) (i.e. [`CSSStyleSheet`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet)).
1342+
1343+
Useful for [custom elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) and shadow DOM.
1344+
1345+
More information:
1346+
1347+
- [Using CSS Module Scripts to import stylesheets](https://web.dev/css-module-scripts/)
1348+
- [Constructable Stylesheets: seamless reusable styles](https://developers.google.com/web/updates/2019/02/constructable-stylesheets)
1349+
1350+
**webpack.config.js**
1351+
1352+
```js
1353+
module.exports = {
1354+
module: {
1355+
rules: [
1356+
{
1357+
assert: { type: "css" },
1358+
loader: "css-loader",
1359+
options: {
1360+
exportType: "css-style-sheet",
1361+
},
1362+
},
1363+
1364+
// For Sass/SCSS:
1365+
//
1366+
// {
1367+
// assert: { type: "css" },
1368+
// rules: [
1369+
// {
1370+
// loader: "css-loader",
1371+
// options: {
1372+
// exportType: "css-style-sheet",
1373+
// // Other options
1374+
// },
1375+
// },
1376+
// {
1377+
// loader: "sass-loader",
1378+
// options: {
1379+
// // Other options
1380+
// },
1381+
// },
1382+
// ],
1383+
// },
1384+
],
1385+
},
1386+
};
1387+
```
1388+
1389+
**src/index.js**
1390+
1391+
```js
1392+
// Example for Sass/SCSS:
1393+
// import sheet from "./styles.scss" assert { type: "css" };
1394+
1395+
// Example for CSS modules:
1396+
// import sheet, { myClass } from "./styles.scss" assert { type: "css" };
1397+
1398+
// Example for CSS:
1399+
import sheet from "./styles.css" assert { type: "css" };
1400+
1401+
document.adoptedStyleSheets = [sheet];
1402+
shadowRoot.adoptedStyleSheets = [sheet];
1403+
```
1404+
1405+
For migration purposes, you can use the following configuration:
1406+
1407+
```js
1408+
module.exports = {
1409+
module: {
1410+
rules: [
1411+
{
1412+
test: /\.css$/i,
1413+
oneOf: [
1414+
{
1415+
assert: { type: "css" },
1416+
loader: "css-loader",
1417+
options: {
1418+
exportType: "css-style-sheet",
1419+
// Other options
1420+
},
1421+
},
1422+
{
1423+
use: [
1424+
"style-loader",
1425+
{
1426+
loader: "css-loader",
1427+
options: {
1428+
// Other options
1429+
},
1430+
},
1431+
],
1432+
},
1433+
],
1434+
},
1435+
],
1436+
},
1437+
};
1438+
```
1439+
12721440
## Examples
12731441

12741442
### Recommend
@@ -1289,7 +1457,7 @@ module.exports = {
12891457
module: {
12901458
rules: [
12911459
{
1292-
test: /\.(sa|sc|c)ss$/,
1460+
test: /\.(sa|sc|c)ss$/i,
12931461
use: [
12941462
devMode ? "style-loader" : MiniCssExtractPlugin.loader,
12951463
"css-loader",
@@ -1512,8 +1680,8 @@ module.exports = {
15121680
// --------
15131681
// SCSS ALL EXCEPT MODULES
15141682
{
1515-
test: /\.scss$/,
1516-
exclude: /\.module\.scss$/,
1683+
test: /\.scss$/i,
1684+
exclude: /\.module\.scss$/i,
15171685
use: [
15181686
{
15191687
loader: "style-loader",
@@ -1535,7 +1703,7 @@ module.exports = {
15351703
// --------
15361704
// SCSS MODULES
15371705
{
1538-
test: /\.module\.scss$/,
1706+
test: /\.module\.scss$/i,
15391707
use: [
15401708
{
15411709
loader: "style-loader",

src/Warning.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
export default class Warning extends Error {
22
constructor(warning) {
33
super(warning);
4+
45
const { text, line, column } = warning;
6+
57
this.name = "Warning";
68

79
// Based on https://github.com/postcss/postcss/blob/master/lib/warning.es6#L74

src/index.js

+3-25
Original file line numberDiff line numberDiff line change
@@ -55,24 +55,13 @@ export default async function loader(content, map, meta) {
5555
const importPluginApi = [];
5656

5757
if (shouldUseImportPlugin(options)) {
58-
const resolver = this.getResolve({
59-
dependencyType: "css",
60-
conditionNames: ["style"],
61-
mainFields: ["css", "style", "main", "..."],
62-
mainFiles: ["index", "..."],
63-
extensions: [".css", "..."],
64-
preferRelative: true,
65-
});
66-
6758
plugins.push(
6859
importParser({
60+
isCSSStyleSheet: options.exportType === "css-style-sheet",
61+
loaderContext: this,
6962
imports: importPluginImports,
7063
api: importPluginApi,
71-
context: this.context,
72-
rootContext: this.rootContext,
73-
resourcePath: this.resourcePath,
7464
filter: options.import.filter,
75-
resolver,
7665
urlHandler: (url) =>
7766
stringifyRequest(
7867
this,
@@ -114,24 +103,13 @@ export default async function loader(content, map, meta) {
114103
const needToUseIcssPlugin = shouldUseIcssPlugin(options);
115104

116105
if (needToUseIcssPlugin) {
117-
const icssResolver = this.getResolve({
118-
dependencyType: "icss",
119-
conditionNames: ["style"],
120-
extensions: ["..."],
121-
mainFields: ["css", "style", "main", "..."],
122-
mainFiles: ["index", "..."],
123-
preferRelative: true,
124-
});
125-
126106
plugins.push(
127107
icssParser({
108+
loaderContext: this,
128109
imports: icssPluginImports,
129110
api: icssPluginApi,
130111
replacements,
131112
exports,
132-
context: this.context,
133-
rootContext: this.rootContext,
134-
resolver: icssResolver,
135113
urlHandler: (url) =>
136114
stringifyRequest(
137115
this,

src/options.json

+5
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@
193193
"description": "Use the ES modules syntax.",
194194
"link": "https://github.com/webpack-contrib/css-loader#esmodule",
195195
"type": "boolean"
196+
},
197+
"exportType": {
198+
"description": "Allows exporting styles as array with modules or constructable stylesheet (i.e. `CSSStyleSheet`).",
199+
"link": "https://github.com/webpack-contrib/css-loader#exporttype",
200+
"enum": ["array", "css-style-sheet"]
196201
}
197202
},
198203
"type": "object"

src/plugins/postcss-icss-parser.js

+16-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ const plugin = (options = {}) => {
1111
const imports = new Map();
1212
const tasks = [];
1313

14+
const { loaderContext } = options;
15+
const resolver = loaderContext.getResolve({
16+
dependencyType: "icss",
17+
conditionNames: ["style"],
18+
extensions: ["..."],
19+
mainFields: ["css", "style", "main", "..."],
20+
mainFiles: ["index", "..."],
21+
preferRelative: true,
22+
});
23+
1424
// eslint-disable-next-line guard-for-in
1525
for (const url in icssImports) {
1626
const tokens = icssImports[url];
@@ -32,13 +42,14 @@ const plugin = (options = {}) => {
3242

3343
const request = requestify(
3444
normalizeUrl(normalizedUrl, true),
35-
options.rootContext
45+
loaderContext.rootContext
3646
);
3747
const doResolve = async () => {
38-
const { resolver, context } = options;
39-
const resolvedUrl = await resolveRequests(resolver, context, [
40-
...new Set([normalizedUrl, request]),
41-
]);
48+
const resolvedUrl = await resolveRequests(
49+
resolver,
50+
loaderContext.context,
51+
[...new Set([normalizedUrl, request])]
52+
);
4253

4354
if (!resolvedUrl) {
4455
return;

0 commit comments

Comments
 (0)