Hi everyone, Shim and I made a working version of Foreman with webpack 5! Please help us test it and make any improvement suggestions to the new configuration.
We have successfully achieved a stable configuration of Foreman and its plugins using Webpack 5. In this revamped setup, we’ve embraced module federation to streamline the loading process. Because we are using module federation, each plugin will be built separately and will be dynamically loaded. The configuration for each plugin will be the same, and is located in foremans webpack.config
.
One of the major changes in this configuration is the shift towards utilizing files from the public folder instead of relying on the webpack dev server to serve them. This change serves two primary purposes: first, it eliminates the need to run a webpack dev server for each plugin, and second, it simplifies the loading process within Ruby. After this change, every plugin will have a folder in public/webpack
with its webpack assets (@packaging). This change also removes the webpack-rails gem.
This transition has necessitated adjustments to the loading order and the implementation of a few workarounds:
- Since the plugins are loaded asynchronously, we have introduced the
loadPlugin
global event that will be fired once all the plugins are loaded. Which means, JavaScript scripts/files loaded with content_for(:javascripts)
will now load only after plugins are loaded.
- The
react_component
will search for its component only after all plugins and JavaScript scripts have loaded, otherwise it might not find the component.
- In Katello: We’ve made crucial changes to the bastion code to ensure it loads in the correct order. Without this adjustment, Angular pages may not function as expected. Specifically, this resolves these errors:
-
BASTION_MODULES
not being defined and issues with angular.element(document).ready
, which is no longer effective due to dynamic script loading.
-
angular.bootstrap
can only run after all angular.module(...
were run.
- Unknown provider: $rootScopeProvider ← $rootScope making angular pages not load
-
-
webpack_asset_paths(plugin_name, extension: 'js')
for Javascript files should not be used anymore, and plugins that use it should replace it with content_for(:javascripts) { webpacked_plugins_js_for(plugin_name) }
. For the next Foreman version we will override the javascript_include_tag
function to make sure plugins are loaded correctly.
-
webpack_asset_paths
for CSS files should not be used as the css will already be loaded.
- Since we no longer run webpack as a server, we will remove
webpack_dev_server
and webpack_dev_server_https
options.
We are sharing the react_app/components/HostDetails/Templates
folder for a specific reason. Without this sharing, each plugin creates its own file for webpack/assets/javascripts/react_app/components/HostDetails/Templates/CardItem/CardTemplate/index.js
. This isolated approach prevents the React Context from being properly passed to the plugins, resulting in crashes on the host details page’s details tab.
Other changes:
- SimpleNamedModulesPlugin was a simple version of webpack 3 SimpleNamedModulesPlugin, we removed it and we are using
optimization:{ moduleIds: 'named',}
as recommended by webpack 5 instead, @packaging will that work for you?
- Webpack 5 no longer automatically includes the
buffer
package, so we need to import it manually in webpack/assets/javascripts/react_app/common/globalIdHelpers.js
.
While we’ve achieved significant improvements with this configuration, we’re aware of a few challenges that still need attention, now or in the future:
-
Lengthy webpack compile times (sometimes up to 5 minutes).
-
Increased JavaScript file sizes.
-
Longer page loading times for certain pages (for example: /foreman_tasks/tasks
, /products
).
Relevant PRS to use the new configuration:
Foreman: webpack 5 by MariaAga · Pull Request #9834 · theforeman/foreman · GitHub
Katello: webpack5 by MariaAga · Pull Request #10735 · Katello/katello · GitHub
To ensure a clean run with Webpack 5, please follow these steps in the Foreman folder:
rm -rf node_modules public/webpack/ public/assets/
npm install
And then:
Run webpack and rails separately:
npx webpack --config config/webpack.config.js --watch
bundle exec foreman start rails
Or together:
bundle exec foreman start
As we move forward, our goal is to enable plugins to consume Foreman as a module via package.json
while leveraging the expose
and shared
features in the webpack’s module federation configuration. We believe this approach will help reduce JavaScript file sizes and prevent Foreman CSS from being duplicated in every plugin, mitigating issues related to CSS file size and compatibility with older plugins.