Buildtime Domain Model

Build Artifacts

If you wish to use the Reactium SDK and hooks system to change the behavior of Gulp tasks or Webpack compilation for your plugin, you can use build-time DDD artifacts to register your behaviors.

reactium-gulp.js

Reactium's build process is started and primarily controlled by Gulp tasks:

Gulp tasks
npx gulp --tasks

Tasks for ~/Reactium/gulpfile.js
├── apidocs
├── local
├── assets
├── preBuild
├─┬ build
 └─┬ <series>
   ├── preBuild
   ├── ensureReactiumModules
   ├── clean
   ├── manifest
   ├─┬ <parallel>
    ├── markup
    └── json
   ├─┬ <parallel>
    ├── assets
    └── styles
   ├── scripts
   ├── umdLibraries
   ├── serviceWorker
   ├── compress
   └── postBuild
├── compress
├── postBuild
├── postServe
├── clean
├── ensureReactiumModules
├── default
├── json
├─┬ manifest
 └─┬ <series>
   └─┬ <parallel>
     ├─┬ <series>
      ├── domainsManifest
      └── mainManifest
     ├── externalsManifest
     └── umdManifest
├── domainsManifest
├── mainManifest
├── externalsManifest
├─┬ umd
 └─┬ <series>
   ├── umdManifest
   └── umdLibraries
├── umdManifest
├── umdLibraries
├── markup
├── scripts
├── serve
├── serve-restart
├── serviceWorker
├─┬ sw
 └─┬ <series>
   ├── umd
   └── serviceWorker
├── static
├── static:copy
├── styles:partials
├── styles:pluginAssets
├── styles:colors
├── styles:compile
├─┬ styles
 └─┬ <series>
   ├── styles:colors
   ├── styles:pluginAssets
   ├── styles:partials
   └── styles:compile
├── watch
└── watchFork

As you can see above, there are many tasks performed with Gulp, and you may wish to create, change, or delete tasks that are run during the build, and this can be done with ease using the reactium-gulp.js artifact.

When you start the build (npm run build or npm run local for product or local development respectively), really you are invoking the gulp default task, which in turn will kick off a number of other tasks in series or in parallel.

All built-in Gulp task are defined in .core/gulp.tasks.js

An abbreviated summary of the default gulp task starts a series of tasks as follows:

  1. A stub preBuild task (does nothing, meant to be optionally implemented by your project)

  2. Cleanup tasks to prepare the project directory (ensure reactium_modules directory exists, remove contents of public, ...)

  3. Prepare a set of source manifests based on DDD artifacts found throughout your project.

  4. Build static html markup and any generated json files

  5. Process assets such as images, and compile CSS (using SASS)

  6. Compile your application javascript with Webpack

  7. Build any UMD (Universal Module Definition) files with Webpack

  8. Create a Google Workbox service worker

  9. Compress all compiled assets (for quicker delivery)

  10. Generate API docs

  11. A stub postBuild task (does nothing, meant to be optionally implemented by your project)

excerpt of gulp.tasks.js (default task)
    task('preBuild'),
    task('ensureReactiumModules'),
    task('clean'),
    task('manifest'),
    gulp.parallel(task('markup'), task('json')),
    gulp.parallel(task('assets'), task('styles')),
    task('scripts'),
    task('umdLibraries'),
    task('serviceWorker'),
    task('compress'),
    task('apidocs'),
    task('postBuild'),

For those industrious folks, see reactium_modules/@atomic-reactor/reactium-core/gulp.tasks.js for the full details of what gulp tasks are defined in core.

See reactium-gulp section below for how to properly change these in your project.

ReactiumGulp

Prior to running any Gulp task, all of the tasks are registered to a global singleton ReactiumGulp, that is made available to any reactium-gulp.js file found in your project under:

  • anywhere in the src directory (or any subdirectory)

  • anywhere in the reactium_modules directory

If a reactium-gulp.js file is found anywhere in one of these location, it will be loaded during the initialization of Gulp prior to running any gulp task. Inside this file, you may register one or more Reactium Gulp synchronous hooks to change the behavior of the gulp build for the whole project.

