2016-01-26 22 views
5

mi piacerebbe realizzare la seguente struttura:Webpack tema caricatore

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

Prendere Reagire come un esempio, mi piacerebbe fare il seguente 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>; 
    } 
} 

In altre parole, voglio definire un tema nel mio webpack.config.js e caricare quel file se esiste. In caso contrario, visualizza il comportamento predefinito. Penso che questo sarebbe un setup molto potente!

Ho cercato un caricatore personalizzato, ma non ho ancora avuto successo. Qualcuno può indicarmi la giusta direzione?

risposta

4

Ho questo lavoro con la scrittura di un "risolutore" su misura:

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

Si tenta di risolvere un file con [theme] nel suo percorso in un percorso con il tema definito come una variabile di ambiente. Se fallisce, ricadrà invece su un file predefinito. In questo modo posso richiedere un file a tema in questo modo:

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

Il componente principale si è rivelato essere un po 'diverso nella mia interrogazione, ma sono in realtà piuttosto contenuti con esso:

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

la logica di questo pulsante-componente può vivere all'interno di button.core.jsx, mentre la presentazione sarà gestito da uno di questi componenti:

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: Non l'ho ancora usato su larga scala o in un ambiente di produzione, ma sembra funzionare in un piccolo POC. Per favore fatemi sapere se sto facendo qualcosa di poco saggio!

+0

Mi sono imbattuto in un problema con questo. Altri plugin non sembrano vederlo. Quindi, nel mio caso, usando 'html-webpack-plugin' per la favicon, non risolve mai il tag del tema. – Ben

+0

Questo in realtà avrebbe senso, perché non stai richiedendo/importando nulla in quel punto. Stai solo facendo un riferimento e il tuo browser caricherà la favicon. Non puoi aggiungere qualche logica all'interno del tuo template? – Jpunt

+0

Questo è probabilmente quello che farò. Modularizzare il codice "il mio file di marca esiste" qui sopra in modo che io possa usarlo al di fuori del resolver. – Ben

Problemi correlati