Webpack + postcss + 主题 + 热重载 [英] Webpack + postcss + themes + hot reloading

查看:34
本文介绍了Webpack + postcss + 主题 + 热重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望允许用户在我的网站上选择主题,他们将通过下拉菜单来完成.我目前无法弄清楚如何支持此功能,而无需编写愚蠢的代码.

我目前使用 css-modules 和 postcss 来让我的生活更轻松.Webpack 用于将所有内容捆绑在一起.我在开发过程中使用热重载,在此期间我使用样式加载器.

完整配置如下

<代码>{测试:/\.css$/,加载器:!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 {边距:10px;宽度:100px;}:global(.theme1) {.myComponent {背景:$theme1_myComponent_background;}}:global(.theme2) {.myComponent {背景:$theme2_myComponent_background;}}

这很快就会变成难以扩展和不可维护的东西,这就是我想避免它的原因.

解决方案 2

为 css 生成预先主题的静态包.当用户请求 /main.css 时,服务器上的处理程序确定要发送的主题(可能是查询字符串)并将它们发送theme1-main.csstheme2-main.css 或类似的东西.问题是我不知道如何支持开发环境.

这样做的好处是我的 css 文件不需要任何额外且难以维护的逻辑:

.myComponent {边距:10px;宽度:100px;背景:$myComponent_background;}

解决方案 3

使用原生 css 变量.这些可以在运行时更新,这将反映已经加载的 css 并在生产和开发环境中正常工作.我的组件看起来也像(或类似于)解决方案 2.这里的问题是它们在本地没有得到广泛支持,我不确定是否有任何值得研究的 polyfills 可以为我做这种类型的事情.

<小时>

总而言之,这些都是我的想法.我还没有得出任何明确的结论,并感谢所有关于我如何解决这个问题的反馈.也许我想的都错了,有更好的方法来做我想做的事.

提前致谢!

解决方案

一种可能的方法如下

  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 = "样式表";style.href=`data:text/css,${css1}`;//style.href=`data:text/css,${css2}`;style.id = "主题";document.querySelector("head").appendChild(style);

  1. 然后您可以在需要时更改主题

只需在href中添加另一种样式:

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

或者让我们通过 React 做同样的事情:

import React, { Component } from 'react';从'./logo.svg'导入标志;类 App 扩展组件 {构造函数(道具){超级(道具);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 = {主题索引:0,}}使成为() {返回 (<div ><风格>{this.cssThemes[this.state.themeInd]}</风格><div className="App-header"><img src={logo} className="App-logo" alt="logo"/><h2>欢迎反应</h2>

<p>首先,编辑 src/App.js;并保存以重新加载.</p><按钮onClick={() =>this.setState({themeInd: this.state.themeInd+1})}>改变主题

);}}导出默认应用程序;

如果你在 webpack.config 中设置 raw-loader 来处理 css 文件,它就会工作

<代码>{测试:/\.css$/,装载机:'原始'},

I want to allow users to select themes on my website, which they will do through a dropdown this. I am currently having trouble figuring out how to support this feature though, without writing dumb code.

I currently use css-modules along with postcss to make my life easier. Webpack is used to bundle everything together. I utilize hot reloading during development, during which I use the style-loader instead.

The full configuration looks like this

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

Solution 1

Place a classname on the body tag to determine what theme is loaded. This is then used to select the correct theme from inside each components css. This is quite tedious and something I'd like to avoid, but it would look something like this:

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

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

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

This is quickly going to turn into something hard to extend and unmaintainable which is why I would like to avoid it.

Solution 2

Generate pre-themed static bundles for the css. When the user requests /main.css, a handler on the server determines which theme to send (perhaps query string) and sends them theme1-main.css or theme2-main.css or something along those lines. The problem there is I don't know how to support the dev environment.

The good thing about this is that my css files don't need any extra and hard to maintain logic:

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

Solution 3

Use native css variables. These can then be updated during runtime which would reflect the already loaded css and work gracefully across both production and development environments. My components would also look like (or similar to) solution 2. The problem here is that they are not very widely supported natively, and I'm unsure if there are any polyfills worth looking into that will do this type of thing for me.


All in all, these are my thoughts. I have not arrived at any definitive conclusion yet and would appreciate all feedback on how I can solve this problem. Perhaps I'm thinking about it all wrong and there is a much better way of doing what I want done.

Thanks in advance!

解决方案

One possible approach could be as follow

  1. Not to use style-loader because it inserts css automatically, but do it manually when we need and what we need.

for example:

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

(we need raw-loader here)

  1. then we just insert required style to document.

for example:

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. then you can change your theme when you need

just put another style to href:

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

or let's do same via 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;

it'll work if you set the raw-loader to handle css file in webpack.config

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

这篇关于Webpack + postcss + 主题 + 热重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