node_modules found dist bootstrap css reactjs themes webpack postcss

found - Webpack+postcss+temas+recarga en caliente



webpack 4 postcss (2)

Quiero permitir que los usuarios seleccionen temas en mi sitio web, lo que harán a través de un menú desplegable. Actualmente estoy teniendo problemas para averiguar cómo admitir esta función, sin escribir código tonto.

Actualmente uso css-modules junto con postcss para hacer mi vida más fácil. Webpack se usa para agrupar todo. Utilizo la recarga en caliente durante el desarrollo, durante el cual utilizo el cargador de estilo.

La configuración completa se ve así

{ test: //.css$/, loader: !isDev ? ExtractTextPlugin.extract(''style-loader'', ''css-loader?sourcemap&minimize&modules&importLoaders=1&localIdentName=[name]-[local]-[hash:base64:5]!postcss-loader'') : ''style-loader!css-loader?sourcemap&minimize&modules&importLoaders=1&localIdentName=[name]-[local]-[hash:base64:5]!postcss-loader'' },

Solución 1

Coloque un nombre de clase en la etiqueta del cuerpo para determinar qué tema se carga. Esto se usa para seleccionar el tema correcto desde el interior de cada componente css. Esto es bastante tedioso y algo que me gustaría evitar, pero se vería así:

.myComponent { margin: 10px; width: 100px; } :global(.theme1) { .myComponent { background: $theme1_myComponent_background; } } :global(.theme2) { .myComponent { background: $theme2_myComponent_background; } }

Esto rápidamente se convertirá en algo difícil de extender e inmanejable, y es por eso que me gustaría evitarlo.

Solución 2

Genera paquetes estáticos pre-temáticos para el css. Cuando el usuario solicita /main.css , un controlador en el servidor determina qué tema enviar (tal vez cadena de consulta) y les envía theme1-main.css o theme2-main.css o algo theme2-main.css . El problema es que no sé cómo soportar el entorno de desarrollo.

Lo bueno de esto es que mis archivos CSS no necesitan ninguna lógica adicional y difícil de mantener:

.myComponent { margin: 10px; width: 100px; background: $myComponent_background; }

Solución 3

Utiliza variables css nativas. Estos pueden actualizarse durante el tiempo de ejecución, lo que reflejaría el css ya cargado y funcionaría correctamente tanto en entornos de producción como de desarrollo. Mis componentes también se verían como (o similares a) la solución 2. El problema aquí es que no cuentan con un amplio respaldo nativo, y no estoy seguro de si hay algún tipo de relleno que valga la pena investigar y que haga este tipo de cosas por mí.

En general, estos son mis pensamientos. Todavía no he llegado a una conclusión definitiva y agradecería cualquier comentario sobre cómo puedo resolver este problema. Tal vez estoy pensando en todo mal y hay una manera mucho mejor de hacer lo que quiero hacer.

¡Gracias por adelantado!


Aquí hay una solución usando SASS. Básicamente es su solución 1, pero más fácil de escribir y mantener. Parece que no estás usando SASS, pero como es la mejor solución que pude encontrar para mi uso personal, pensé que valía la pena compartir ...

Aquí está el código SCSS ( CodePen aquí ):

// Define theme variables $themes: ( default: ( // default theme bg-color: white, text-color: black, ), dark: ( bg-color: black, text-color: white, ), colorful: ( bg-color: green, text-color: orange, ) ); // This is how you use your themes .example{ padding: 10px; @include themify { background: theme-get(bg-color); color: theme-get(text-color); } }

Requiere que esto funcione:

@mixin themify() { // Iterate over the themes @each $theme-name, $theme in $themes { $current-theme: $theme !global; @if $theme-name == ''default'' { @content; } @else { .theme-#{$theme-name} & { @content; } } } } @function theme-get($key, $theme: $current-theme) { $ret: map-get($theme, $key); @if not $ret { @error ''Your theme doesn/'t have a value for `#{$key}`.''; } @return $ret; }

CSS resultante:

.example { padding: 10px; background: white; color: black; } .theme-dark .example { background: black; color: white; } .theme-colorful .example { background: green; color: orange; }

Esto está fuertemente inspirado en:


Un posible enfoque podría ser el siguiente

  1. No utilizar style-loader porque inserta css automáticamente, pero hacerlo manualmente cuando lo necesitamos y lo que necesitamos.

por ejemplo:

const css1 = require("raw!./App1.css"); const css2 = require("raw!./App2.css");

(Necesitamos raw-loader aquí)

  1. luego solo insertamos el estilo requerido para documentar.

por ejemplo:

const style = document.createElement("link"); style.type = "stylesheet/text-css"; style.rel = "stylesheet"; style.href=`data:text/css,${css1}`; // style.href=`data:text/css,${css2}`; style.id = "theming"; document.querySelector("head").appendChild(style);

  1. entonces puedes cambiar tu tema cuando lo necesites

simplemente pon otro estilo a href :

style.href=`data:text/css,${css2}`

o hagámoslo a través de React:

import React, { Component } from ''react''; import logo from ''./logo.svg''; class App extends Component { constructor(props) { super(props); this.cssThemes = []; this.cssThemes.push(require("./App.css")); this.cssThemes.push(require("./App1.css")); this.cssThemes.push(require("./App2.css")); this.cssThemes.push(require("./App3.css")); this.state = { themeInd: 0, } } render() { return ( <div > <style> {this.cssThemes[this.state.themeInd]} </style> <div className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h2>Welcome to React</h2> </div> <p > To get started, edit <code>src/App.js</code> and save to reload. </p> <button onClick={() => this.setState({themeInd: this.state.themeInd+1})} > Change theme </button> </div> ); } } export default App;

Funcionará si configura el raw-loader para manejar el archivo css en webpack.config

{ test: //.css$/, loader: ''raw'' },