foreman/config/webpack.config.js @ develop
caa81e6f | Ohad Levy | /* eslint-disable no-var*/
|
|
e2a57bfe | Tomer Brisker | 'use strict';
|
|
var path = require('path');
|
|||
var webpack = require('webpack');
|
|||
89c61045 | MariaAga | const dotenv = require('dotenv');
|
|
dotenv.config();
|
|||
074471af | Amir Fefer | var ForemanVendorPlugin = require('@theforeman/vendor')
|
|
.WebpackForemanVendorPlugin;
|
|||
var StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin;
|
|||
123df74a | Ron Lavi | var vendorEntry = require('./webpack.vendor');
|
|
bc486dd6 | Tomas Strachota | var fs = require('fs');
|
|
89c61045 | MariaAga | const { ModuleFederationPlugin } = require('webpack').container;
|
|
var pluginUtils = require('../script/plugin_webpack_directories');
|
|||
4550a0c1 | MariaAga | var { generateExportsFile }= require('../webpack/assets/javascripts/exportAll');
|
|
6cafc684 | Evgeni Golov | var CompressionPlugin = require('compression-webpack-plugin');
|
|
bc486dd6 | Tomas Strachota | ||
89c61045 | MariaAga | class AddRuntimeRequirement {
|
|
// to avoid "webpackRequire.l is not a function" error
|
|||
// enables use of webpack require inside promise new promise
|
|||
apply(compiler) {
|
|||
compiler.hooks.compilation.tap('AddRuntimeRequirement', compilation => {
|
|||
const { RuntimeGlobals } = compiler.webpack;
|
|||
compilation.hooks.additionalModuleRuntimeRequirements.tap(
|
|||
'AddRuntimeRequirement',
|
|||
(module, set) => {
|
|||
set.add(RuntimeGlobals.loadScript);
|
|||
}
|
|||
);
|
|||
});
|
|||
}
|
|||
}
|
|||
5f911c19 | Tomas Strachota | ||
123df74a | Ron Lavi | const supportedLocales = () => {
|
|
const localeDir = path.join(__dirname, '..', 'locale');
|
|||
// Find all files in ./locale/*
|
|||
const localesFiles = fs.readdirSync(localeDir);
|
|||
// Return only folders
|
|||
return localesFiles.filter(f =>
|
|||
fs.statSync(path.join(localeDir, f)).isDirectory()
|
|||
);
|
|||
};
|
|||
const supportedLanguages = () => {
|
|||
// Extract extract languages from the language tags (strip off dialects)
|
|||
return [...new Set(supportedLocales().map(d => d.split('_')[0]))];
|
|||
};
|
|||
89c61045 | MariaAga | const supportedLanguagesRE = new RegExp(
|
|
`/(${supportedLanguages().join('|')})$`
|
|||
);
|
|||
5f911c19 | Tomas Strachota | ||
89c61045 | MariaAga | const commonConfig = function() {
|
|
b0ee9fd6 | Eric D. Helms | var production =
|
|
process.env.RAILS_ENV === 'production' ||
|
|||
process.env.NODE_ENV === 'production';
|
|||
89c61045 | MariaAga | const mode = production ? 'production' : 'development';
|
|
const config = {};
|
|||
if (production) {
|
|||
config.devtool = 'source-map';
|
|||
config.optimization = {
|
|||
moduleIds: 'named',
|
|||
splitChunks: false,
|
|||
};
|
|||
b0ee9fd6 | Eric D. Helms | } else {
|
|
89c61045 | MariaAga | config.devtool = 'inline-source-map';
|
|
config.optimization = {
|
|||
splitChunks: false,
|
|||
};
|
|||
b0ee9fd6 | Eric D. Helms | }
|
|
89c61045 | MariaAga | return {
|
|
...config,
|
|||
mode,
|
|||
b0ee9fd6 | Eric D. Helms | resolve: {
|
|
89c61045 | MariaAga | fallback: {
|
|
path: require.resolve('path-browserify'),
|
|||
os: require.resolve('os-browserify'),
|
|||
},
|
|||
alias: {
|
|||
foremanReact: path.join(
|
|||
__dirname,
|
|||
'../webpack/assets/javascripts/react_app'
|
|||
),
|
|||
},
|
|||
},
|
|||
resolveLoader: {
|
|||
modules: [path.resolve(__dirname, '..', 'node_modules')],
|
|||
b0ee9fd6 | Eric D. Helms | },
|
|
module: {
|
|||
rules: [
|
|||
{
|
|||
test: /\.js$/,
|
|||
b674b25e | Gilad Lekner | /* Include novnc, unidiff in webpack, transpiling is needed for phantomjs (which does not support ES6) to run tests
|
|
unidiff can be removed once https://github.com/mvoss9000/unidiff/pull/1 is merged */
|
|||
exclude: /node_modules(?!\/(@novnc|unidiff))/,
|
|||
b0ee9fd6 | Eric D. Helms | loader: 'babel-loader',
|
|
1944da62 | Tomer Brisker | options: {
|
|
presets: [require.resolve('@theforeman/builder/babel')],
|
|||
},
|
|||
b0ee9fd6 | Eric D. Helms | },
|
|
{
|
|||
8a80ef08 | Fellipe Henrique | test: /\.(png|gif|svg)$/,
|
|
89c61045 | MariaAga | type: 'asset',
|
|
parser: {
|
|||
dataUrlCondition: {
|
|||
maxSize: 32767,
|
|||
},
|
|||
},
|
|||
0aebf308 | Ondrej Prazak | },
|
|
{
|
|||
test: /\.(graphql|gql)$/,
|
|||
exclude: /node_modules/,
|
|||
loader: 'graphql-tag/loader',
|
|||
074471af | Amir Fefer | },
|
|
],
|
|||
b0ee9fd6 | Eric D. Helms | },
|
|
plugins: [
|
|||
074471af | Amir Fefer | new ForemanVendorPlugin({
|
|
89c61045 | MariaAga | mode,
|
|
8d46433b | Amir Fefer | }),
|
|
b0ee9fd6 | Eric D. Helms | new webpack.DefinePlugin({
|
|
'process.env': {
|
|||
89c61045 | MariaAga | NODE_ENV: JSON.stringify(mode),
|
|
10959277 | Gilad Lekner | NOTIFICATIONS_POLLING: process.env.NOTIFICATIONS_POLLING,
|
|
074471af | Amir Fefer | REDUX_LOGGER: process.env.REDUX_LOGGER,
|
|
},
|
|||
b0ee9fd6 | Eric D. Helms | }),
|
|
123df74a | Ron Lavi | // limit locales from intl only to supported ones
|
|
new webpack.ContextReplacementPlugin(
|
|||
/intl\/locale-data\/jsonp/,
|
|||
supportedLanguagesRE
|
|||
),
|
|||
// limit locales from react-intl only to supported ones
|
|||
new webpack.ContextReplacementPlugin(
|
|||
/react-intl\/locale-data/,
|
|||
supportedLanguagesRE
|
|||
),
|
|||
89c61045 | MariaAga | new AddRuntimeRequirement(),
|
|
6cafc684 | Evgeni Golov | new CompressionPlugin(),
|
|
123df74a | Ron Lavi | ],
|
|
89c61045 | MariaAga | stats: process.env.WEBPACK_STATS || 'normal',
|
|
e2a57bfe | Tomer Brisker | };
|
|
89c61045 | MariaAga | };
|
|
e2a57bfe | Tomer Brisker | ||
89c61045 | MariaAga | const coreConfig = function() {
|
|
var config = commonConfig();
|
|||
var manifestFilename = 'manifest.json';
|
|||
var bundleEntry = path.join(
|
|||
__dirname,
|
|||
'..',
|
|||
'webpack/assets/javascripts/bundle.js'
|
|||
123df74a | Ron Lavi | );
|
|
89c61045 | MariaAga | config.context = path.resolve(__dirname, '..');
|
|
config.entry = {
|
|||
43a7a4f2 | Evgeni Golov | bundle: { import: bundleEntry, dependOn: ['vendor', 'reactExports'] },
|
|
89c61045 | MariaAga | vendor: vendorEntry,
|
|
4550a0c1 | MariaAga | reactExports: path.join(
|
|
__dirname,
|
|||
'..',
|
|||
'webpack/assets/javascripts/all_react_app_exports.js'
|
|||
),
|
|||
89c61045 | MariaAga | };
|
|
config.output = {
|
|||
path: path.join(__dirname, '..', 'public', 'webpack'),
|
|||
publicPath: '/webpack/',
|
|||
4550a0c1 | MariaAga | library: {
|
|
name: ['TheForeman', '[name]'],
|
|||
type: 'var',
|
|||
},
|
|||
89c61045 | MariaAga | };
|
|
var plugins = config.plugins;
|
|||
123df74a | Ron Lavi | ||
89c61045 | MariaAga | plugins.push(
|
|
new ModuleFederationPlugin({
|
|||
name: 'foremanReact',
|
|||
})
|
|||
);
|
|||
plugins.push(
|
|||
new StatsWriterPlugin({
|
|||
filename: manifestFilename,
|
|||
})
|
|||
);
|
|||
config.plugins = plugins;
|
|||
var rules = config.module.rules;
|
|||
rules.push({
|
|||
test: /\.(sa|sc|c)ss$/,
|
|||
use: [
|
|||
{
|
|||
loader: 'style-loader',
|
|||
options: {
|
|||
injectType: 'singletonStyleTag',
|
|||
06190391 | MariaAga | attributes: { id: 'foreman_core_css' },
|
|
b0ee9fd6 | Eric D. Helms | },
|
|
89c61045 | MariaAga | },
|
|
'css-loader',
|
|||
'sass-loader',
|
|||
],
|
|||
});
|
|||
config.module.rules = rules;
|
|||
return config;
|
|||
};
|
|||
const pluginConfig = function(plugin) {
|
|||
const pluginRoot = plugin.root;
|
|||
const pluginName = plugin.name.replace('-', '_'); // module federation doesnt like -
|
|||
var config = commonConfig();
|
|||
config.context = path.join(pluginRoot, 'webpack');
|
|||
config.entry = {};
|
|||
4550a0c1 | MariaAga | ||
function convertImportStatement(importStatement) {
|
|||
const importPath = importStatement;
|
|||
const importPathParts = importPath.split('/');
|
|||
const newImportName = importPathParts.slice(1).join('_');
|
|||
return newImportName;
|
|||
}
|
|||
config.externals = function({ request }, callback) {
|
|||
if (/^foremanReact(\/.*)?$/.test(request)) {
|
|||
const prefix = 'var TheForeman.reactExports.';
|
|||
const newPath = prefix + convertImportStatement(request.substring('foremanReact'.length));
|
|||
return callback(null, newPath);
|
|||
}
|
|||
return callback();
|
|||
};
|
|||
89c61045 | MariaAga | var pluginEntries = {
|
|
'./index': path.resolve(pluginRoot, 'webpack', 'index'),
|
|||
};
|
|||
plugin.entries.filter(Boolean).forEach(entry => {
|
|||
pluginEntries[`./${entry}_index`] = path.resolve(
|
|||
pluginRoot,
|
|||
'webpack',
|
|||
`${entry}_index`
|
|||
b0ee9fd6 | Eric D. Helms | );
|
|
89c61045 | MariaAga | });
|
|
if (config.mode == 'production') {
|
|||
var outputPath = path.join(pluginRoot, 'public', 'webpack', pluginName);
|
|||
b0ee9fd6 | Eric D. Helms | } else {
|
|
89c61045 | MariaAga | var outputPath = path.join(
|
|
__dirname,
|
|||
'..',
|
|||
'public',
|
|||
'webpack',
|
|||
pluginName
|
|||
b0ee9fd6 | Eric D. Helms | );
|
|
}
|
|||
89c61045 | MariaAga | config.output = {
|
|
path: outputPath,
|
|||
publicPath: '/webpack/' + pluginName + '/',
|
|||
uniqueName: pluginName,
|
|||
};
|
|||
var configModules = config.resolve.modules || [];
|
|||
// make webpack to resolve modules from core first
|
|||
configModules.unshift(path.resolve(__dirname, '..', 'node_modules'));
|
|||
// add plugin's node_modules to the reslver list
|
|||
configModules.push(path.resolve(pluginRoot, 'node_modules'));
|
|||
84f33a33 | Evgeni Golov | configModules.push('node_modules/');
|
|
89c61045 | MariaAga | config.resolve.modules = configModules;
|
|
//get the list of webpack plugins
|
|||
var plugins = config.plugins;
|
|||
4550a0c1 | MariaAga | ||
89c61045 | MariaAga | plugins.push(
|
|
new ModuleFederationPlugin({
|
|||
name: pluginName,
|
|||
filename: pluginName + '_remoteEntry.js',
|
|||
exposes: pluginEntries,
|
|||
})
|
|||
);
|
|||
config.plugins = plugins;
|
|||
var rules = config.module.rules;
|
|||
rules.push({
|
|||
test: /\.(sa|sc|c)ss$/,
|
|||
use: [
|
|||
{
|
|||
loader: 'style-loader',
|
|||
options: {
|
|||
injectType: 'singletonStyleTag',
|
|||
06190391 | MariaAga | attributes: { id: `${pluginName}_css` },
|
|
89c61045 | MariaAga | },
|
|
},
|
|||
'css-loader',
|
|||
'sass-loader',
|
|||
],
|
|||
});
|
|||
config.module.rules = rules;
|
|||
b0ee9fd6 | Eric D. Helms | ||
return config;
|
|||
074471af | Amir Fefer | };
|
|
89c61045 | MariaAga | ||
module.exports = function(env, argv) {
|
|||
4550a0c1 | MariaAga | generateExportsFile();
|
|
89c61045 | MariaAga | const { pluginName } = env;
|
|
var pluginsDirs = pluginUtils.getPluginDirs('pipe');
|
|||
var pluginsInfo = {};
|
|||
var pluginsConfigEnv = [];
|
|||
var pluginDirKeys = Object.keys(pluginsDirs.plugins);
|
|||
if (pluginName) {
|
|||
pluginDirKeys = pluginDirKeys.filter(key => key.includes(pluginName));
|
|||
}
|
|||
pluginDirKeys.forEach(pluginDirKey => {
|
|||
const parts = pluginDirKey.split(':');
|
|||
const name = parts[0];
|
|||
const entry = parts[1];
|
|||
if (pluginsInfo[name]) {
|
|||
pluginsInfo[name].entries.push(entry);
|
|||
} else {
|
|||
pluginsInfo[name] = {
|
|||
name,
|
|||
entries: [entry],
|
|||
root: pluginsDirs.plugins[pluginDirKey].root,
|
|||
};
|
|||
}
|
|||
if (!pluginDirKey.includes(':')) {
|
|||
const keysWithExtras = pluginDirKeys.filter(key =>
|
|||
key.includes(pluginDirKey + ':')
|
|||
);
|
|||
// for example: {global: true, routes: true}
|
|||
const pluginExtras = keysWithExtras.map(key => ({
|
|||
[key.split(':')[1]]: true,
|
|||
}));
|
|||
pluginsConfigEnv.push({
|
|||
plugin: {
|
|||
...pluginExtras,
|
|||
name: pluginDirKey,
|
|||
root: pluginsDirs.plugins[pluginDirKey].root,
|
|||
},
|
|||
});
|
|||
}
|
|||
});
|
|||
let configs = [];
|
|||
const pluginsInfoValues = Object.values(pluginsInfo);
|
|||
if (pluginsInfoValues.length > 0) {
|
|||
configs = pluginsInfoValues.map(plugin => pluginConfig(plugin));
|
|||
}
|
|||
if (pluginName) return configs;
|
|||
return [coreConfig(env, argv), ...configs];
|
|||
};
|