web-dev-qa-db-fra.com

Ecrire un plugin Javascript intégrable avec React & Webpack

Je souhaite pouvoir regrouper mon application React avec Webpack de telle sorte que les copies distribuées placées sur un CDN puissent être recherchées, appelées et initialisées avec un tas de configurations pertinentes pour un client.

Après avoir lu this et this , je configure mon fichier d’entrée Webpack comme suit:

// ... React requires etc.

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

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

L'idée étant que chez mon client, je peux faire quelque chose comme ceci:

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

Et ma fonction MyApp#init rendra mon application React dans un conteneur du client.

Est-ce que je pense à cela de la bonne manière? Existe-t-il un moyen plus simple ou plus efficace de s'y prendre?

Mon erreur est Uncaught TypeError: Cannot set property 'MyApp' of undefined, puisque this à l'intérieur de l'IIFE est undefined. J'aimerais vraiment comprendre à la fois pourquoi cela se produit et des conseils pour y remédier.

Merci d'avance!

20
mattsch

J'ai donc en quelque sorte trouvé une solution à cela, comme décrit ici

Si je modifie mon fichier webpack.config.js pour ajouter les attributs suivants à l'objet output, c.-à-d.

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

Cela spécifie le fichier que je regroupe avec webpack en tant que module UMD, donc si j'ai une fonction dans ce fichier et que je l'exporte ...

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

Je peux alors, dans mon client, faire ce qui suit.

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

Et mon application React rend.

Si quelqu'un pense que c'est une façon idiote de le faire, j'aimerais l'entendre!

29
mattsch

Vous avez la clôture autour de votre classe.

MonApp doit être exporté ou attaché à l'objet de fenêtre global avant de pouvoir l'appeler ainsi. 

Dans votre cas, vous n'appelez pas réellement MyApp.init () mais vous appelez window.MyApp.init (), mais la fenêtre de l'objet global n'a pas d'objet MyApp qui lui est associé.

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

Je préférerais créer un module de classe et d'exportation à l'aide de l'exportation. Ensuite, créez un autre fichier juste pour attacher à la fenêtre. Comme il n'est pas considéré comme la meilleure pratique d'attacher des classes à la fenêtre comme ça.

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

Vous pouvez rechercher des options avancées d’exportation de modules tels que UMD, AMD ...

0
Marcel Mandatory