Build configuration plugins
To create a build plugin - means to create extend the application build configuration. The build plugins can modify: Webpack, Webpack dev-server, Craco configurations. You can also provide commands to run before starting the build.
Instruction
Example
- 1.Define an empty object as a value of the
scandipwa.build
field in your extension'spackage.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 yourpackage.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.
You can also use the existing Craco extensions. You can find the list of them here. 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 tomagento/Magento_Theme
. - The
appHtml
topublic/index.php
. - The options field
filename
of theHtmlWebpackPlugin
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.
We used
getLoader
and loaderByName
utility functions of Craco. Learn more about them in official Craco guide.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;
}
}
};
Instruction
Example
- 1.Define an empty object as a value of the
scandipwa.build
field in your extension'spackage.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 yourpackage.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();
}
};
The plugin syntax of Create ScandiPWA App is based on the Craco (Create React App Configuration Override) plugin 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.
Instruction
Example
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;
}
Instruction
Example
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;
}
Instruction
Example
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;
}
Last modified 2yr ago