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