2016-05-15 16 views
9

Desidero essere in grado di raggruppare la mia app React con Webpack in modo tale che copie distribuite immesse in un CDN possano essere originate, richiamate e inizializzate con un gruppo di configurazioni rilevanti per un cliente.Scrittura plugin embeddable per Javascript con React & Webpack

Dopo aver letto this e this, Sto installando il mio file di entrata webpack come segue:

// ... React requires etc. 

(() => { 
    this.MyApp = (config) => { 
    // some constructor code here 
    } 

    MyApp.prototype.init =() => { 
    ReactDOM.render(<MyReactApp config={MyApp.config} />, someSelector); 
    } 
})(); 

L'idea è che nel mio cliente, posso fare qualcosa di simile al seguente:

<script src="./bundle.js" type="text/javascript"></script> 
<script type="text/javascript"> 
    MyApp.init({ 
    some: "config" 
    }); 
</script> 

E la mia funzione MyApp#init renderà la mia app React all'interno di un contenitore sul client.

Sto pensando a questo nel modo giusto? C'è un modo più semplice o più efficace per fare questo?

Il mio errore è Uncaught TypeError: Cannot set property 'MyApp' of undefined, poiché this all'interno dell'IFE è undefined. Mi piacerebbe davvero capire sia il motivo per cui ciò sta accadendo sia i consigli su come risolverlo.

Grazie in anticipo!

risposta

14

Così ho sorta di trovato una soluzione a questo, come descritto here

Se cambio il mio file webpack.config.js per aggiungere i seguenti attributi all'oggetto output, cioè

var config = { 
    // ... 
    output: { 
    // ... 
    library: 'MyApp', 
    libraryTarget: 'umd', 
    umdNamedDefine: true, 
    } 
} 

Specifica il file 'm bundling con webpack come un modulo UMD, quindi se ho una funzione in quel file ed esportarlo ...

export const init = (config) => { 
    ReactDOM.render(<MyReactApp config={config} />, someSelector); 
} 

Posso quindi, nel mio cliente, fare quanto segue.

<script src="./bundle.js" type="text/javascript"></script> 
<script type="text/javascript"> 
    MyApp.init({ 
    some: "config" 
    }); 
</script> 

E il rendering dell'app React.

Se qualcuno pensa che questo sia un modo stupido per farlo, mi piacerebbe sentirlo!

+0

Ciao, mattsch. Questa è una bella soluzione. L'unica domanda che ho è come potrei controllare che il widget sia integrato sul sito web del cliente.Quindi diciamo di avere un'app e costruire un widget. Farei il check-in dell'app che un utente (tramite ID o nome host) ha incorporato un widget sul proprio sito. –

+0

@ To_wave Suppongo che come parte di una funzione 'init' è possibile eseguire il ping di una richiesta sul server con i dettagli del client - che potrebbe funzionare? – mattsch

+0

Ci ho pensato, ma quella soluzione non mi permette di controllare se il client ha cancellato un widget dal loro sito web. Quindi, con la funzione callback, l'unico controllo possibile è il widget integrato, ma non rimosso. –

0

Hai recinto intorno alla tua classe.

MyApp deve essere esportato o collegato all'oggetto della finestra globale prima di poterlo chiamare in questo modo.

Nella tua situazione, in realtà non stai chiamando MyApp.init() ma stai chiamando window.MyApp.init(), ma la finestra dell'oggetto globale non ha un oggetto MyApp collegato ad esso.

// ... Simple attaching MyApp to the window (as a function) 
window.MyApp = (config) => { 
    ... 
} 

// ... Using class and export 
class MyApp { 
    constructor(config){...} 
} 
export default MyApp 

// or simply attach to the window 
window.MyApp = MyApp 

Preferirei creare classe ed esportare modulo utilizzando l'esportazione. Quindi crea un altro file solo per il collegamento alla finestra. Dal momento che non è considerata una buona pratica associare le classi alla finestra in questo modo.

// Import module and attach it to the window 
import MyApp from '.my-app' 
window.MyApp = MyApp 

È possibile cercare le opzioni avanzate di moduli esportatori come UMD, AMD ...

Problemi correlati