css - unknown - webpack sass




Webpack+postcss+темы+горячая перезагрузка (2)

Я хочу разрешить пользователям выбирать темы на моем веб-сайте, которые они будут делать через раскрывающееся меню. В настоящее время у меня возникают проблемы с выяснением того, как поддерживать эту функцию, но без написания немого кода.

В настоящее время я использую css-модули вместе с postcss, чтобы облегчить мою жизнь. Webpack используется для объединения всего вместе. Я использую горячую перезагрузку во время разработки, в то время как вместо этого я использую загрузчик стиля.

Полная конфигурация выглядит так:

{
  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'
},

Решение 1

Поместите имя класса в тег body, чтобы определить, какая тема загружена. Затем он используется для выбора правильной темы изнутри каждого компонента css. Это довольно утомительно и что-то, чего я бы хотел избежать, но это выглядело бы примерно так:

.myComponent {
  margin: 10px;
  width: 100px;
}

:global(.theme1) {
  .myComponent {
    background: $theme1_myComponent_background;
  }
}

:global(.theme2) {
  .myComponent {
    background: $theme2_myComponent_background;
  }
}

Это быстро превратится во что-то трудное для расширения и недостижимости, поэтому я бы хотел его избежать.

Решение 2

Создайте предварительно заданные статические расслоения для css. Когда пользователь запрашивает /main.css , обработчик на сервере определяет, какую тему отправить (возможно, строку запроса), и отправляет им theme1-main.css или theme2-main.css или что-то в этом направлении. Проблема в том, что я не знаю, как поддерживать среду dev.

Хорошая вещь об этом заключается в том, что мои файлы css не нуждаются в дополнительной и сложной для поддержания логики:

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

Решение 3

Используйте собственные переменные css. Затем они могут быть обновлены во время выполнения, что будет отражать уже загруженный css и изящно работать как в производственных средах, так и в среде разработки. Мои компоненты также будут выглядеть (или похожими на) решение 2. Проблема здесь в том, что они не очень широко поддерживаются изначально, и я не уверен, есть ли какие-либо полины, которые стоит посмотреть, которые будут делать для меня такие вещи.

В общем, это мои мысли. Я еще не пришел к какому-либо окончательному заключению и буду благодарен всем отзывам о том, как я могу решить эту проблему. Возможно, я думаю об этом неправильно, и есть намного лучший способ сделать то, что я хочу сделать.

Заранее спасибо!


Вот решение, использующее SASS. Это в основном ваше решение 1, но проще писать и поддерживать. Это означает, что вы не используете SASS, но поскольку это лучшее решение для моего личного использования, я подумал, что стоит поделиться ...

Вот код SCSS ( CodePen здесь ):

// 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);
  }
}

Для этого требуется:

@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:

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

Это в значительной степени вдохновлено:


Один из возможных подходов может быть следующим:

  1. Не использовать style-loader потому что он автоматически вставляет css, но делайте это вручную, когда нам нужно и что нам нужно.

например:

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

(здесь нужен raw-loader )

  1. то мы просто вставляем требуемый стиль в документ.

например:

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. то вы можете изменить свою тему, когда вам нужно

просто добавьте другой стиль в href :

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

или давайте делать то же самое через 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;

он будет работать, если вы установите raw-loader для обработки файла css в webpack.config

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




postcss