Create ScandiPWA App
ScandiPWA DocsCreate Magento AppGitHub
  • Create ScandiPWA App
  • Getting Started
    • Getting Started
    • Folder structure
    • Supported Browsers & Features
    • Updating to New Releases
  • Themes
    • Themes
    • File overrides
  • Extensions
    • Extensions
    • Installation
    • Application plugins
      • Plugin Templates
    • Build configuration plugins
    • Plugins for HTML and PHP
    • File provision
    • Module preference
  • Building your app
    • Proxying requests to server
    • Internationalization
    • Creating production build
  • Deploying your app
    • Storefront
    • Magento theme
Powered by GitBook
On this page
  • To create a build plugin
  • To define a before run script
  • Build plugin implementation syntax
  • Craco configuration plugin
  • Webpack configuration plugin
  • Webpack dev-server configuration plugin

Was this helpful?

  1. Extensions

Build configuration plugins

PreviousPlugin TemplatesNextPlugins for HTML and PHP

Last updated 4 years ago

Was this helpful?

ScandiPWA introduces concept of "build plugins". This is a feature of .

To create a build plugin - means to create extend the application build configuration. The build plugins can modify: , , configurations. You can also provide commands to run before starting the build.

To create a build plugin

  1. Define an empty object as a value of the scandipwa.build field in your extension's package.json

    1. Populate the configuration object with cracoPlugins field, set it to empty array.

  2. Create a new folder in your extension's root, name it build-config:

    1. Create a new file in it, name it to represent it's build modification purpose

    2. Populate an array of cracoPlugins in your package.json with a path to your new file (relative to the extension root).

  3. Inside of your plugin file, define a module.exports equal to an object. This object may have two keys:

    1. plugin (required) where the plugin implementation will be defined

    2. options (optional) where the plugin options will be defined

  4. Implement a plugin in the object created at the step 3). To do it, follow .

You can also use the existing Craco extensions. You can find . You can import them and use as the plugin implementation passing into the plugin key value on the step 3).

This plugin implements a Create ScandiPWA App compilation into valid Magento 2 theme. We plan to modify the Webpack and Craco configurations.

Following instruction steps 1) and 2) we created following entry in our package.json:

{
    "scandipwa": {
        "type": "extension",
        "build": {
            "cracoPlugins": [
                "build-config/magento.js"
            ]
        }
    },
    ...
}

The new file magento.js was created in build-config folder in our extension root.

In our magento.js plugin file, we define a module.exports an object, with plugin key, where we implement extensions of Webpack and Craco configurations. We make sure:

  • The appBuild should is set to magento/Magento_Theme.

  • The appHtml to public/index.php.

  • The options field filename of the HtmlWebpackPlugin is set to ../templates/root.phtml.

  • The file-loader is excluding the .php from processing, so it does not appear in the build folder along-side of others application assets.

Heads up!

Create ScandiPWA App uses the custom fork of Craco called @scandipwa/craco.

The final file will look something like this:

const path = require('path');
const FallbackPlugin = require('@scandipwa/webpack-fallback-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { sources } = require('@scandipwa/scandipwa-scripts/lib/sources');
const { getLoader, loaderByName } = require('@scandipwa/craco');

module.exports = {
    plugin: {
        overrideCracoConfig: ({
            cracoConfig
        }) => {
            // For Magento, use magento/Magento_Theme folder as dist
            cracoConfig.paths.appBuild = path.join(process.cwd(), 'magento', 'Magento_Theme', 'web');

            // For Magento use PHP template (defined in /public/index.php)
            cracoConfig.paths.appHtml = FallbackPlugin.getFallbackPathname('./public/index.php', sources);

            // Always return the config object.
            return cracoConfig;
        },
        overrideWebpackConfig: ({ webpackConfig }) => {
            // For Magento setup, change output file name
            webpackConfig.plugins.forEach((plugin) => {
                if (plugin instanceof HtmlWebpackPlugin) {
                    plugin.options.filename = '../templates/root.phtml';
                }
            });

            const { isFound: isFileLoaderFound, match: fileLoader } = getLoader(
                webpackConfig,
                loaderByName('file-loader')
            );

            if (isFileLoaderFound) {
                // Add .php to ignore files (otherwise php will compile into /media as file)
                fileLoader.loader.exclude.push(/\.php$/);
            }

            return webpackConfig;
        }
    }
};

To define a before run script

  1. Define an empty object as a value of the scandipwa.build field in your extension's package.json

    1. Populate the configuration object with before field, set it to empty string.

  2. Create a new folder in your extension's root, name it build-config:

    1. Create a new file in it, name it to represent before-run script's purpose

    2. Set the before field in your package.json equal to a path to your new file (relative to the extension root).

  3. Inside of your plugin file, define a module.exports equal to a function.

  4. Implement a script based on your needs. No guidelines here, it's up to you!

The purpose of our script is to make sure there is a file named composer.json in the root current theme.

Following instruction steps 1) and 2) we created following entry in our package.json:

