Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Procfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@
# If you wish to use a different server then the default, use e.g. `export RAILS_STARTUP='puma -w 3 -p 3000 --preload'`
rails: [ -n "$RAILS_STARTUP" ] && env PRY_WARNING=1 $RAILS_STARTUP || [ -n "$BIND" ] && bin/rails server -b $BIND || env PRY_WARNING=1 bin/rails server

# you can use WEBPACK_OPTS to customize webpack server, e.g. 'WEBPACK_OPTS=--progress' foreman start '
# filter out webpack options that are commonly used but not supported by webpack 5 and not needed in the new configutation as webpack is not run as a server anymore
webpack: FILTERED_WEBPACK_OPTS=$(echo $WEBPACK_OPTS | sed -e 's/--key [^ ]*//g' -e 's/--public [^ ]*//g' -e 's/--https [^ ]*//g' -e 's/--cert [^ ]*//g' -e 's/--cacert [^ ]*//g' -e 's/--host [^ ]*//g') && [ -n "$NODE_ENV" ] && npx webpack --config config/webpack.config.js --watch $FILTERED_WEBPACK_OPTS || env NODE_ENV=development npx webpack --config config/webpack.config.js --watch $FILTERED_WEBPACK_OPTS
webpack: env NODE_OPTIONS=${NODE_OPTIONS:---max-old-space-size=8096} NODE_ENV=${NODE_ENV:-development} npx webpack --config config/webpack.config.js --watch $WEBPACK_OPTS
5 changes: 0 additions & 5 deletions app/helpers/reactjs_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ def get_webpack_chunk(name, extension)
data['assetsByChunkName'][name]&.find { |value| value.end_with?(".#{extension}") }
end

def get_webpack_foreman_vendor_js
foreman_vendor_js = get_webpack_chunk('foreman-vendor', 'js')
javascript_include_tag("/webpack/#{foreman_vendor_js}")
end

def get_webpack_foreman_vendor_css
foreman_vendor_css = get_webpack_chunk('vendorStyles', 'css')
stylesheet_link_tag("/webpack/#{foreman_vendor_css}")
Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/base.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
</head>

<body class='<%= body_css_classes %>'>
<%= get_webpack_foreman_vendor_js %>

