Files
piratepoet/webpack.config.js
Rostislav Wolny dac4fb5dd0 Replace clean-webpack-plugin with initial cleanup in Robofile
We need to share the same output path (assets/build/js) in more configs
in order to generate a common manifest.json file.
The cleanup plugin and also build-in output.clean setting do the cleanup on emit
and that causes that they delete files we want to keep.
Using different output paths solves the problem with cleanup but it causes that we generate a bunch of manifest.json files
instead of one.
As simplest workaround I chose cleaning the output directory before we trigger the Webpack build in the Robofile.
[MAILPOET-3214]
2021-09-22 11:56:49 +02:00

416 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 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: {
publicPath: '', // This is needed to have correct names in WebpackManifestPlugin
path: path.join(__dirname, 'assets/dist/js'),
filename: (PRODUCTION_ENV) ? '[name].[fullhash:8].js' : '[name].js',
chunkFilename: (PRODUCTION_ENV) ? '[name].[fullhash:8].chunk.js' : '[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',
},
},
plugins: [],
module: {
noParse: /node_modules\/lodash\/lodash\.js/,
rules: [
{
test: /\.(j|t)sx?$/,
exclude: /(node_modules|src\/vendor)/,
loader: 'babel-loader',
},
{
include: require.resolve('underscore'),
loader: 'expose-loader',
options: {
exposes: '_',
},
},
{
include: require.resolve('react-tooltip'),
loader: 'expose-loader',
options: {
exposes: globalPrefix + '.ReactTooltip',
},
},
{
include: require.resolve('react'),
loader: 'expose-loader',
options: {
exposes: globalPrefix + '.React',
},
},
{
include: require.resolve('react-dom'),
loader: 'expose-loader',
options: {
exposes: globalPrefix + '.ReactDOM',
},
},
{
include: require.resolve('react-router-dom'),
loader: 'expose-loader',
options: {
exposes: globalPrefix + '.ReactRouter',
},
},
{
include: require.resolve('react-string-replace'),
loader: 'expose-loader',
options: {
exposes: globalPrefix + '.ReactStringReplace',
},
},
{
include: path.resolve(__dirname, 'assets/js/src/hooks.js'),
loader: 'expose-loader',
options: {
exposes: {
globalName: globalPrefix + '.Hooks',
override: true,
},
},
},
{
test: /listing.jsx/i,
use: [
{
loader: 'expose-loader',
options: {
exposes: globalPrefix + '.Listing',
},
},
'babel-loader'
],
},
{
include: path.resolve(__dirname, 'assets/js/src/help-tooltip.jsx'),
use: [
{
loader: 'expose-loader',
options: {
exposes: globalPrefix + '.HelpTooltip',
},
},
'babel-loader',
]
},
{
include: path.resolve(__dirname, 'assets/js/src/common/index.ts'),
use: [
{
loader: 'expose-loader',
options: {
exposes: globalPrefix + '.Common',
},
},
'babel-loader',
]
},
{
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',
},
},
},
{
include: require.resolve('classnames'),
use: [
{
loader: 'expose-loader',
options: {
exposes: 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 contains libraries shared between free and premium plugin
admin_vendor: [
'react',
'react-dom',
require.resolve('react-router-dom'),
'react-string-replace',
'prop-types',
'classnames',
'lodash',
'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'
},
],
}),
new webpack.ProvidePlugin({
process: 'process/browser',
}),
],
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\.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: {
'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',
},
};
module.exports = [publicConfig, adminConfig, migratorConfig, formPreviewConfig, testConfig, postEditorBlock].map((config, index) => {
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);
});