2016-01-26 13 views
5

Ich mag würde die folgende Struktur erreichen:Webpack Thema loader

  • button.core.jsx
  • button.theme-a.jsx
  • button.theme-b.jsx

zu nehmen, um als Beispiel Reaktion, Ich mag würde tun das folgende in button.core.jsx:

import React from 'react'; 
import Themed from './button.[theme]'; 

export default class Button extends React.Component { 
    render() { 
     if (Themed) { 
      return <Themed />; 
     } 
     return <button>default button</button>; 
    } 
} 

Mit anderen Worten, ich möchte ein Thema in meinem webpack.config.js definieren und diese Datei laden, wenn es existiert. Wenn dies nicht der Fall ist, rendern Sie das Standardverhalten. Ich denke, das wäre ein sehr leistungsfähiges Setup!

Ich habe nach einem benutzerdefinierten Loader gesucht, aber noch keinen Erfolg. Kann mir jemand in die richtige Richtung zeigen?

Antwort

4

Ich habe diese Arbeit bekomme mit einem benutzerdefinierten „Resolver“ Schreiben:

const ThemeResolver = { 
    apply: function(resolver) { 
     resolver.plugin('file', function(req, cb) { 
      if (req.request.indexOf('[theme]') == -1) { 
       return cb(); 
      } 

      const defaultFile = req.request.replace('[theme]', 'Default'); 
      const themedFile = req.request.replace('[theme]', process.env.THEME); 
      req.request = themedFile; 

      this.doResolve(['file'], req, (err) => { 
       if (!err) { 
        return cb(); 
       } 
       req.request = defaultFile; 
       this.doResolve(['file'], req, cb); 
      }) 
     }); 
    } 
}; 

module.exports = { 
    // ... 
    plugins: [ 
     new webpack.ResolverPlugin([ThemeResolver]), 
    ] 
    // ... 
}; 

Es wird versucht, eine Datei mit [theme] auf seinem Weg zu einem Pfad mit dem Thema zu lösen als Umgebungsvariable definiert. Wenn dies fehlschlägt, wird stattdessen auf eine Standarddatei zurückgegriffen. Auf diese Weise kann ich eine thematische Datei benötigen etwa so:

import Presentation from './button-[theme]'

Die Hauptkomponente ein bisschen anders als in meiner Frage entpuppte, aber ich bin eigentlich ziemlich zufrieden damit:

import React from 'react'; 
import Presentation from './button-[theme]'; 

export default class Button extends React.Component { 
    onClick = (e) => console.log('some logic'); 

    render() { 
     return <Presentation onClick={ this.onClick } />; 
    } 
} 

die Logik dieser Taste-Komponente kann innerhalb von button.core.jsx, während die Präsentation durch eine dieser Komponenten behandelt werden leben:

THEME=theme-a npm start // button-[theme] resolves to button-theme-a.jsx 
THEME=theme-c npm start // button-[theme] resolves to button-default.jsx 

Disclaimer: Ich habe dies noch nicht in einer großen Produktionsumgebung verwendet, aber es scheint in einem kleinen POC zu funktionieren. Bitte lassen Sie mich wissen, wenn ich etwas Unkluges mache!

+0

Ich lief ein Problem damit. Andere Plugins scheinen es nicht zu sehen. Also, in meinem Fall, mit 'html-webpack-plugin' für das Favicon, löst es niemals das Theme-Tag auf. – Ben

+0

Das wäre eigentlich sinnvoll, weil Sie zu diesem Zeitpunkt nichts benötigen/importieren. Sie machen nur eine Referenz und Ihr Browser lädt das Favicon. Kannst du nicht etwas Logik in deiner Vorlage hinzufügen? – Jpunt

+0

Das ist wahrscheinlich, was ich tun werde. Modifizieren Sie den Code "Ist meine Datei vorhanden" oben, damit ich ihn außerhalb des Resolvers verwenden kann. – Ben

Verwandte Themen