The path is required in css module which we use for parsing custom css string in the form editor. We don't use functionality which is dependent on nodejs path module so we can use "dummy" module. Alternatively we could install a polyfill for brower for the path module but it would increase a package size with functions we don't use. [MAILPOET-3214]
401 lines
11 KiB
JavaScript
401 lines
11 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',
|
|
],
|
|
fallback: {
|
|
fs: false,
|
|
path: false, // path is used in css module, but we don't use the functionality which requires it
|
|
},
|
|
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',
|
|
},
|
|
},
|
|
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'),
|
|
},
|
|
fallback: {
|
|
fs: false,
|
|
},
|
|
},
|
|
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);
|
|
});
|