Skip to content

Commit

Permalink
updated react support
Browse files Browse the repository at this point in the history
* updated to react 16.
* created a component mounting helper to initalize react componenets
from rails views
* create a component registery, so that plugins can register their
top level containers
* broke down generate webpack chunks into plugin specific vs common
js code (to avoid duplications of js code within the bundle)
* change webpack source maps to inline so it can easily be used to
debug in the browser. (see webpack/webpack#2145)
* updated webpack configuration so it can read from a package.json
defined on a plugin
  • Loading branch information
ohadlevy committed Nov 6, 2017
1 parent 3734555 commit b6455cf
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 19 deletions.
1 change: 0 additions & 1 deletion .eslintrc.json
@@ -1,6 +1,5 @@
{
"root": true,
"installedESLint": true,
"env": {
"browser": true,
"jquery": true
Expand Down
1 change: 1 addition & 0 deletions app/helpers/application_helper.rb
Expand Up @@ -12,6 +12,7 @@ module ApplicationHelper
include NumberHelper
include PlanningHelper
include Title
include ReactjsHelper

VALID_PERF_PARENTS = {
"EmsCluster" => :ems_cluster,
Expand Down
7 changes: 7 additions & 0 deletions app/helpers/reactjs_helper.rb
@@ -0,0 +1,7 @@
module ReactjsHelper
def mount_react_component(name, selector, data = [])
javascript_tag(:defer => 'defer') do
"$(MiqReact.mount('#{name}', '#{selector}', #{data.to_json}));".html_safe
end
end
end
13 changes: 7 additions & 6 deletions app/javascript/packs/application-common.js
Expand Up @@ -6,10 +6,11 @@
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
import { mount } from '../react/mounter';
import componentRegistry from '../react/componentRegistry';

console.log('Hello World from Webpacker')

import * as React from 'react';
import * as ReactDOM from 'react-dom';
window.React = React;
window.ReactDOM = ReactDOM;
// TODO: use ManageIQ object, once race conditions are fixed
window.MiqReact = Object.assign(window.MiqReact || {}, {
mount: mount,
componentRegistry: componentRegistry
});
59 changes: 59 additions & 0 deletions app/javascript/react/componentRegistry.js
@@ -0,0 +1,59 @@
import React from 'react';
import forEach from 'lodash/forEach';
import map from 'lodash/map';

const componentRegistry = {
registry: {},

register({ name = null, type = null, store = true, data = true }) {
if (!name || !type) {
throw new Error('Component name or type is missing');
}
if (this.registry[name]) {
throw new Error(`Component name already taken: ${name}`);
}

this.registry[name] = { type, store, data };
return this.registry;
},

registerMultiple(componentObjs) {
return forEach(componentObjs, obj => {
return this.register(obj);
});
},

getComponent(name) {
return this.registry[name];
},

registeredComponents() {
return map(this.registry, (value, key) => {
return key;
}).join(', ');
},

markup(name, data, store) {
const currentComponent = this.getComponent(name);

if (!currentComponent) {
throw new Error(
`Component not found: ${name} among ${this.registeredComponents()}`
);
}
const ComponentName = currentComponent.type;

return (
<ComponentName
data={currentComponent.data ? data : undefined}
store={currentComponent.store ? store : undefined}
/>
);
}
};

const coreComponets = [];

componentRegistry.registerMultiple(coreComponets);

export default componentRegistry;
17 changes: 17 additions & 0 deletions app/javascript/react/mounter.js
@@ -0,0 +1,17 @@
import React from 'react';
import ReactDOM from 'react-dom';
import componentRegistry from './componentRegistry';

export function mount(component, selector, data = {}) {
const reactNode = document.querySelector(selector);

if (reactNode) {
ReactDOM.unmountComponentAtNode(reactNode);
ReactDOM.render(componentRegistry.markup(component, data), reactNode);
} else {
// eslint-disable-next-line no-console
console.log(
`Cannot find \'${selector}\' element for mounting the \'${component}\'`
);
}
}
1 change: 1 addition & 0 deletions app/views/layouts/application.html.haml
Expand Up @@ -32,6 +32,7 @@
= csrf_meta_tag
= render :partial => 'layouts/i18n_js'
-# FIXME: the conditional below is a temporary fix for a webpacker issue, remove when it's resolved
= javascript_pack_tag 'vendor'
- unless Rails.env.test?
- Webpacker::Manifest.instance.data.keys.each do |pack|
= javascript_pack_tag pack if pack.ends_with? '-common.js'
Expand Down
2 changes: 1 addition & 1 deletion config/webpack/development.js
Expand Up @@ -5,7 +5,7 @@ const sharedConfig = require('./shared.js')
const { settings, output } = require('./configuration.js')

module.exports = merge(sharedConfig, {
devtool: 'cheap-eval-source-map',
devtool: 'inline-source-map',

stats: {
errorDetails: true
Expand Down
14 changes: 8 additions & 6 deletions config/webpack/shared.js
Expand Up @@ -56,16 +56,18 @@ module.exports = {

new ManifestPlugin({
publicPath: output.publicPath,
writeToFileEmit: true
})
writeToFileEmit: true,
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
}),
],

resolve: {
extensions: settings.extensions,
modules: [
resolve(settings.source_path),
'node_modules'
]
modules: [resolve(settings.source_path)].concat(
Object.values(engines).map(engine => `${engine}/node_modules`)
),
},

resolveLoader: {
Expand Down
10 changes: 5 additions & 5 deletions package.json
Expand Up @@ -22,11 +22,10 @@
"@angular/core": "~4.0.3",
"@angular/platform-browser": "~4.0.3",
"@angular/platform-browser-dynamic": "~4.0.3",
"babel-preset-react": "^6.24.1",
"core-js": "~2.4.1",
"prop-types": "^15.5.10",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"prop-types": "^15.6.0",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"rxjs": "~5.3.0",
"ui-select": "0.19.8",
"zone.js": "~0.8.5"
Expand All @@ -40,6 +39,7 @@
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-polyfill": "^6.23.0",
"babel-preset-env": "~1.4.0",
"babel-preset-react": "^6.24.1",
"coffee-loader": "~0.7.3",
"coffee-script": "~1.12.5",
"compression-webpack-plugin": "~0.4.0",
Expand All @@ -51,7 +51,7 @@
"eslint-plugin-import": "~1.9.2",
"eslint-plugin-jsx-a11y": "~1.5.3",
"eslint-plugin-promise": "~3.3.0",
"eslint-plugin-react": "~5.1.1",
"eslint-plugin-react": "~7.4.0",
"eslint-plugin-standard": "~2.0.1",
"extract-text-webpack-plugin": "~2.1.0",
"file-loader": "~0.11.1",
Expand Down

0 comments on commit b6455cf

Please sign in to comment.