<%= javascript_include_tag("/webpack/#{get_webpack_chunk('vendor', 'js')}") %>
<%= javascript_include_tag("/webpack/#{get_webpack_chunk('bundle', 'js')}") %>
<%= javascript_include_tag("/webpack/#{get_webpack_chunk('reactExports', 'js')}") %>
Expand Down
105 changes: 69 additions & 36 deletions config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,33 @@
var path = require('path');
var webpack = require('webpack');
const dotenv = require('dotenv');
const root = path.resolve(__dirname, '..');
dotenv.config();
var ForemanVendorPlugin = require('@theforeman/vendor')
.WebpackForemanVendorPlugin;
var StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin;
var vendorEntry = require('./webpack.vendor');
var fs = require('fs');
const { ModuleFederationPlugin } = require('webpack').container;
var pluginUtils = require('../script/plugin_webpack_directories');
var { generateExportsFile }= require('../webpack/assets/javascripts/exportAll');
var {
generateExportsFile,
} = require('../webpack/assets/javascripts/exportAll');
var CompressionPlugin = require('compression-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const packageJsonPath = path.resolve(root, 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
const dependencies = packageJson.dependencies || {};
const devDependencies = packageJson.devDependencies || {};
const allDependencies = { ...dependencies, ...devDependencies };
const shared = isPlugin =>
Object.keys(allDependencies).map(dep => ({
[dep]: {
eager: !isPlugin, // core should load all dependencies eagerly so they will be available for plugins
singleton: true,
requiredVersion: allDependencies[dep],
Comment thread
ShimShtein marked this conversation as resolved.
Outdated
import: isPlugin ? false : dep,
},
}));

class AddRuntimeRequirement {
// to avoid "webpackRequire.l is not a function" error
Expand All @@ -33,7 +49,7 @@ class AddRuntimeRequirement {
}

const supportedLocales = () => {
const localeDir = path.join(__dirname, '..', 'locale');
const localeDir = path.join(root, 'locale');

// Find all files in ./locale/*
const localesFiles = fs.readdirSync(localeDir);
Expand Down Expand Up @@ -80,14 +96,31 @@ const commonConfig = function() {
os: require.resolve('os-browserify'),
},
alias: {
'patternfly-react$': path.resolve(
__dirname,
'..',
Comment on lines +100 to +101

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
__dirname,
'..',
root,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then in the next pr (scalprum)

'node_modules/patternfly-react/dist/js/index.js'
), // to avoid circular dependency in dist/esm
'/node_modules/jquery': path.resolve(
__dirname,
'..',
Comment on lines +105 to +106

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
__dirname,
'..',
root

'webpack/assets/javascripts/jquery.js'
),
jquery: path.resolve(root, 'webpack/assets/javascripts/jquery.js'),
foremanReact: path.join(
__dirname,
'../webpack/assets/javascripts/react_app'
),
'react/jsx-runtime': 'react/jsx-runtime.js', // for react-dnd
'react/jsx-dev-runtime': 'react/jsx-dev-runtime.js', // for react-dnd
'datatables.net': path.resolve(
root,
'node_modules/datatables.net/js/jquery.dataTables.js'
), // otherwise we get datatables.net-bs Cannot read properties of undefined (reading 'classes') since dataTables.mjs is a module.
},
},
resolveLoader: {
modules: [path.resolve(__dirname, '..', 'node_modules')],
modules: [path.resolve(root, 'node_modules')],
},
module: {
rules: [
Expand Down Expand Up @@ -118,9 +151,6 @@ const commonConfig = function() {
],
},
plugins: [
new ForemanVendorPlugin({
mode,
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(mode),
Expand Down Expand Up @@ -148,30 +178,32 @@ const commonConfig = function() {
const coreConfig = function() {
var config = commonConfig();
var manifestFilename = 'manifest.json';
var bundleEntry = path.join(
__dirname,
'..',
'webpack/assets/javascripts/bundle.js'
);
config.context = path.resolve(__dirname, '..');
var bundleEntry = path.join(root, 'webpack/assets/javascripts/bundle.js');
config.context = path.resolve(root);
if (config.mode == 'production') {
var chunkFilename = '[name]-[chunkhash].js'
var chunkFilename = '[name]-[chunkhash].js';
} else {
var chunkFilename = '[name].js'
var chunkFilename = '[name].js';
}

config.entry = {
/* keep bundle entry files and reactExports seperate to avoid late loading issues of mixed files, import in react_app only from react_app and node_modules */
bundle: { import: bundleEntry, dependOn: ['vendor', 'reactExports'] },
reactExports: {
import: path.join(
root,
'webpack/assets/javascripts/all_react_app_exports.js'
),
dependOn: 'vendor',
},
vendor: vendorEntry,
reactExports: path.join(
__dirname,
'..',
'webpack/assets/javascripts/all_react_app_exports.js'
),
vendorStyles: path.join(__dirname, '..', 'webpack/assets/javascripts/react_app/common/scss/vendor-core.scss'),
vendorStyles: path.join(
root,
'webpack/assets/javascripts/react_app/common/scss/vendor-core.scss'
),
};
config.output = {
path: path.join(__dirname, '..', 'public', 'webpack'),
path: path.join(root, 'public', 'webpack'),
publicPath: '/webpack/',
library: {
name: ['TheForeman', '[name]'],
Expand All @@ -181,21 +213,22 @@ const coreConfig = function() {
};
var plugins = config.plugins;

plugins.push(new MiniCssExtractPlugin());
plugins.push(
new ModuleFederationPlugin({
name: 'foremanReact',
shared: shared(false),
})
);
plugins.push(
new StatsWriterPlugin({
filename: manifestFilename,
})
);
plugins.push(
new MiniCssExtractPlugin()
);
plugins.push(new MiniCssExtractPlugin());
config.plugins = plugins;
var rules = config.module.rules;

rules.push({
test: /\.(sa|sc|c)ss$/,
exclude: /vendor-core/i,
Expand All @@ -213,11 +246,7 @@ const coreConfig = function() {
});
rules.push({
test: /vendor-core/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
],
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
});
config.module.rules = rules;
return config;
Expand All @@ -239,7 +268,9 @@ const pluginConfig = function(plugin) {
config.externals = function({ request }, callback) {
if (/^foremanReact(\/.*)?$/.test(request)) {
const prefix = 'var TheForeman.reactExports.';
const newPath = prefix + convertImportStatement(request.substring('foremanReact'.length));
const newPath =
prefix +
convertImportStatement(request.substring('foremanReact'.length));
return callback(null, newPath);
}
return callback();
Expand All @@ -257,7 +288,7 @@ const pluginConfig = function(plugin) {

if (config.mode == 'production') {
var outputPath = path.join(pluginRoot, 'public', 'webpack', pluginName);
var chunkFilename = '[name]-[chunkhash].js'
var chunkFilename = '[name]-[chunkhash].js';
} else {
var outputPath = path.join(
__dirname,
Expand All @@ -266,7 +297,7 @@ const pluginConfig = function(plugin) {
'webpack',
pluginName
);
var chunkFilename = '[name].js'
var chunkFilename = '[name].js';
}
config.output = {
path: outputPath,
Expand All @@ -276,7 +307,7 @@ const pluginConfig = function(plugin) {
};
var configModules = config.resolve.modules || [];
// make webpack to resolve modules from core first
configModules.unshift(path.resolve(__dirname, '..', 'node_modules'));
configModules.unshift(path.resolve(root, 'node_modules'));
// add plugin's node_modules to the reslver list
configModules.push(path.resolve(pluginRoot, 'node_modules'));
configModules.push('node_modules/');
Expand All @@ -290,8 +321,10 @@ const pluginConfig = function(plugin) {
name: pluginName,
filename: pluginName + '_remoteEntry.js',
exposes: pluginEntries,
shared: shared(true),
})
);

config.plugins = plugins;
var rules = config.module.rules;
rules.push({
Expand Down
101 changes: 100 additions & 1 deletion config/webpack.vendor.js
Original file line number Diff line number Diff line change
@@ -1 +1,100 @@
module.exports = ['react-intl', 'intl'];
/* eslint-disable */

module.exports = [
'intl',
/**
* React related
*/
'@apollo/client',
'@apollo/client/link/batch-http',
'@reduxjs/toolkit',
'core-js/shim',
'regenerator-runtime/runtime',
'formik',
'rc-input-number',
'react',
'react-ace',
'react-dom',
'react-dnd',
'react-dnd-html5-backend',
'react-debounce-input',
'react-diff-view',
'react-ellipsis-with-tooltip',
'react-onclickoutside',
'react-password-strength',
'react-router-dom',
'react-router-bootstrap',
'react-loading-skeleton',
'react-redux',
'redux',
'redux-logger',
'redux-thunk',
'reselect',
'prop-types',
'classnames',
'seamless-immutable',
'connected-react-router',
'react-helmet',
'react-intl',

/**
* Patternfly related
*/
'patternfly-react',
'patternfly-react-extensions',
'@patternfly/react-core',
'@patternfly/react-icons',
'@patternfly/react-table',
'@patternfly/react-tokens',
'@patternfly/react-styles',
'@patternfly/react-charts',

/**
* ace-builds related
*/
'ace-builds',
'ace-builds/src-noconflict/ace',
'ace-builds/src-noconflict/ext-language_tools',
'ace-builds/src-noconflict/mode-ruby',
'ace-builds/src-noconflict/mode-json',
'ace-builds/src-noconflict/mode-sh',
'ace-builds/src-noconflict/mode-html_ruby',
'ace-builds/src-noconflict/mode-xml',
'ace-builds/src-noconflict/mode-yaml',
'ace-builds/src-noconflict/theme-github',
'ace-builds/src-noconflict/theme-monokai',
'ace-builds/src-noconflict/keybinding-vim',
'ace-builds/src-noconflict/keybinding-emacs',
'ace-builds/src-min-noconflict/ext-searchbox',

/**
* UUID
*/
'uuid',
'uuid/v1',
'uuid/v3',
'uuid/v4',
'uuid/v5',

'jstz',
'diff',

/**
* Other packages
*/
'history',
'number_helpers',
'lodash',
'axios',
'file-saver',
'humanize-duration',
'unidiff',
'urijs',
'yup',
Comment thread
ShimShtein marked this conversation as resolved.
Outdated
'select2',
'multiselect',
'@novnc/novnc/core/rfb',

// '@webcomponents/webcomponentsjs/webcomponents-bundle',
// '@webcomponents/webcomponentsjs/custom-elements-es5-adapter',
Comment on lines 98 to 99

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

];
2 changes: 1 addition & 1 deletion developer_docs/foreman_dev_setup.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ list of options that can be set in an .env file (as well as in the cli call):

* `NOTIFICATIONS_POLLING` is the notification polling interval in ms.

* `NODE_OPTIONS` is used for npm actions, when running plugin tests with `npm run test:plugins` we add `--max-old-space-size=8192` to the options, but it can be overridden by writing your own `NODE_OPTIONS`
* `NODE_OPTIONS` is used for npm actions, when running plugin tests with `npm run test:plugins` we add `--max-old-space-size=8192` to the options, but it can be overridden by writing your own `NODE_OPTIONS`. It is also added for webpack compile (`foreman start webpack`).


=== Resetting password
Expand Down
Loading
Loading