2016-05-15 17 views
9

Chcę móc połączyć moją aplikację React z Webpack tak, aby rozproszone kopie umieszczone na CDN mogły być pozyskiwane, wywoływane i inicjowane za pomocą zestawu konfiguracji istotnych dla klienta.Pisanie wbudowanej wtyczki Javascript z React & Webpack

Po przeczytaniu this i this, jestem skonfigurowaniu pliku wejścia WebPACK następująco:

// ... React requires etc. 

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

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

Pomysł jest, że w moim klientem, mogę zrobić coś jak następuje:

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

I moja funkcja MyApp#init spowoduje zrenderowanie aplikacji React wewnątrz jakiegoś kontenera na kliencie.

Czy o tym myślę we właściwy sposób? Czy istnieje prostszy lub bardziej skuteczny sposób na poradzenie sobie z tym?

Mój błąd: Uncaught TypeError: Cannot set property 'MyApp' of undefined, ponieważ this wewnątrz IIFE jest undefined. Naprawdę chciałbym zrozumieć zarówno dlaczego tak się dzieje, jak i porady, jak to naprawić.

Z góry dziękuję!

Odpowiedz

14

Więc niby znaleźli rozwiązanie tego, jak opisano here

Jeśli zmienię mój plik webpack.config.js dodać następujące atrybuty do obiektu output, tj

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

Określa plik I Łączenie z pakietem sieci Web jako modułem UMD, więc jeśli mam funkcję w tym pliku i wyeksportuję ją ...

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

Mogę wtedy, w moim kliencie, wykonać następujące czynności.

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

I moja aplikacja React renderuje.

Jeśli ktoś myśli, że to głupi sposób, chciałbym to usłyszeć!

+0

Cześć, mattsch. To dobre rozwiązanie. Mam tylko pytanie, w jaki sposób mogę sprawdzić, czy widget jest zintegrowany z witryną klienta.Powiedzmy, że masz aplikację i zbudujesz widżet. Sprawdziłbym, czy jakiś użytkownik (według id lub nazwy hosta) umieścił widżet w swojej witrynie. –

+0

@To_wave Domyślam się, że jako część funkcji 'init' możesz wysłać zapytanie do serwera z danymi klienta - to może zadziałać? – mattsch

+0

Myślałem o tym, ale to rozwiązanie nie pozwala mi sprawdzić, czy klient usunął widżet z ich strony internetowej. Tak więc z callbackiem mogę tylko sprawdzić, czy widget jest zintegrowany, ale nie został usunięty. –

0

Masz obudowę wokół swojej klasy.

MyApp musi zostać wyeksportowany lub dołączony do globalnego obiektu okna, zanim będzie można go nazwać w ten sposób.

W Twojej sytuacji nie wywołujesz MyApp.init(), ale wywołujesz window.MyApp.init(), ale okno obiektu globalnego nie ma dołączonego obiektu MyApp.

// ... 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 

Wolałbym utworzyć moduł klasy i eksportu przy użyciu eksportu. Następnie utwórz kolejny plik tylko do dołączenia do okna. Ponieważ nie uważa się za najlepszą praktykę dołączanie klas do tego okna.

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

Możesz zajrzeć do opcji zaawansowanych modułów eksportujących jak UMD, AMD ...

Powiązane problemy