Reactium Core
Reactium is a Node/Express + React.js framework for creating front-end apps.
Reactium is built on a core framework. The local development and build configuration that comes out of the box is meant to be upgradeable, so long as your application was built off a semver that is minor-version compatible with the current.
Even for larger version steps, we are going to attempt to describe (or automate) much of the migration from one version of Reactium core to another.
Updating core is performed with the
reactium
command:npx reactium update
With a number of other front-end frameworks, even those based on React, the philosophy is to entirely hide the local development/build configuration from the developer, sometimes with an eject feature to get raw configuration / build files.
Our philosophy is to create a strong opinion for building a React application, from application structure, to out of the box capabilities such as routing, plugins, and state management, while giving the code maintainer, lead-dev, and ops roles on your team the power to replace, augment, or override behaviors of the build.
Should you hack reactium_modules? Short answer: no
If you hack on the files in the
reactium_modules
directory of your project, those changes will be overwritten when executing routing reactium install
operations, similar to npm install
for node_modules
. Instead of modifying these files directly, fork Reactium-Core-Plugins on Github and send us a pull-request. We'll either add your update if appropriate.That being said, there are a number of build and development overrides built-in to core for your use.
Reason | Purpose | Where |
DDD (domain-driven design) artifact to register/unregister gulp tasks with the ReactiumGulp registry, used to generate gulp tasks at build-time. You can use this in a Reactium plugin to alter gulp tasks within your own domain. Final tasks can be overriden by gulp.tasks.override.js. | Create this file in any of the following:
| |
DDD (domain-driven design) artifact to interact with the ReactiumWebpack registry, used to generate the webpack configuration at build-time. Final configuration can be overridden by webpack.override.js | Create this file in any of the following:
| |
gulp.config.override.js | Override: .core/gulp.config.js
| Create this file in any of the following:
|
gulp.tasks.override.js | Override: .core/gulp.tasks.js
| Create this file in the project root. |
manifest.config.override.js | Override: .core/reactium-config.js
| Create this file in any of the following:
|
webpack.override.js | Override: .core/webpack.config.js
| Create this file in any of the following:
|
webpack.umd.override.js | Override: .core/webpack.config.umd.js
| Create this file in any of the following:
|
babel.config.js | Override: .core/babel.config.js
| Must exist in the project root. |
Exports a function that takes core gulp configuration object as a parameter, and returns configuration object used by gulp tasks.
In some case Webpack uses the gulp config.
/gulp.config.override.js
module.exports = config => {
// Electron configuration
config.dest.electron = 'build-electron';
config.dest.static = 'build-electron/app/public';
config.electron = {
config: {
width: 1280,
height: 1024,
show: false,
title: 'App Title',
backgroundColor: '#000000',
},
devtools: true,
};
// Disable auto launch of default browser
config.open = false;
return config;
};
Exports a function that takes an object defining core gulp tasks as a parameter, and returns and object whose properties define the tasks run by gulp.
Code example
Exports a function that takes configuration the manifest-tools use to build src/manifest.js as a parameter, and returns new manifest configuration.
/manifest.config.override.js
module.exports = config => {
// Disable code splitting for Electron projects
config.contexts.components.mode = 'sync';
config.contexts.common.mode = 'sync';
config.contexts.toolkit.mode = 'sync';
config.contexts.core.mode = 'sync';
return config;
};
Exports a function that takes the core webpack configuration as a parameter, and returns an object that will be used for webpack to build the js bundle.
/webpack.override.js
const webpack = require('webpack');
const path = require('path');
/**
* Passed the current webpack configuration from core
* @param {Object} webpackConfig the .core webpack configuration
* @return {Object} your webpack configuration override
*/
module.exports = webpackConfig => {
const newWebpackConfig = Object.assign({}, webpackConfig);
newWebpackConfig.entries['entry'] = path.resolve('/path/to/my/entry');
newWebpackConfig.plugins.push(new webpack.ContextReplacementPlugin(/^my-context/, context => {
context.request = path.resolve('./src/app/my-context');
}));
return newWebpackConfig;
};
Serves the same purpose at the webpack.override.js except overrides the configuration used for each UMD (Universal Module Definition) module that is created by making a umd.js DDD artifact in your project. The callback function you export will receive at separate webpack configuration for each umd.js module to be created.
/webpack.umd.override.js
/**
* Passed the current webpack configuration from core
* @param {Object} umd module manifest configuration, generated when
* umd files are located.
* @param {Object} webpackConfig the .core webpack configuration
* @return {Object} your webpack configuration override
*/
module.exports = (umd, webpackConfig) => {
if (umd.libraryName === 'media-uploader') {
delete webpackConfig.module.rules;
}
return webpackConfig;
};
To see what is generated for each umd in the manifest, look in .tmp/umd-manifest.json after running the build (
npm run build
). This will contain all the objects generated when looking for umd.js DDD artifacts. See the umd-config.json DDD artifact for more information on controlling this behavior.Required and provided by default.
Imports babel configuration and exports the configuration used by Webpack and babel-node.
/babel.config.js
const config = require('./.core/babel.config');
// To add a module resolver for node and webpack
const path = require('path');
const moduleResolver = config.plugins.find(plugin => plugin[0] === 'module-resolver');
moduleResolver[1].alias['redux-addons'] = './src/app/redux-addons';
module.exports = config;
Important to dev-leads, ops and backend devs, there are a number of ways you can change the behavior of the core express server without hacking .core.
To add or change the stack of Node / Express middleware for the running server, create a src/app/server/middleware.js file, which should export a function taking an array of express middlewares as an argument, and returns the modified list of middlewares.
In this way, you can add/change routing, security configuration, etc to your hearts content.
/src/app/server/middleware.js
module.exports = expressMiddlewares => {
// Simple Logger
const mySimpleRequestLogger = (req, res, next) => {
console.log('SIMPLE LOGGER: REQUEST '+req.path);
next();
};
return [
{
name: 'mySimpleRequestLogger',
use: mySimpleRequestLogger,
},
...expressMiddlewares,
];
};
Express Middleware Example #2:
/src/app/server/middleware.js
// Health check route handler
const express = require('express');
const router = express.Router();
const healthy = router.get('/healthcheck', (req, res) => {
res.status(200).send('ok');
});
module.exports = expressMiddlewares => {
return [
{
name: 'myRouteHandler',
use: router,
},
...expressMiddlewares,
];
};
Express Middleware Example #3:
/src/app/server/middleware.js
// More secure Cross Origin Request Sharing for production: