babel-elm-assets-plugin
TypeScript icon, indicating that this package has built-in type declarations

1.2.4 • Public • Published

Babel Elm Assets Plugin

This Babel plugin allows you to search for a particular function call in Elm, and replace it with a require() JS call. This allows you to use webpack generated assets directly in your Elm code.

Usage

import WebpackAsset exposing (assetUrl)

imageUrl =
    assetUrl "./lost.png"

image : Html Msg
image =
    img [ src imageUrl, alt "Image of man looking lost" ] []

At runtime imageUrl will be set to the full path Webpack generates to point to "list.png". Often this will end up with a hash in the name: lost.6f3a4c.png, or with a path to the place your assets are stored.

Configuration

Add the elm package

elm install cultureamp/babel-elm-assets-plugin

Add the babel plugin using Yarn (or NPM)

yarn add --dev babel-elm-assets-plugin

Add the following rules to your webpack config:

// webpack.config.js
  rules: [
    {
      test: /\.elm$/,
      exclude: [/elm-stuff/, /node_modules/],
      use: [
        // babel-loader modifies the ouput of elm-webpack-loader
        {
          loader: "babel-loader",
          options: {
            plugins: ["module:babel-elm-assets-plugin"]
          }
        },
        {
          loader: "elm-webpack-loader",
          options: {
            // ...your usual options
            // There may be some issues with using this plugin with optimized Elm builds
            optimize: false
          }
        }
      ]
    }
  ],

Advanced configuration

You can use multiple Babel plugins to post-process your Elm code. This allows you to:

  • Use elm-css-modules-plugin
  • Use multiple instances of babel-elm-assets-plugin so that you can have it work for functions other than WebpackAsset.assetUrl

Here's a more complicated example, where we include CSS modules, as well as a custom SVG loader.

-- Icon.SvgAsset.elm
type alias SvgAsset =
    { id : String
    , viewBox : String
    }

svgAsset : String -> SvgAsset
svgAsset path =
    -- these placeholder values are replaced by Webpack at build time
    { id = "elm-svg-asset-placeholder"
    , viewBox = "0 0 0 0"
    }

Notice here that calls to Icon.SvgAsset.svgAsset will expect to hold a SvgAsset, as compared to calls to WebpackAsset.assetUrl, which will hold a String.

Now, the webpack config:

// webpack.config.js
  rules: [
    {
      test: /\.elm$/,
      exclude: [/elm-stuff/, /node_modules/],
      use: [
        {
          loader: "babel-loader",
          options: {
            plugins: [
              "module:elm-css-modules-plugin",
              // If you use a plugin multiple times, you need to specify it as an array ["module:path", options, "unique-name"]
              ["module:babel-elm-assets-plugin", {}, "assets-plugin-generic"],
              [
                "module:babel-elm-assets-plugin",
                {
                  // "author/project" is the default value if no "name" field is specified in elm.json.
                  package: "author/project",
                  module: "Icon.SvgAsset",
                  function: "svgAsset"
                },
                "assets-plugin-svg"
              ]
            ]
          }
        },
        {
          loader: "elm-webpack-loader",
          options: {
            // ...your usual options
            // There may be some issues with using this plugin with optimized Elm builds
            optimize: false
          }
        }
      ]
    }
  ],

How it works

Let's work through the example above.

-- Main.elm
import WebpackAsset exposing (assetUrl)

imageUrl =
    assetUrl "./lost.png"

image : Html Msg
image =
    img [ src imageUrl, alt "Image of man looking lost" ] []

Normally when you compile this with Elm, the generated JS will look like:

var $cultureamp$babel_elm_assets_plugin$WebpackAsset$assetUrl = function (path) {
  return path;
};
var author$project$Main$imageUrl = $cultureamp$babel_elm_assets_plugin$WebpackAsset$assetUrl(
  "./lost.png"
);

Now our Babel plugin can transform that JS to use a require call:

var $cultureamp$babel_elm_assets_plugin$WebpackAsset$assetUrl = function (path) {
  return path;
};
var author$project$Main$imageUrl = require("./lost.png");

Which webpack will know how to handle, meaning your final JS will do something similar to:

var $cultureamp$babel_elm_assets_plugin$WebpackAsset$assetUrl = function (path) {
  return path;
};
var author$project$Main$myImageUrl = "/assets/lost-0fabe3.png";

The babel-elm-assets-plugin is maintained by the Delivery Engineering Team at Culture Amp.

Dependencies (2)

Dev Dependencies (9)

Package Sidebar

Install

npm i babel-elm-assets-plugin

Weekly Downloads

1,395

Version

1.2.4

License

MIT

Unpacked Size

9.92 kB

Total Files

5

Last publish

Collaborators

  • sentience
  • jasononeil
  • cultureamp-user
  • zioroboco