Last Updated on March 4, 2020 by Neil Murray
All JavaScript & CSS used in the CF7 Skins Visual interface, is built using webpack.
All React development files are contained in ..\cf7skins-visual\src\ which is built to ..\cf7skins-visual\dist\ by webpack.
create-react-app #
We are using an ejected version of create-react-app (CRA). We update our npm package versions in package.json to match updated create-react-app versions.
We have customized the following CRA webpack.config files:
- webpack.config.dev.js
- webpack.config.prod.js
We do this to ensure operation of the JavaScript interface at localhost:3000 matches with operation in the wp-admin.
2018-09-05 Right now create-react-app uses Webpack 3
Refer:
- Eject create-react-app (Bitbucket Issue)
webpack build process #
Our Build Scripts #
We adapt the build scripts from create-react-app:
"scripts": {
"start": "node scripts/start.js", // local JS development at http://localhost:3000 - changes are reloaded automatically
"build": "node scripts/build.js", // from create-react-app
"test": "node scripts/test.js --env=jsdom", // from create-react-app
"webpack": "webpack" // rebuilds CF7 Skins Visual plugins in wp-admin using local webpack version
},
Building our WordPress Plugins #
We use webpack to build separate plugin versions (Dev, Lite, Pro + Add-ons) of CF7 Skins Visual from a single Git repo at https://bitbucket.org/cf7skins/cf7skins-dev-cf7skins-visual.
These plugins can be selectively activated in the wp-admin to test how the Visual Editor operates in our different CF7 Skins plugins:
- Visual Dev – Contact Form 7 Skins + CF7 Skins Pro + Add-ons
- Visual Lite – Contact Form 7 Skins only
- Visual Pro – CF7 Skins Pro + Add-ons
We select which React Components are included in each version when we build each plugin.
NOTE: The JS code generated in CF7 Skins Visual is currently copied manually to our CF7 Skins plugins in their individual Git repositories.
Refer:
- Setup CF7 Skins Lite & Pro plugins (Bitbucket Issue)
- Setup webpack for CF7 Skins build process (Bitbucket Issue)
Code Splitting #
We use webpack for bundling process and to ensure that no Add-on code is included in the free version of CF7 Skins – refer Separating Add-on files.
All the JS code for each Add-on is created as a chunk which can be added as a standalone file in the individual Add-on plugin.
Configurations #
To build and split several files, we use multiple configurations with slightly different webpack
configurations, entries and output:
baseConfigas base configuration contains webpack default module rules and output for merging with other config.visualConfigto generatevisual.jsfile and AddOns files configuration.addonsConfigto exportaddons.jsintowindow.cf7svisualused by AddOns.
We use Lodash.merge() ↗ for merging the two config object by appending child object properties without overriding source object. Object.assign() ↗ override source object properties with target object.
Entries #
We setup webpack entry as an object that contains entry (file) name and its path relative to current webpack config file path. These entries are built into standalone chunk files:
visual.js– common chunk file, contains all required modules, Visual components and functions, a big file size.-
- We use
CommonsChunkPluginto build the chunk. - The modules should not be added or repeated into other files because it will generates error – see multiple copies of React loaded
error.
- This file should be enqueued first before other chunk files.
- We use
-
ready.js– AddOns file chunk for Ready plugin .addons.js– used by AddOns to register their component into Visual.
This is the same approach as WordPress filters. Read more about working with AddOns
.
Sample webpack entries:
// visualConfig
entry: {
visual : './src/index.js',
ready : './src/visual/Addons/Ready/index.js',
},
// addonsConfig
entry: {
addons : './src/visual/Addons/addons.js',
},
Output #
For base configuration baseConfig, we build each entry chunk into dist directory with the entry name as filename.
output: {
filename: "dist/[name].js",
},
String [name] will be replaced by webpack with respective entry name. Read more about webpack output.filename ↗. The output filename will be merged with other configs.
output: {
filename: "dist/[name].js", // after merging
library: [ 'cf7svisual', '[name]' ], // [name] replaced to `addons`
libraryTarget: 'window',
},
For addons configuration addonsConfig, we use output.library ↗ to output addons.js as a library for other files and output.librarytarget ↗ to exposed it into window. AddOns can used it by accessing window.cf7svisual.addons.

Exposed addons.js into window.cf7svisual
Further Reading:
- Separating Add-on files
- Working with CF7 Skins Add-ons
- webpack multiple configurations
- multiple copies of React loaded
webpack.config.js #
npm packages used #
- autoprefixer – add vendor prefixes to CSS rules
- babel-plugin-transform-runtime – avoid duplication of babel helpers & creates sandboxed code environment
- babel-plugin-transform-object-rest-spread – transform rest properties for object destructuring assignment and spread properties for object literals
- babel-plugin-syntax-dynamic-import – allow parsing of import()
- babel-plugin-dynamic-import-node – transpile import() to a deferred require(), for node
- browser-sync – keep multiple browsers & devices in sync
- cross-env – use environment variables across platforms without problems
- enzyme – JavaScript testing utility for React
- extract-text-webpack-plugin – extract text from bundle into a separate file
- lodash – JavaScript utility library
- nodemon – automatically restart Node.js when file changes are detected
- path – Node.js path module – utilities for working with file and directory paths
- postcss – tool for transforming CSS styles with PostCSS
- ncp – copy files programmatically
- react-error-overlay – displays when there is a runtime error
- sinon – JavaScript test spies, stubs and mocks
- webpack-shell-plugin – run shell commands before or after webpack builds
- whatwg-fetch – polyfill for fetch()
webpack plugins used #
- CommonsChunkPlugin – generate chunk which contains common modules shared between entry points
Loaders #
- babel-loader – transpile JavaScript files
- style-loader – add CSS to the DOM by injecting a style tag
- css-loader – translates CSS into CommonJS
- postcss-loader – process CSS with PostCSS
- postcss-flexbugs-fixes – tries to fix all of flexbox’s issues
- html-loader – exports HTML as string
- url-loader – loads files as base64 URIs if small size (fallsback to file-loader)
- file-loader – loads files as URL
- less-loader – compiles LESS files to CSS & extracts into a separate file
- sass-loader – loads SASS/SCSS file and compiles it to CSS
Tests:
- .js
- .css
- .scss
- .less
- .html
- (woff|ttf|eot|svg)
Plugins #
- ExtractTextPlugin – used by ‘less-loader’ to extract CSS into a separate file
- WebpackShellPlugin – runs commands before & after webpack build
In order to use a plugin, you need to require() it and add it to the plugins array. You need to create an instance of it by calling it with the new operator (since you can use a plugin multiple times in a config for different purposes).
