Writing embeddable Javascript plugin with React & Webpack

后端 未结 2 1016
灰色年华
灰色年华 2020-12-04 06:43

I want to be able to bundle my React app with Webpack such that distributed copies put onto a CDN can be sourced, called and initialised with a bunch of config relevant to a

相关标签:
2条回答
  • 2020-12-04 07:26

    You have enclosure around your class.

    MyApp needs to be exported or attached to the global window object before you can call it like that.

    In your situation you are actually not calling MyApp.init() but you are calling window.MyApp.init(), but global object window does not have object MyApp attached to it.

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

    I would prefer to create class and export module using export. Then create another file just for attaching to the window. Since it is not considered best practice to attach classes to the window like that.

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

    You can look for advanced options of exporting modules as UMD, AMD...

    0 讨论(0)
  • 2020-12-04 07:27

    So I kind of found a solution to this, as described here

    If I change my webpack.config.js file to add the following attributes to the output object, i.e.

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

    This specifies the file I'm bundling with webpack as a UMD module, so if I have a function in that file and export it...

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

    I can then, in my client, do the following.

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

    And my React app renders.

    If anyone thinks this is a daft way of doing it, I'd love to hear it!

    MORE INFORMATION ON WEBPACK CONFIG

    Please bear in mind I haven't touched this code in a while. Given it's Javascript, the world has likely moved on and some practises may be outdated.

    This is my React entrypoint file (src/index.js)

    import 'babel-polyfill';
    import React from 'react';
    import { render } from 'react-dom';
    import Root from './components/Root';
    import configureStore from './lib/configureStore';
    
    const store = configureStore();
    
    export const init = (config) => {
      render(
        <Root store={store} config={config} />, 
        document.querySelector(config.selector || "")
      );
    }
    

    This is my Webpack config (webpack.config.js)

    var webpack = require('webpack');
    var path = require('path');
    var loaders = require('./webpack.loaders');
    
    module.exports = {
        entry: [
            'webpack-dev-server/client?http://0.0.0.0:8080', // WebpackDevServer host and port
            'webpack/hot/only-dev-server',
            './src/index.js' // Your appʼs entry point
        ],
        devtool: process.env.WEBPACK_DEVTOOL || 'source-map',
        output: {
            path: path.join(__dirname, 'public'),
            filename: 'bundle.js',
            library: 'Foo',
            libraryTarget: 'umd',
            umdNamedDefine: true,
        },
        resolve: {
            extensions: ['', '.js', '.jsx']
        },
        module: {
            loaders: loaders
        },
        devServer: {
            contentBase: "./public",
                noInfo: true, //  --no-info option
                hot: true,
                inline: true
            },
        plugins: [
            new webpack.NoErrorsPlugin()
        ]
    };
    

    As you can see, my Webpack config outputs my bundle.js which is what my front-end will ingest.

    0 讨论(0)
提交回复
热议问题