Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
417 views
in Technique[技术] by (71.8m points)

reactjs - Writing embeddable Javascript plugin with React & Webpack

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

After reading this and this, I'm setting up my webpack entry file as follows:

// ... React requires etc.

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

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

The idea being that in my client, I can do something like the following:

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

And my MyApp#init function will render my React app inside some container on the client.

Am I thinking about this in the right way? Is there a simpler or more efficient way to go about this?

My error is Uncaught TypeError: Cannot set property 'MyApp' of undefined, since this inside the IIFE is undefined. I'd really like to understand both why this is happening and advice on how to fix it.

Thanks in advance!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...