For example, say you do not wish to use the current Dart SASS compilation (defined in the .core/gulp.tasks.js in the styles:compile task, but instead which to replace this with node-sass. To do this, first you will want to register a synchronous tasks hook callback. This hook will be passed the task registry used to generate the full list of gulp tasks you see above. Use this registry to unregister the existing gulp task, and replace it with your own.

reactium-gulp.js
const gulp = require('gulp');
const sass = require('gulp-sass');
sass.compiler = require('node-sass');
const reactiumImporter = require('@atomic-reactor/node-sass-reactium-importer');
const jsonFunctions = require('node-sass-functions-json').default;
const sourcemaps = require('gulp-sourcemaps');
const gulpif = require('gulp-if');
const cleanCSS = require('gulp-clean-css');
const prefix = require('gulp-autoprefixer');
const rename = require('gulp-rename');
const env = process.env.NODE_ENV || 'development';
const isDev = env === 'development';
const browserSync = require('browser-sync');

ReactiumGulp.Hook.registerSync('tasks', (GulpRegistry, config) => {
    GulpRegistry.unregister('styles:compile');

    const compileStyles = () => {
        return gulp
            .src(config.src.style)
            .pipe(gulpif(isDev, sourcemaps.init()))
            .pipe(
                sass({
                    functions: Object.assign({}, jsonFunctions),
                    importer: reactiumImporter,
                    includePaths: config.src.includes,
                }).on('error', sass.logError),
            )
            .pipe(prefix(config.browsers))
            .pipe(gulpif(!isDev, cleanCSS()))
            .pipe(gulpif(isDev, sourcemaps.write()))
            .pipe(rename({ dirname: '' }))
            .pipe(gulp.dest(config.dest.style))
            .pipe(gulpif(isDev, browserSync.stream()));
    };

    GulpRegistry.register('styles:compile', {
        task: compileStyles,
        order: 100,
    });
});

You might also wish to change the values specified by .core/gulp.config.js that are used in your tasks. You can do this with the synchronous config hook.

reactium-gulp.js
// change the location where _colors.scss is generated by the
// styles:colors gulp task

ReactiumGulp.Hook.registerSync('config', gulpConfig => {
  gulpConfig.dest.colors = 'src/app/components/Admin/style/_colors.scss';
});

This isn't the last or only way to manipulate the gulp tasks for your project. If you would prefer to get in between the final list of tasks that are used for gulp, you may wish to create a gulp.tasks.override.js file. Either method is fine, however gulp.tasks.override.js will simply export a function that returns the entire list of gulp tasks (including the default), and may invalidate other plugins' efforts from reactium-gulp.js. If you wish to play nice, use reactium-gulp.js

reactium-webpack.js

When the Gulp scripts task is run, Gulp will run the Webpack compilation specified by the overridable configuration in .core/webpack.config.js. Likewise, when compiling any UMD (Universal Module Definition) javascript modules during the Gulp umdLibraries task, Gulp will run the Webpack compiliation specified by the overridable configuration provided in .core/umd.webpack.config.js.

ReactiumWebpack

Prior to running any either the main or umd Webpack compilations, the webpack configuration is run through a series of hooks that are registered to a global singleton ReactiumWebpack, that is made available to any reactium-webpack.js file found in your project under:

  • anywhere in the src directory (or any subdirectory)

  • in any node module directory located in a reactium-plugin directory

  • anywhere in the reactium_modules directory

If a reactium-webpack.js file is found anywhere in one of these location, it will be loaded during the initialization of Webpack configuration prior to running any compilation. Inside this file, you may register one or more Reactium Webpack synchronous hooks to change the behavior of the webpack compilation for the whole project.

Note: most of the WebpackSDK registries (ignores, externals, rules, plugins) have an sdk property that refers back to the WebpackSDK object.

Both of the main webpack configuration and the umd configurations are built using a helper object, WebpackSDK:

WebpackSDK

This class provided the following public properties and methods, to aid in managing your Webpack configuration:

WebpackSDK setters

Most of the webpack configuration that is not terribly complex is handled with simple setters.

Setter for the webpack mode configuration property

Setter for the webpack entry configuration property

Setter for webpack target configuration property

Setter for webpack output configuration property

Setter for webpack devtool configuration property

WebpackSDK Methods

Automatically configures the webpack optimization configuration property, attempting to code-split Reactium javascript bundles into chunks that can be lazy loaded automatically by webpack, optimized to Reactium's logical components.

Automatically configures the webpack optimization configuration property, attempting to code-split Reactium javascript bundles into chunks that can be lazy loaded automatically by webpack, in a way that is fairly default Webpack code-splitting behavior.

Automatically configures the webpack optimization configuration property, setting up Reactium to bundle everything together in one monolithic bundle.

To get this behavior for the top-level application entries, you can also start the build with the Environment Variable DISABLE_CODE_SPLITTING set to 'true'.

Used to register Webpack plugins, and give them an id, so they can be overridden or removed.

Alternately, you can call register() on WebpackSDK.plugins (a standard Reactium registry). See Using Registry tab.

Used to register Webpack module rules, but give them an id, so they can be easily overridden or removed.

Alternately, you can call register() on WebpackSDK.rules (a standard Reactium registry). See Using Registry tab.

A special registry that manages the webpack.IgnorePlugin, allowing you to easily specify regular expression that will instruct Webpack what sort of modules to ignore.

Alternately, you can call register() on WebpackSDK.ignores (a standard Reactium registry). See Using Registry tab.

A special registry that manages the webpack.ContextReplacementPlugin, allowing you to easily specify regular expression that will instruct Webpack what sort of modules to ignore.

Alternately, you can call register() on WebpackSDK.plugins (a standard Reactium registry), and register a new instance of the webpack.ContextReplacementPlugin. See Using Registry tab.

Last updated