Webpack config for Elm

For my dmx-zettelkasten plugin I want to add a loader that can handle the .elm file type.

Unfortunately I am not an expert when it comes to customizing the webpack.config.js.

Since I essentially need a bridge to render Elm modules in a Vue application, I use Lindsay Wardell’s elm-vue-bridge package. The vue.config.js mentioned there adds the elm-webpack-loader:


module.exports = {
  configureWebpack: {
    module: {
      rules: [
        {
          test: /\.elm$/,
          exclude: [/elm-stuff/, /node_modules/],
          use: { loader: "elm-webpack-loader", options: {} }
        }
      ]
    }
  }
};

Outside the dmx codebase this works, but I need help to configure the webpack.config.js for my dmx plugin inside it’s modules-external directory. See this commit.

You can write 2 types of plugins for the DMX platform. Both rely on the DMX backend and data model, but differ at the frontend:

  1. Plugins that extend the DMX Webclient.
    You can e.g. mount custom (Vue) components to the Webclient’s toolbar or provide custom renderers for e.g. the detail panel. You’re fixed to use Vue (and Vuex) as this is the technology the DMX Webclient is based on.

  2. Plugins that create a proprietary web frontend – besides the DMX Webclient (like e.g. the dm5-mobile plugin).
    In this case you’re free to choose any frontend technology you like.

What kind of plugin do you want develop?

As you mention Elm I guess you’re aiming for 2.
In this case the dm5-plugin-template is not suitable.
See the webpack.config.js of the dm5-mobile project as a template instead.

But in case you’re aiming for 1.: from my point of view, architecturally it does not make lot of sense to mix Elm and Vue/Vuex in one application as both perform basically the same task (state management and reactivity). Although technically possible, by mixing both technologies you buy unnecessary complexity, resulting in more headaches than needed, in particular when it comes to more advanced components. (Besides that your plugin will grow in size.)

That said, if you change your dmx-zettelkasten webpack.config.js like this (exactly as appearing in elm-vue-bridge’s vue.config.js) …

    rules: [
      {
        test: /\.elm$/,
        exclude: [/elm-stuff/, /node_modules/],
        use: {
          loader: 'elm-webpack-loader',
          options: {}
        }
      },
      ...
    ]

… then the webpack build works:

dmx-zettelkasten$ npm install
dmx-zettelkasten$ npm run build

> dmx-zettelkasten@0.1.0 build /Users/jri/Documents/DMX/Development/modules-external/dmx-zettelkasten
> ../../node_modules/.bin/webpack -p --hide-modules

Hash: 0aa08786a1a21d1a746c
Version: webpack 4.41.5
Time: 2062ms
Built at: 02/06/2020 10:57:51 AM
                         Asset      Size  Chunks                         Chunk Names
6d0ce3d676cecf7ddd63.style.css  34 bytes       0  [emitted] [immutable]  main
ae7fd52ee9425f3c7e48.plugin.js  37.8 KiB       0  [emitted] [immutable]  main

I’m very interested in Elm, but unfortunately have no experience yet. Developing a DMX based frontend in Elm (e.g. the Zettelkasten application) that runs independently from the DMX Webclient, would be a very interesting task.

1 Like

I want to develop a plugin that extends the standard DMX webclient. (and add a server-side part to the plugin later on) Cf. README.md of DeepaMehta 5 Plugin Template

I work like this to take advantage of the described 2 benefits:

  • For building the production version of the plugin the existing Webpack installation of the DeepaMehta installation will be reused (you don’t need install Webpack for every plugin project again and again).
  • The production build of your plugin is automatically copied to DeepaMehta’s bundle-deploy directory in order to get hot deployed.

The dmx-zettelkasten plugin’s source code attempts to demonstrate the following concepts:

  • How to Use Elm at Work [1]
  • JavaScript Interop [2] (Flags, Ports)

References

[1] CZAPLICKI, Evan, 2016. How to Use Elm at Work. [online]. 11 Juli 2016. [Zugriff am: 10 Februar 2020]. Verfügbar unter: https://elm-lang.org/news/how-to-use-elm-at-work

[2] JavaScript Interop · An Introduction to Elm, [kein Datum]. [online]. [Zugriff am: 18 November 2019]. Verfügbar unter: https://guide.elm-lang.org/interop/

Just a note: also for the other case – a plugin that creates a proprietary web frontend – you get both benefits (1. reuse of DM’s Webpack installation, and 2. plugin hot deployment).

Thank you very much for the accurate information about Elm utilization! This brings me one step closer to Elm :slight_smile:

1 Like

The adjustments must be made in two places. Besides the plugin directory also in the root directory.

  • I also had to change the webpack.config.js in the deepamehta root directory (add Elm entry under rules)
  • npm install --save elm-webpack-loader
  • elm init
  • elm install elm/json
  • After that ’ mvn clean install -P all -DskipTests’ and ‘mvn pax:run’ and ‘npm run dev’ was successful

These two places correspond to the 2 modes: dev mode and production mode.

In dev mode you want have Hot Module Replacement for your plugin that extends the Webclient. You do so by adding the plugin to Webclient’s plugin_manager.js, effectively making it part of the Webclient source tree. In dev mode the Webclient is build (along with your plugins) and served by the webpack-dev-server. The dev server uses webpack internally for building. This build is governed by the Webclient’s webpack.config.js (in platform root directory).

In production mode that source code “symbiosis” is abolished. For production you want build your plugin independently from Webclient and make it a distributable and deployable unit. That webpack production build process is governed by your plugin’s webpack.config.js (in your plugin directory).

The latter describes the status quo, for your understanding. There is still much room for improving the DMX build system. Having certain config in 2 places is obviously a bad thing. Also I would like eliminate the need for “registering” plugins in Webclient source code (plugin_manager.js) while development.