From 7b32255c295f6a5b0cbdbd76b74fa272840d4c70 Mon Sep 17 00:00:00 2001
From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com>
Date: Mon, 6 Sep 2021 18:11:37 +0300
Subject: [PATCH] docs: example of multiple themes
---
README.md | 144 ++++++++++++++++++
package-lock.json | 85 +++++++++++
package.json | 2 +
.../expected/dark.css | 3 +
.../expected/main.css | 3 +
.../public/index.html | 12 ++
.../src/dark-theme/_vars.scss | 1 +
.../src/index.js | 50 ++++++
.../src/light-theme/_vars.scss | 1 +
.../src/style.scss | 3 +
.../webpack.config.js | 47 ++++++
.../expected/dark.css | 3 +
.../expected/light.css | 3 +
.../public/index.html | 11 ++
.../src/dark-theme/_vars.scss | 1 +
.../src/index.js | 58 +++++++
.../src/light-theme/_vars.scss | 1 +
.../src/style.scss | 3 +
.../webpack.config.js | 47 ++++++
19 files changed, 478 insertions(+)
create mode 100644 test/cases/multiple-themes-async-loading-with-default-light/expected/dark.css
create mode 100644 test/cases/multiple-themes-async-loading-with-default-light/expected/main.css
create mode 100644 test/cases/multiple-themes-async-loading-with-default-light/public/index.html
create mode 100644 test/cases/multiple-themes-async-loading-with-default-light/src/dark-theme/_vars.scss
create mode 100644 test/cases/multiple-themes-async-loading-with-default-light/src/index.js
create mode 100644 test/cases/multiple-themes-async-loading-with-default-light/src/light-theme/_vars.scss
create mode 100644 test/cases/multiple-themes-async-loading-with-default-light/src/style.scss
create mode 100644 test/cases/multiple-themes-async-loading-with-default-light/webpack.config.js
create mode 100644 test/cases/multiple-themes-async-loading/expected/dark.css
create mode 100644 test/cases/multiple-themes-async-loading/expected/light.css
create mode 100644 test/cases/multiple-themes-async-loading/public/index.html
create mode 100644 test/cases/multiple-themes-async-loading/src/dark-theme/_vars.scss
create mode 100644 test/cases/multiple-themes-async-loading/src/index.js
create mode 100644 test/cases/multiple-themes-async-loading/src/light-theme/_vars.scss
create mode 100644 test/cases/multiple-themes-async-loading/src/style.scss
create mode 100644 test/cases/multiple-themes-async-loading/webpack.config.js
diff --git a/README.md b/README.md
index 1c0905b0..bf483fab 100644
--- a/README.md
+++ b/README.md
@@ -911,6 +911,150 @@ module.exports = {
};
```
+### Multiple Themes
+
+**webpack.config.js**
+
+```js
+const MiniCssExtractPlugin = require("mini-css-extract-plugin");
+
+module.exports = {
+ entry: "./src/index.js",
+ module: {
+ rules: [
+ {
+ test: /\.s[ac]ss$/i,
+ oneOf: [
+ {
+ resourceQuery: "?dark",
+ use: [
+ Self.loader,
+ "css-loader",
+ {
+ loader: "sass-loader",
+ options: {
+ additionalData: `@use 'dark-theme/vars' as vars;`,
+ },
+ },
+ ],
+ },
+ {
+ use: [
+ Self.loader,
+ "css-loader",
+ {
+ loader: "sass-loader",
+ options: {
+ additionalData: `@use 'light-theme/vars' as vars;`,
+ },
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ plugins: [
+ new Self({
+ filename: "[name].css",
+ attributes: {
+ id: "theme",
+ },
+ }),
+ ],
+};
+```
+
+**src/index.js**
+
+```js
+import "./style.scss";
+
+let theme = "light";
+const themes = {};
+
+themes[theme] = document.querySelector("#theme");
+
+async function loadTheme(newTheme) {
+ // eslint-disable-next-line no-console
+ console.log(`CHANGE THEME - ${newTheme}`);
+
+ const themeElement = document.querySelector("#theme");
+
+ if (themeElement) {
+ themeElement.remove();
+ }
+
+ if (themes[newTheme]) {
+ // eslint-disable-next-line no-console
+ console.log(`THEME ALREADY LOADED - ${newTheme}`);
+
+ document.head.appendChild(themes[newTheme]);
+
+ return;
+ }
+
+ if (newTheme === "dark") {
+ // eslint-disable-next-line no-console
+ console.log(`LOADING THEME - ${newTheme}`);
+
+ import(/* webpackChunkName: "dark" */ "./style.scss?dark").then(() => {
+ themes[newTheme] = document.querySelector("#theme");
+
+ // eslint-disable-next-line no-console
+ console.log(`LOADED - ${newTheme}`);
+ });
+ }
+}
+
+document.onclick = () => {
+ if (theme === "light") {
+ theme = "dark";
+ } else {
+ theme = "light";
+ }
+
+ loadTheme(theme);
+};
+```
+
+**src/dark-theme/\_vars.scss**
+
+```scss
+$background: black;
+```
+
+**src/light-theme/\_vars.scss**
+
+```scss
+$background: white;
+```
+
+**src/styles.scss**
+
+```scss
+body {
+ background-color: vars.$background;
+}
+```
+
+**public/index.html**
+
+```html
+
+
+
+
+
+ Document
+
+
+
+
+
+
+```
+
### Media Query Plugin
If you'd like to extract the media queries from the extracted CSS (so mobile users don't need to load desktop or tablet specific CSS anymore) you should use one of the following plugins:
diff --git a/package-lock.json b/package-lock.json
index 25ab70db..6a8cb0cf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -36,6 +36,8 @@
"memfs": "^3.0.2",
"npm-run-all": "^4.1.5",
"prettier": "^2.3.2",
+ "sass": "^1.39.0",
+ "sass-loader": "^12.1.0",
"standard-version": "^9.3.0",
"webpack": "^5.48.0",
"webpack-cli": "^4.7.2",
@@ -11633,6 +11635,15 @@
"node": ">=6"
}
},
+ "node_modules/klona": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz",
+ "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
"node_modules/leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@@ -14776,6 +14787,55 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
+ "node_modules/sass": {
+ "version": "1.39.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.39.0.tgz",
+ "integrity": "sha512-F4o+RhJkNOIG0b6QudYU8c78ZADKZjKDk5cyrf8XTKWfrgbtyVVXImFstJrc+1pkQDCggyidIOytq6gS4gCCZg==",
+ "dev": true,
+ "dependencies": {
+ "chokidar": ">=3.0.0 <4.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=8.9.0"
+ }
+ },
+ "node_modules/sass-loader": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.1.0.tgz",
+ "integrity": "sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg==",
+ "dev": true,
+ "dependencies": {
+ "klona": "^2.0.4",
+ "neo-async": "^2.6.2"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "fibers": ">= 3.1.0",
+ "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0",
+ "sass": "^1.3.0",
+ "webpack": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "fibers": {
+ "optional": true
+ },
+ "node-sass": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
+ }
+ },
"node_modules/saxes": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
@@ -26188,6 +26248,12 @@
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
"dev": true
},
+ "klona": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz",
+ "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==",
+ "dev": true
+ },
"leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@@ -28557,6 +28623,25 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
+ "sass": {
+ "version": "1.39.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.39.0.tgz",
+ "integrity": "sha512-F4o+RhJkNOIG0b6QudYU8c78ZADKZjKDk5cyrf8XTKWfrgbtyVVXImFstJrc+1pkQDCggyidIOytq6gS4gCCZg==",
+ "dev": true,
+ "requires": {
+ "chokidar": ">=3.0.0 <4.0.0"
+ }
+ },
+ "sass-loader": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.1.0.tgz",
+ "integrity": "sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg==",
+ "dev": true,
+ "requires": {
+ "klona": "^2.0.4",
+ "neo-async": "^2.6.2"
+ }
+ },
"saxes": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
diff --git a/package.json b/package.json
index 947fc76a..a6715cb9 100644
--- a/package.json
+++ b/package.json
@@ -71,6 +71,8 @@
"memfs": "^3.0.2",
"npm-run-all": "^4.1.5",
"prettier": "^2.3.2",
+ "sass": "^1.39.0",
+ "sass-loader": "^12.1.0",
"standard-version": "^9.3.0",
"webpack": "^5.48.0",
"webpack-cli": "^4.7.2",
diff --git a/test/cases/multiple-themes-async-loading-with-default-light/expected/dark.css b/test/cases/multiple-themes-async-loading-with-default-light/expected/dark.css
new file mode 100644
index 00000000..c4d554e0
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading-with-default-light/expected/dark.css
@@ -0,0 +1,3 @@
+body {
+ background-color: black;
+}
diff --git a/test/cases/multiple-themes-async-loading-with-default-light/expected/main.css b/test/cases/multiple-themes-async-loading-with-default-light/expected/main.css
new file mode 100644
index 00000000..cdf802a3
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading-with-default-light/expected/main.css
@@ -0,0 +1,3 @@
+body {
+ background-color: white;
+}
diff --git a/test/cases/multiple-themes-async-loading-with-default-light/public/index.html b/test/cases/multiple-themes-async-loading-with-default-light/public/index.html
new file mode 100644
index 00000000..061216f2
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading-with-default-light/public/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/cases/multiple-themes-async-loading-with-default-light/src/dark-theme/_vars.scss b/test/cases/multiple-themes-async-loading-with-default-light/src/dark-theme/_vars.scss
new file mode 100644
index 00000000..2abe50c6
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading-with-default-light/src/dark-theme/_vars.scss
@@ -0,0 +1 @@
+$background: black;
diff --git a/test/cases/multiple-themes-async-loading-with-default-light/src/index.js b/test/cases/multiple-themes-async-loading-with-default-light/src/index.js
new file mode 100644
index 00000000..cce9cc7c
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading-with-default-light/src/index.js
@@ -0,0 +1,50 @@
+/* eslint-env browser */
+import "./style.scss";
+
+let theme = "light";
+const themes = {};
+
+themes[theme] = document.querySelector("#theme");
+
+async function loadTheme(newTheme) {
+ // eslint-disable-next-line no-console
+ console.log(`CHANGE THEME - ${newTheme}`);
+
+ const themeElement = document.querySelector("#theme");
+
+ if (themeElement) {
+ themeElement.remove();
+ }
+
+ if (themes[newTheme]) {
+ // eslint-disable-next-line no-console
+ console.log(`THEME ALREADY LOADED - ${newTheme}`);
+
+ document.head.appendChild(themes[newTheme]);
+
+ return;
+ }
+
+ if (newTheme === "dark") {
+ // eslint-disable-next-line no-console
+ console.log(`LOADING THEME - ${newTheme}`);
+
+ // eslint-disable-next-line import/no-unresolved
+ import(/* webpackChunkName: "dark" */ "./style.scss?dark").then(() => {
+ themes[newTheme] = document.querySelector("#theme");
+
+ // eslint-disable-next-line no-console
+ console.log(`LOADED - ${newTheme}`);
+ });
+ }
+}
+
+document.onclick = () => {
+ if (theme === "light") {
+ theme = "dark";
+ } else {
+ theme = "light";
+ }
+
+ loadTheme(theme);
+};
diff --git a/test/cases/multiple-themes-async-loading-with-default-light/src/light-theme/_vars.scss b/test/cases/multiple-themes-async-loading-with-default-light/src/light-theme/_vars.scss
new file mode 100644
index 00000000..6a1fb84b
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading-with-default-light/src/light-theme/_vars.scss
@@ -0,0 +1 @@
+$background: white;
diff --git a/test/cases/multiple-themes-async-loading-with-default-light/src/style.scss b/test/cases/multiple-themes-async-loading-with-default-light/src/style.scss
new file mode 100644
index 00000000..fb281175
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading-with-default-light/src/style.scss
@@ -0,0 +1,3 @@
+body {
+ background-color: vars.$background;
+}
diff --git a/test/cases/multiple-themes-async-loading-with-default-light/webpack.config.js b/test/cases/multiple-themes-async-loading-with-default-light/webpack.config.js
new file mode 100644
index 00000000..58c979cd
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading-with-default-light/webpack.config.js
@@ -0,0 +1,47 @@
+import Self from "../../../src";
+
+module.exports = {
+ entry: "./src/index.js",
+ module: {
+ rules: [
+ {
+ test: /\.s[ac]ss$/i,
+ oneOf: [
+ {
+ resourceQuery: "?dark",
+ use: [
+ Self.loader,
+ "css-loader",
+ {
+ loader: "sass-loader",
+ options: {
+ additionalData: `@use 'dark-theme/vars' as vars;`,
+ },
+ },
+ ],
+ },
+ {
+ use: [
+ Self.loader,
+ "css-loader",
+ {
+ loader: "sass-loader",
+ options: {
+ additionalData: `@use 'light-theme/vars' as vars;`,
+ },
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ plugins: [
+ new Self({
+ filename: "[name].css",
+ attributes: {
+ id: "theme",
+ },
+ }),
+ ],
+};
diff --git a/test/cases/multiple-themes-async-loading/expected/dark.css b/test/cases/multiple-themes-async-loading/expected/dark.css
new file mode 100644
index 00000000..c4d554e0
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading/expected/dark.css
@@ -0,0 +1,3 @@
+body {
+ background-color: black;
+}
diff --git a/test/cases/multiple-themes-async-loading/expected/light.css b/test/cases/multiple-themes-async-loading/expected/light.css
new file mode 100644
index 00000000..cdf802a3
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading/expected/light.css
@@ -0,0 +1,3 @@
+body {
+ background-color: white;
+}
diff --git a/test/cases/multiple-themes-async-loading/public/index.html b/test/cases/multiple-themes-async-loading/public/index.html
new file mode 100644
index 00000000..c51cce96
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading/public/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+ Document
+
+
+
+
+
\ No newline at end of file
diff --git a/test/cases/multiple-themes-async-loading/src/dark-theme/_vars.scss b/test/cases/multiple-themes-async-loading/src/dark-theme/_vars.scss
new file mode 100644
index 00000000..2abe50c6
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading/src/dark-theme/_vars.scss
@@ -0,0 +1 @@
+$background: black;
diff --git a/test/cases/multiple-themes-async-loading/src/index.js b/test/cases/multiple-themes-async-loading/src/index.js
new file mode 100644
index 00000000..8c016077
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading/src/index.js
@@ -0,0 +1,58 @@
+/* eslint-env browser */
+
+let theme = "light";
+
+const themes = {};
+
+async function loadTheme(newTheme) {
+ // eslint-disable-next-line no-console
+ console.log(`CHANGE THEME - ${newTheme}`);
+
+ const themeElement = document.querySelector("#theme");
+
+ if (themeElement) {
+ themeElement.remove();
+ }
+
+ if (themes[newTheme]) {
+ // eslint-disable-next-line no-console
+ // eslint-disable-next-line no-console
+ console.log(`THEME ALREADY LOADED - ${newTheme}`);
+
+ document.head.appendChild(themes[newTheme]);
+
+ return;
+ }
+
+ // eslint-disable-next-line no-console
+ console.log(`LOADING THEME - ${newTheme}`);
+
+ if (newTheme === "light") {
+ import(/* webpackChunkName: "light" */ "./style.scss").then(() => {
+ themes[newTheme] = document.querySelector("#theme");
+
+ // eslint-disable-next-line no-console
+ console.log(`LOADED - ${newTheme}`);
+ });
+ } else {
+ // eslint-disable-next-line import/no-unresolved
+ import(/* webpackChunkName: "dark" */ "./style.scss?dark").then(() => {
+ themes[newTheme] = document.querySelector("#theme");
+
+ // eslint-disable-next-line no-console
+ console.log(`LOADED - ${newTheme}`);
+ });
+ }
+}
+
+document.onclick = () => {
+ if (theme === "light") {
+ theme = "dark";
+ } else {
+ theme = "light";
+ }
+
+ loadTheme(theme);
+};
+
+loadTheme(theme);
diff --git a/test/cases/multiple-themes-async-loading/src/light-theme/_vars.scss b/test/cases/multiple-themes-async-loading/src/light-theme/_vars.scss
new file mode 100644
index 00000000..6a1fb84b
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading/src/light-theme/_vars.scss
@@ -0,0 +1 @@
+$background: white;
diff --git a/test/cases/multiple-themes-async-loading/src/style.scss b/test/cases/multiple-themes-async-loading/src/style.scss
new file mode 100644
index 00000000..fb281175
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading/src/style.scss
@@ -0,0 +1,3 @@
+body {
+ background-color: vars.$background;
+}
diff --git a/test/cases/multiple-themes-async-loading/webpack.config.js b/test/cases/multiple-themes-async-loading/webpack.config.js
new file mode 100644
index 00000000..58c979cd
--- /dev/null
+++ b/test/cases/multiple-themes-async-loading/webpack.config.js
@@ -0,0 +1,47 @@
+import Self from "../../../src";
+
+module.exports = {
+ entry: "./src/index.js",
+ module: {
+ rules: [
+ {
+ test: /\.s[ac]ss$/i,
+ oneOf: [
+ {
+ resourceQuery: "?dark",
+ use: [
+ Self.loader,
+ "css-loader",
+ {
+ loader: "sass-loader",
+ options: {
+ additionalData: `@use 'dark-theme/vars' as vars;`,
+ },
+ },
+ ],
+ },
+ {
+ use: [
+ Self.loader,
+ "css-loader",
+ {
+ loader: "sass-loader",
+ options: {
+ additionalData: `@use 'light-theme/vars' as vars;`,
+ },
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ plugins: [
+ new Self({
+ filename: "[name].css",
+ attributes: {
+ id: "theme",
+ },
+ }),
+ ],
+};