Using inject-loader requires first transpiling modules to CommonJS. Previously, we were doing this via parametrized imports, but these are no longer supported. Instead, we can fix this by using CommonJS preset in Webpack config. [MAILPOET-5491]
552 lines
14 KiB
JavaScript
552 lines
14 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 wpScriptConfig = require('@wordpress/scripts/config/webpack.config');
|
|
const DependencyExtractionWebpackPlugin = require('@wordpress/dependency-extraction-webpack-plugin');
|
|
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
|
|
|
const globalPrefix = 'MailPoetLib';
|
|
const PRODUCTION_ENV = process.env.NODE_ENV === 'production';
|
|
const manifestSeed = {};
|
|
|
|
const stats = {
|
|
preset: 'minimal',
|
|
assets: false,
|
|
modules: false,
|
|
chunks: true,
|
|
};
|
|
|
|
// Base config
|
|
const baseConfig = {
|
|
stats,
|
|
ignoreWarnings: [
|
|
(warnings) => {
|
|
// Todo: remove this if statement per MAILPOET-4544
|
|
if (
|
|
warnings &&
|
|
[
|
|
'AssetsOverSizeLimitWarning',
|
|
'EntrypointsOverSizeLimitWarning',
|
|
'NoAsyncChunksWarning',
|
|
].includes(warnings.name)
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
// only show warnings when watching
|
|
if (process.env.WEBPACK_WATCH || process.argv.includes('--watch')) {
|
|
return false;
|
|
}
|
|
|
|
if (warnings) {
|
|
// eslint-disable-next-line
|
|
console.warn(warnings);
|
|
process.emitWarning(warnings); // emit for listeners
|
|
process.exit(1);
|
|
}
|
|
|
|
return false;
|
|
},
|
|
],
|
|
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: {
|
|
publicPath: '', // This is needed to have correct names in WebpackManifestPlugin
|
|
path: path.join(__dirname, 'assets/dist/js'),
|
|
filename: '[name].js',
|
|
chunkFilename: '[name].chunk.js',
|
|
},
|
|
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',
|
|
chai: 'chai/index.js',
|
|
papaparse: 'papaparse/papaparse.min.js',
|
|
html2canvas: 'html2canvas/dist/html2canvas.js',
|
|
asyncqueue: 'vendor/jquery.asyncqueue.js',
|
|
'@woocommerce/settings': path.resolve(
|
|
__dirname,
|
|
'assets/js/src/mock-woocommerce-settings.ts',
|
|
),
|
|
'@automattic/tour-kit': path.resolve(
|
|
__dirname,
|
|
'assets/js/src/mock-empty-module.js',
|
|
),
|
|
},
|
|
},
|
|
plugins: PRODUCTION_ENV ? [] : [new ForkTsCheckerWebpackPlugin()],
|
|
module: {
|
|
noParse: /node_modules\/lodash\/lodash\.js/,
|
|
rules: [
|
|
{
|
|
test: /\.(j|t)sx?$/,
|
|
exclude: /(node_modules|src\/vendor)/,
|
|
loader: 'babel-loader',
|
|
resolve: {
|
|
fullySpecified: false,
|
|
},
|
|
},
|
|
{
|
|
include: path.resolve(
|
|
__dirname,
|
|
'assets/js/src/webpack-admin-expose.js',
|
|
),
|
|
loader: 'expose-loader',
|
|
options: { exposes: globalPrefix },
|
|
},
|
|
{
|
|
include: require.resolve('underscore'),
|
|
loader: 'expose-loader',
|
|
options: {
|
|
exposes: '_',
|
|
},
|
|
},
|
|
{
|
|
include: /Blob.js$/,
|
|
loader: 'exports-loader',
|
|
options: {
|
|
exports: 'default window.Blob',
|
|
},
|
|
},
|
|
{
|
|
test: /backbone.supermodel/,
|
|
loader: 'exports-loader',
|
|
options: {
|
|
exports: 'default Backbone.SuperModel',
|
|
},
|
|
},
|
|
{
|
|
include: require.resolve('velocity-animate'),
|
|
loader: 'imports-loader',
|
|
options: {
|
|
imports: {
|
|
name: 'jQuery',
|
|
moduleName: 'jquery',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
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: 'window\\.tinyMCE',
|
|
replace: 'window.mailpoetTinyMCE',
|
|
flags: 'g',
|
|
},
|
|
{
|
|
search: 'tinymce\\.util',
|
|
replace: 'window.mailpoetTinymce.util',
|
|
flags: 'g',
|
|
},
|
|
{
|
|
search: "resolve\\('tinymce",
|
|
replace: "resolve('mailpoetTinymce",
|
|
flags: 'g',
|
|
},
|
|
{
|
|
search: 'tinymce.Resource',
|
|
replace: 'mailpoetTinymce.Resource',
|
|
flags: 'g',
|
|
},
|
|
],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
};
|
|
|
|
// Admin config
|
|
const adminConfig = {
|
|
name: 'admin',
|
|
entry: {
|
|
vendor: 'webpack-vendor-index.jsx',
|
|
mailpoet: 'webpack-mailpoet-index.jsx',
|
|
admin_vendor: ['prop-types', 'lodash', 'webpack-admin-expose.js'], // libraries shared between free and premium plugin
|
|
admin: 'webpack-admin-index.tsx',
|
|
automation: 'automation/automation.tsx',
|
|
automation_editor: 'automation/editor/index.tsx',
|
|
automation_analytics:
|
|
'automation/integrations/mailpoet/analytics/index.tsx',
|
|
automation_templates: 'automation/templates/index.tsx',
|
|
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: 'single',
|
|
splitChunks: {
|
|
cacheGroups: {
|
|
commons: {
|
|
name: 'commons',
|
|
chunks: 'initial',
|
|
minChunks: 2,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
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\.ts/,
|
|
'./mailpoet-public.ts',
|
|
),
|
|
],
|
|
externals: {
|
|
jquery: 'jQuery',
|
|
},
|
|
};
|
|
|
|
// 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/automated-latest-content-layout.spec.js',
|
|
'blocks/button.spec.js',
|
|
'blocks/container.spec.js',
|
|
'blocks/coupon.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',
|
|
],
|
|
},
|
|
module: {
|
|
...baseConfig.module,
|
|
rules: [
|
|
{
|
|
test: /\.(j|t)sx?$/,
|
|
exclude: /(node_modules|src\/vendor)/,
|
|
loader: 'babel-loader',
|
|
resolve: { fullySpecified: false },
|
|
options: {
|
|
presets: [['@babel/preset-env', { modules: 'commonjs' }]],
|
|
},
|
|
},
|
|
...baseConfig.module.rules,
|
|
],
|
|
},
|
|
output: {
|
|
path: path.join(
|
|
__dirname,
|
|
'tests/javascript-newsletter-editor/testBundles',
|
|
),
|
|
filename: '[name].js',
|
|
},
|
|
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: {
|
|
handlebars: 'handlebars/dist/handlebars.js',
|
|
'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',
|
|
},
|
|
};
|
|
|
|
// Marketing Optin config
|
|
function requestToExternal(request) {
|
|
const wcDepMap = {
|
|
'@woocommerce/settings': ['wc', 'wcSettings'],
|
|
'@woocommerce/blocks-checkout': ['wc', 'blocksCheckout'],
|
|
};
|
|
if (wcDepMap[request]) {
|
|
return wcDepMap[request];
|
|
}
|
|
// DependencyExtractionWebpackPlugin has native handling for @wordpress/*
|
|
// packages, for that handling to kick in, we must not return anything from
|
|
// function.
|
|
/* eslint-disable-next-line consistent-return, no-useless-return */
|
|
return;
|
|
}
|
|
|
|
function requestToHandle(request) {
|
|
const wcHandleMap = {
|
|
'@woocommerce/settings': 'wc-settings',
|
|
'@woocommerce/blocks-checkout': 'wc-blocks-checkout',
|
|
};
|
|
if (wcHandleMap[request]) {
|
|
return wcHandleMap[request];
|
|
}
|
|
// DependencyExtractionWebpackPlugin has native handling for @wordpress/*
|
|
// packages, for that handling to kick in, we must not return anything from
|
|
// function.
|
|
/* eslint-disable-next-line consistent-return, no-useless-return */
|
|
return;
|
|
}
|
|
const marketingOptinBlock = Object.assign({}, wpScriptConfig, {
|
|
stats,
|
|
name: 'marketing_optin_block',
|
|
entry: {
|
|
'marketing-optin-block': '/assets/js/src/marketing-optin-block/index.tsx',
|
|
'marketing-optin-block-frontend':
|
|
'/assets/js/src/marketing-optin-block/frontend.ts',
|
|
},
|
|
output: {
|
|
filename: '[name].js',
|
|
path: path.join(__dirname, 'assets/dist/js/marketing-optin-block'),
|
|
},
|
|
module: Object.assign({}, wpScriptConfig.module, {
|
|
rules: [
|
|
...wpScriptConfig.module.rules,
|
|
{
|
|
test: /\.(t|j)sx?$/,
|
|
exclude: /node_modules/,
|
|
use: {
|
|
loader: 'babel-loader?cacheDirectory',
|
|
options: {
|
|
presets: ['@wordpress/babel-preset-default'],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
}),
|
|
resolve: {
|
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
|
},
|
|
// use only needed plugins from wpScriptConfig and add the custom ones
|
|
plugins: [
|
|
...wpScriptConfig.plugins.filter(
|
|
(plugin) =>
|
|
plugin.constructor.pluginName === 'mini-css-extract-plugin' ||
|
|
plugin.constructor.name === 'CleanWebpackPlugin',
|
|
),
|
|
new DependencyExtractionWebpackPlugin({
|
|
injectPolyfill: true,
|
|
requestToExternal,
|
|
requestToHandle,
|
|
}),
|
|
new WebpackCopyPlugin({
|
|
patterns: [
|
|
{
|
|
from: 'assets/js/src/marketing-optin-block/block.json',
|
|
to: 'block.json',
|
|
},
|
|
],
|
|
}),
|
|
],
|
|
});
|
|
|
|
const emailEditorBlocks = Object.assign({}, wpScriptConfig, {
|
|
name: 'email-editor-blocks',
|
|
entry: {
|
|
'powered-by-mailpoet-block':
|
|
'/assets/js/src/email-editor/blocks/powered-by-mailpoet/block.tsx',
|
|
},
|
|
output: {
|
|
filename: '[name].js',
|
|
path: path.join(__dirname, 'assets/dist/js/email-editor-blocks'),
|
|
},
|
|
module: Object.assign({}, wpScriptConfig.module, {
|
|
rules: [
|
|
...wpScriptConfig.module.rules,
|
|
{
|
|
test: /\.(t|j)sx?$/,
|
|
exclude: /node_modules/,
|
|
use: {
|
|
loader: 'babel-loader?cacheDirectory',
|
|
options: {
|
|
presets: ['@wordpress/babel-preset-default'],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
}),
|
|
resolve: {
|
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
|
},
|
|
// use only needed plugins from wpScriptConfig and add the custom ones
|
|
plugins: [
|
|
...wpScriptConfig.plugins.filter(
|
|
(plugin) =>
|
|
plugin.constructor.pluginName === 'mini-css-extract-plugin' ||
|
|
plugin.constructor.name === 'CleanWebpackPlugin',
|
|
),
|
|
new DependencyExtractionWebpackPlugin({
|
|
injectPolyfill: true,
|
|
requestToExternal,
|
|
requestToHandle,
|
|
}),
|
|
],
|
|
});
|
|
|
|
const emailEditorCustom = Object.assign({}, wpScriptConfig, {
|
|
name: 'email_editor',
|
|
entry: {
|
|
email_editor: 'email-editor/index.ts',
|
|
},
|
|
output: {
|
|
filename: '[name].js',
|
|
path: path.join(__dirname, 'assets/dist/js/email-editor'),
|
|
},
|
|
resolve: {
|
|
...wpScriptConfig.resolve,
|
|
modules: ['node_modules', 'assets/js/src'],
|
|
},
|
|
plugins: PRODUCTION_ENV
|
|
? wpScriptConfig.plugins
|
|
: [...wpScriptConfig.plugins, new ForkTsCheckerWebpackPlugin()],
|
|
});
|
|
|
|
const configs = [
|
|
publicConfig,
|
|
adminConfig,
|
|
emailEditorCustom,
|
|
formPreviewConfig,
|
|
postEditorBlock,
|
|
marketingOptinBlock,
|
|
emailEditorBlocks,
|
|
];
|
|
|
|
module.exports = (env) => {
|
|
// Include tests build only if requested
|
|
if (env && env.BUILD_TESTS === 'build') {
|
|
configs.push(testConfig);
|
|
}
|
|
return configs.map((conf) => {
|
|
const config = Object.assign({}, conf);
|
|
if (
|
|
config.name === 'marketing_optin_block' ||
|
|
config.name === 'email_editor'
|
|
) {
|
|
return config;
|
|
}
|
|
if (config.name !== 'test') {
|
|
config.plugins = config.plugins || [];
|
|
config.plugins.push(
|
|
new WebpackManifestPlugin({
|
|
// create single manifest file for all Webpack configs
|
|
seed: manifestSeed,
|
|
}),
|
|
);
|
|
}
|
|
return Object.assign({}, baseConfig, config);
|
|
});
|
|
};
|