{
    "scandipwa": {
        "type": "extension",
        "build": {
            "before": "build-config/composer.js"
        }
    },
    ...
}

The new file composer.js was created in build-config folder in our extension root.

Inside of this file we will use the process.cwd() to determine the location of current theme. We will use process.exit() to exit the program and stop build from running.

The final file will look something like this:

const fs = require('fs');
const path = require('path');

module.exports = () => {
    const composerPath = path.join(process.cwd(), 'composer.json');
    
    if (!fs.existsSync(composerPath)) {
        console.log('The file "composer.json" should be present it the theme\'s root');
        process.exit();
    }
};

Build plugin implementation syntax

Each plugin is an object, which might contain following keys (you can combine them):

  • overrideCracoConfig - allows to customize the Craco configuration object.

  • overrideWebpackConfig - allows to customize the Webpack config.

  • overrideDevServerConfig - allows to customize the Webpack dev-server config

The values of this object keys are functions, which implement an override for the configuration. The function may be asynchronous.

Craco configuration plugin

The function overrideCracoConfig allows a plugin override the configuration object before it's process by Craco.

The function must return a valid Craco configuration object. The function will be called with a single object argument having the following structure:

{
    cracoConfig, // The original CRACO configuration object
    pluginOptions, // The plugin options provided by the consumer
    context: {
        env, // The current NODE_ENV (development, production, etc..)
        paths // An object that contains all the paths used by CRA
    }
}

The cracoConfig is passed into you plugin implementation by reference, which means you can modify it's values directly.

This plugin intent is to modify the paths of an application. The appBuild should be set to magento/Magento_Theme and the appHtml to public/index.php.

({ cracoConfig }) => {
    // For Magento, use magento/Magento_Theme folder as dist
    cracoConfig.paths.appBuild = path.join(process.cwd(), 'magento', 'Magento_Theme', 'web');
    
    // For Magento use PHP template (defined in /public/index.php)
    cracoConfig.paths.appHtml = FallbackPlugin.getFallbackPathname('./public/index.php', sources);
    
    // Always return the config object.
    return cracoConfig;
}

Webpack configuration plugin

The function overrideWebpackConfig allows plugin override the Webpack configuration object after it's been customized by Craco.

The function must return a valid Webpack configuration object. The function will be called with a single object argument having the following structure:

{
    webpackConfig, // The webpack config object already customized by craco
    cracoConfig, // The configuration object read from the craco.config.js file provided by the consumer
    pluginOptions, // The plugin options provided by the consumer
    context: {
        env, // The current NODE_ENV (development, production, etc..)
        paths //An object that contains all the paths used by CRA
    }
}

The webpackConfig is passed into you plugin implementation by reference, which means you can modify it's values directly.

The plugin modifies the options field filename of the HtmlWebpackPlugin. It set's it to ../templates/root.phtml.

({ webpackConfig }) => {
    // For Magento setup, change output file name
    webpackConfig.plugins.forEach((plugin) => {
        if (plugin instanceof HtmlWebpackPlugin) {
            plugin.options.filename = '../templates/root.phtml';
        }
    });

    // Always return the config object.    
    return webpackConfig;
}

Webpack dev-server configuration plugin

The function overrideDevServerConfig let a plugin override the dev server config object after it's been customized by Craco.

The function must return a valid Webpack dev-server configuration object. The function will be called with a single object argument having the following structure:

{
    devServerConfig, // The dev server config object already customized by craco
    cracoConfig, // The configuration object read from the craco.config.js file provided by the consumer
    pluginOptions, // The plugin options provided by the consumer
    context: {
        env, // The current NODE_ENV (development, production, etc..)
        paths, // An object that contains all the paths used by CRA
        allowedHost // Provided by CRA
    }
}

This plugin dumps the configuration object of Webpack dev-server for debugging purposes.

({ devServerConfig }) => {
    // Dump the configuration file and format it
    console.log(JSON.stringify(devServerConfig, null, 4));
    
    // Always return the config object.
    return devServerConfig;
}

We used getLoader and loaderByName utility functions of Craco. Learn more about them in .

The plugin syntax of Create ScandiPWA App is based on the (Create React App Configuration Override) plugin syntax.

official Craco guide
Craco
ScandiPWA extensions
Webpack
Webpack dev-server
Craco
the list of them here
these guidelines