Webpacking plugins, let's do it right

Hello,

I think that for plugin developers, the webpack build is a black hole and there is no way to configure staff from the plugin itself.

How it works right now:
foreman-core will create a generic “configuration” for each gem recognized as a plugin.

How do we know this gem is actually a plugin?
It’s name start with foreman_ (or foreman- for foreman-tasks)

How do we know this plugin need to get build with webpack?

  1. It contains a package.json file
  2. It has a webpack/ folder

My proposal:

Ask plugins to add a new configuration file to the root folder (foremanPack.json?) or add a new section to the package.json
Foreman core should read this json and apply its configuration for the webpack build.
For example:

{
  "plugin-name": "my-plugin-name",
  "entry": {
    "my-entry-1": "./webpack/assets/javascripts/my-entry-1.js",
    "my-entry-2": "./webpack/assets/javascripts/my-entry-2.js",
    "my-scss-entry": "./webpack/assets/stylesheets/my-scss-entry.scss",
  },
  "resolve": {
    "modules": ["./node_modules"],
    "alias": {
      "MyAlias1": "./webpack/assets/javascripts/my-alias-1.js",
      "MyAlias2": "./webpack/assets/javascripts/my-alias-2.js",
    }
  },
  "sass": {
    "overrideVariables": "./webpack/assets/stylesheets/variables/_my-variables.scss",
    "overrideMixins": "./webpack/assets/stylesheets/variables/_my-mixins.scss",
  }
}

Any thoughts?

Cheers!

2 Likes

Sounds good to me, good start is updating https://github.com/theforeman/foreman_plugin_template and How to Create a Plugin - Foreman once the core supports it.

I agree, only an explanation by you helped to figure out how to do it, the current documentation did not mentioned it.

I think that the structure is a bit problematic here, because “entry”, “resolve” and “sass” can actually have configuration at the same place.

{
   "plugin-name": "my-plugin-name",
   "files": [
       {  "name": "my-entry-1",
          "file": ""./webpack/assets/javascripts/my-entry-1.js", 
         "alias": [ "./webpack/assets/javascripts/my-alias-1.js" ], 
         "modules": ["./node_modules"]
        },
      {
        "name": "my-scss-entry",
        "file": "./webpack/assets/stylesheets/my-scss-entry.scss",
        "overrideVariables": "./webpack/assets/stylesheets/variables/_my-variables.scss",
        "overrideMixins": "./webpack/assets/stylesheets/variables/_my-mixins.scss",
      }
    ],
  "global": {
    "scss": {
       "overrideMixins": "./webpack/assets/stylesheets/variables/_global-mixins.scss"
     }
  }
}

The idea is to unified configuration, so it is easy to understand what belongs to where, and how.

What do you think?

1 Like

While it makes sense separating to files and globals, entry and resolve are coupled with the webpack API so it may be easier to integrate and easier to understand if you familiar with webpack.

1 Like

Oh, then yes, you are right :slight_smile:

One thing to keep in mind- we are currently using the webpack-rails gem that is deprecated, and will need to migrate to rails default of using webpacker sometime in the (hopefully) near future. Will this still work and/or be needed?

It will not work. webpacker and our plugin model work in a different way. There’s also assumptions on different paths. The third big change is yarn instead of npm. A trail I did while looking at things:

https://github.com/theforeman/foreman/compare/develop...ekohl:webpacker

Note that I have stopped halfway when I realized that fixing the current setup was a better fix on the short term we needed and cherry picking was not going to be an option. Do not take this as the right way or anything.

I think we can phase out webpack rails altogether, based on experience with Using webpack infront of rails in development it looks like we just need to maintain a few helper methods to link to assets, but we don’t really need rails to be aware of webpack at all. also AFAIU webpacker is not going to support rails engines, which suggest we should not aim to use it long term?

It’s not that a big deal.

yes, the webpack.config.js is going to be different, and live across multiple files and the rails-helpers/middlewares is a bit different.
But at the end, when it comes to the webpack.config.js (which is relevant here), you can achieve whatever webpack configuration you wants to.

I could already migrate some old webpack config, from my experience, its makes webpack easier to configure.

No, we’ll still need webpack-rails/webpacker/equivalent. The part we need is to include the right JS/CSS file names. This is read from manifest.json. Given we already hack around this because we read multiple manifest.json files, we could probably find an alternative that only provides that part. Probably not too hard to write our own helper functions for this.

This will be needed until we have a full SPA that also serves the index.html. There’s a good chance we need to modify webpack to know about our plugin chunks from multiple manifest.json files though.

1 Like