Form editor and settings used to have a separate configs because we they use lodash and it conflicted with underscore in newsletter edtior. We had recently fixed that conflict and now we can add them to admin. This also resolves an issue with multiple loading of @emotion/react [MAILPOET-3654]
397 lines
10 KiB
JavaScript
397 lines
10 KiB
JavaScript
const webpack = require('webpack');
|
|
const webpackManifestPlugin = require('webpack-manifest-plugin');
|
|
const webpackTerserPlugin = require('terser-webpack-plugin');
|
|
const webpackCopyPlugin = require('copy-webpack-plugin');
|
|
const path = require('path');
|
|
const del = require('del');
|
|
const globalPrefix = 'MailPoetLib';
|
|
const PRODUCTION_ENV = process.env.NODE_ENV === 'production';
|
|
const manifestSeed = {};
|
|
|
|
// Base config
|
|
const baseConfig = {
|
|
mode: PRODUCTION_ENV ? 'production' : 'development',
|
|
devtool: PRODUCTION_ENV ? undefined : 'eval-source-map',
|
|
cache: true,
|
|
bail: PRODUCTION_ENV,
|
|
context: __dirname,
|
|
watchOptions: {
|
|
aggregateTimeout: 300,
|
|
poll: true
|
|
},
|
|
optimization: {
|
|
minimizer: [
|
|
new webpackTerserPlugin({
|
|
terserOptions: {
|
|
// preserve identifier names for easier debugging & support
|
|
mangle: false,
|
|
},
|
|
parallel: false,
|
|
}),
|
|
],
|
|
},
|
|
output: {
|
|
path: path.join(__dirname, 'assets/dist/js'),
|
|
filename: (PRODUCTION_ENV) ? '[name].[hash:8].js' : '[name].js',
|
|
chunkFilename: (PRODUCTION_ENV) ? '[name].[hash:8].chunk.js' : '[name].chunk.js',
|
|
jsonpFunction: 'mailpoetJsonp'
|
|
},
|
|
resolve: {
|
|
modules: [
|
|
'node_modules',
|
|
'assets/js/src',
|
|
],
|
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
|
alias: {
|
|
'handlebars': 'handlebars/dist/handlebars.js',
|
|
'backbone.marionette': 'backbone.marionette/lib/backbone.marionette',
|
|
'backbone.supermodel$': 'backbone.supermodel/build/backbone.supermodel.js',
|
|
'sticky-kit': 'vendor/jquery.sticky-kit.js',
|
|
'interact$': 'interact.js/interact.js',
|
|
'spectrum$': 'spectrum-colorpicker/spectrum.js',
|
|
'wp-js-hooks': path.resolve(__dirname, 'assets/js/src/hooks.js'),
|
|
'blob$': 'blob-tmp/Blob.js',
|
|
'papaparse': 'papaparse/papaparse.min.js',
|
|
'html2canvas': 'html2canvas/dist/html2canvas.js',
|
|
'asyncqueue': 'vendor/jquery.asyncqueue.js',
|
|
},
|
|
},
|
|
node: {
|
|
fs: 'empty'
|
|
},
|
|
plugins: [],
|
|
module: {
|
|
noParse: /node_modules\/lodash\/lodash\.js/,
|
|
rules: [
|
|
{
|
|
test: /\.(j|t)sx?$/,
|
|
exclude: /(node_modules|src\/vendor)/,
|
|
loader: 'babel-loader',
|
|
},
|
|
{
|
|
test: /form_editor\.js$/,
|
|
loader: 'expose-loader?WysijaForm',
|
|
},
|
|
{
|
|
include: require.resolve('codemirror'),
|
|
loader: 'expose-loader?CodeMirror',
|
|
},
|
|
{
|
|
include: require.resolve('backbone'),
|
|
loader: 'expose-loader?Backbone',
|
|
},
|
|
{
|
|
include: require.resolve('underscore'),
|
|
loader: 'expose-loader?_',
|
|
},
|
|
{
|
|
include: require.resolve('react-tooltip'),
|
|
loader: 'expose-loader?' + globalPrefix + '.ReactTooltip',
|
|
},
|
|
{
|
|
include: require.resolve('react'),
|
|
loader: 'expose-loader?' + globalPrefix + '.React',
|
|
},
|
|
{
|
|
include: require.resolve('react-dom'),
|
|
loader: 'expose-loader?' + globalPrefix + '.ReactDOM',
|
|
},
|
|
{
|
|
include: require.resolve('react-router-dom'),
|
|
use: 'expose-loader?' + globalPrefix + '.ReactRouter',
|
|
},
|
|
{
|
|
include: require.resolve('react-string-replace'),
|
|
loader: 'expose-loader?' + globalPrefix + '.ReactStringReplace',
|
|
},
|
|
{
|
|
include: path.resolve(__dirname, 'assets/js/src/hooks.js'),
|
|
use: 'expose-loader?' + globalPrefix + '.Hooks',
|
|
},
|
|
{
|
|
test: /listing.jsx/i,
|
|
use: [
|
|
'expose-loader?' + globalPrefix + '.Listing',
|
|
'babel-loader'
|
|
],
|
|
},
|
|
{
|
|
include: path.resolve(__dirname, 'assets/js/src/help-tooltip.jsx'),
|
|
use: [
|
|
'expose-loader?' + globalPrefix + '.HelpTooltip',
|
|
'babel-loader',
|
|
]
|
|
},
|
|
{
|
|
include: path.resolve(__dirname, 'assets/js/src/common/index.ts'),
|
|
use: [
|
|
'expose-loader?' + globalPrefix + '.Common',
|
|
'babel-loader',
|
|
]
|
|
},
|
|
{
|
|
include: /Blob.js$/,
|
|
loader: 'exports-loader?window.Blob',
|
|
},
|
|
{
|
|
test: /backbone.supermodel/,
|
|
loader: 'exports-loader?Backbone.SuperModel',
|
|
},
|
|
{
|
|
include: require.resolve('handlebars'),
|
|
loader: 'expose-loader?Handlebars',
|
|
},
|
|
{
|
|
include: require.resolve('velocity-animate'),
|
|
loader: 'imports-loader?jQuery=jquery',
|
|
},
|
|
{
|
|
include: require.resolve('classnames'),
|
|
use: [
|
|
'expose-loader?' + globalPrefix + '.ClassNames',
|
|
'babel-loader',
|
|
]
|
|
},
|
|
{
|
|
test: /node_modules\/tinymce/,
|
|
loader: 'string-replace-loader',
|
|
options: {
|
|
// prefix TinyMCE to avoid conflicts with other plugins
|
|
multiple: [
|
|
{
|
|
search: 'window\\.tinymce',
|
|
replace: 'window.mailpoetTinymce',
|
|
flags: 'g',
|
|
},
|
|
{
|
|
search: 'tinymce\\.util',
|
|
replace: 'window.mailpoetTinymce.util',
|
|
flags: 'g',
|
|
},
|
|
{
|
|
search: 'resolve\\(\'tinymce',
|
|
replace: 'resolve(\'mailpoetTinymce',
|
|
flags: 'g',
|
|
},
|
|
],
|
|
},
|
|
},
|
|
]
|
|
}
|
|
};
|
|
|
|
// Admin config
|
|
const adminConfig = {
|
|
name: 'admin',
|
|
entry: {
|
|
vendor: 'webpack_vendor_index.jsx',
|
|
mailpoet: 'webpack_mailpoet_index.jsx',
|
|
admin_vendor: [
|
|
'react',
|
|
'react-dom',
|
|
require.resolve('react-router-dom'),
|
|
'react-string-replace',
|
|
'prop-types',
|
|
'classnames',
|
|
'lodash',
|
|
'@emotion/react',
|
|
'@emotion/styled',
|
|
'help-tooltip.jsx',
|
|
'listing/listing.jsx',
|
|
'common/index.ts',
|
|
],
|
|
admin: 'webpack_admin_index.jsx',
|
|
newsletter_editor: 'newsletter_editor/webpack_index.jsx',
|
|
form_editor: 'form_editor/form_editor.jsx',
|
|
settings: 'settings/index.tsx'
|
|
},
|
|
plugins: [
|
|
...baseConfig.plugins,
|
|
|
|
new webpackCopyPlugin({
|
|
patterns: [
|
|
{
|
|
from: 'node_modules/tinymce/skins/ui/oxide',
|
|
to: 'skins/ui/oxide'
|
|
},
|
|
],
|
|
}),
|
|
],
|
|
optimization: {
|
|
runtimeChunk: {
|
|
name: 'vendor',
|
|
},
|
|
splitChunks: {
|
|
cacheGroups: {
|
|
chunks: 'all',
|
|
default: false,
|
|
vendors: false,
|
|
vendor: {
|
|
name: 'vendor',
|
|
chunks: (chunk) => chunk.name === 'vendor',
|
|
priority: 1,
|
|
enforce: true,
|
|
},
|
|
admin_vendor_chunk: {
|
|
name: 'admin_vendor_chunk',
|
|
test: (module, chunks) => {
|
|
// add all modules from 'admin_vendor' entrypoint
|
|
if (chunks.some((chunk) => chunk.name === 'admin_vendor')) {
|
|
return true;
|
|
}
|
|
|
|
// add admin/form_editor_legacy/newsletter_editor shared modules
|
|
const filteredChunks = chunks.filter((chunk) => {
|
|
return ['admin', 'newsletter_editor', 'form_editor', 'settings'].includes(chunk.name);
|
|
});
|
|
return filteredChunks.length > 1;
|
|
},
|
|
enforce: true,
|
|
chunks: (chunk) => ['admin_vendor', 'admin', 'newsletter_editor'].includes(chunk.name),
|
|
priority: 0,
|
|
},
|
|
}
|
|
}
|
|
},
|
|
externals: {
|
|
'jquery': 'jQuery',
|
|
}
|
|
};
|
|
|
|
// Public config
|
|
const publicConfig = {
|
|
name: 'public',
|
|
entry: {
|
|
public: 'webpack_public_index.jsx',
|
|
},
|
|
plugins: [
|
|
...baseConfig.plugins,
|
|
|
|
// replace MailPoet definition with a smaller version for public
|
|
new webpack.NormalModuleReplacementPlugin(
|
|
/mailpoet\.js/,
|
|
'./mailpoet_public.js'
|
|
),
|
|
],
|
|
externals: {
|
|
'jquery': 'jQuery'
|
|
}
|
|
};
|
|
|
|
// Migrator config
|
|
const migratorConfig = {
|
|
name: 'mp2migrator',
|
|
entry: {
|
|
mp2migrator: [
|
|
'mp2migrator.js'
|
|
]
|
|
},
|
|
externals: {
|
|
'jquery': 'jQuery',
|
|
'mailpoet': 'MailPoet'
|
|
}
|
|
};
|
|
|
|
// Newsletter Editor Tests Config
|
|
const testConfig = {
|
|
name: 'test',
|
|
entry: {
|
|
vendor: 'webpack_vendor_index.jsx',
|
|
testNewsletterEditor: [
|
|
'webpack_mailpoet_index.jsx',
|
|
'newsletter_editor/webpack_index.jsx',
|
|
|
|
'components/config.spec.js',
|
|
'components/content.spec.js',
|
|
'components/heading.spec.js',
|
|
'components/history.spec.js',
|
|
'components/save.spec.js',
|
|
'components/sidebar.spec.js',
|
|
'components/styles.spec.js',
|
|
'components/communication.spec.js',
|
|
|
|
'blocks/automatedLatestContentLayout.spec.js',
|
|
'blocks/button.spec.js',
|
|
'blocks/container.spec.js',
|
|
'blocks/divider.spec.js',
|
|
'blocks/footer.spec.js',
|
|
'blocks/header.spec.js',
|
|
'blocks/image.spec.js',
|
|
'blocks/posts.spec.js',
|
|
'blocks/products.spec.js',
|
|
'blocks/social.spec.js',
|
|
'blocks/spacer.spec.js',
|
|
'blocks/text.spec.js',
|
|
],
|
|
},
|
|
output: {
|
|
path: path.join(__dirname, 'tests/javascript_newsletter_editor/testBundles'),
|
|
filename: '[name].js',
|
|
},
|
|
plugins: [
|
|
...baseConfig.plugins,
|
|
|
|
// replace MailPoet definition with a smaller version for public
|
|
new webpack.NormalModuleReplacementPlugin(
|
|
/mailpoet\.js/,
|
|
'./mailpoet_tests.js'
|
|
),
|
|
],
|
|
resolve: {
|
|
modules: [
|
|
'node_modules',
|
|
'assets/js/src',
|
|
'tests/javascript_newsletter_editor/newsletter_editor'
|
|
],
|
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
|
alias: {
|
|
'sticky-kit': 'vendor/jquery.sticky-kit.js',
|
|
'backbone.marionette': 'backbone.marionette/lib/backbone.marionette',
|
|
'backbone.supermodel$': 'backbone.supermodel/build/backbone.supermodel.js',
|
|
'blob$': 'blob-tmp/Blob.js',
|
|
'wp-js-hooks': path.resolve(__dirname, 'assets/js/src/hooks.js'),
|
|
},
|
|
},
|
|
externals: {
|
|
'jquery': 'jQuery',
|
|
'interact': 'interact',
|
|
'spectrum': 'spectrum',
|
|
},
|
|
};
|
|
|
|
// Form preview config
|
|
const formPreviewConfig = {
|
|
name: 'form_preview',
|
|
entry: {
|
|
form_preview: 'form_editor/form_preview.ts',
|
|
},
|
|
externals: {
|
|
'jquery': 'jQuery',
|
|
},
|
|
};
|
|
|
|
// Block config
|
|
const postEditorBlock = {
|
|
name: 'post_editor_block',
|
|
entry: {
|
|
post_editor_block: 'post_editor_block/blocks.jsx',
|
|
},
|
|
};
|
|
|
|
module.exports = [adminConfig, publicConfig, migratorConfig, formPreviewConfig, testConfig, postEditorBlock].map((config) => {
|
|
if (config.name !== 'test') {
|
|
config.plugins = config.plugins || [];
|
|
config.plugins.push(
|
|
new webpackManifestPlugin({
|
|
// create single manifest file for all Webpack configs
|
|
seed: manifestSeed,
|
|
})
|
|
);
|
|
}
|
|
// Clean output paths before build
|
|
if (config.output && config.output.path) {
|
|
del.sync([path.resolve(config.output.path, '**/*')]);
|
|
}
|
|
return Object.assign({}, baseConfig, config);
|
|
});
|