-
Notifications
You must be signed in to change notification settings - Fork 16
How an Elm Native module may look
Write as much as your code as possible in Elm. Elm is safe. Javascript, and therefore Native, is not. Introducing Native code can make your application much harder to debug and rely on. One of the things we love about Elm is that if it compiles, we're pretty sure we won't get runtime errors. Native modules can and will introduce runtime errors.
Make sure to read this first.
If you are considering writing a Native module, take a step back, and ask yourself if you should be. Native modules are an implementation detail, and subject to change at any moment in any form. Do you have a valid use case where you couldn't communicate to your JS through a port? Are you willing to make extra work for yourself?
Every Native module has some boilerplate attached. Below is an annotated example.
This file should be saved in src/Native/MyModule.js
// make is a function that takes an instance of the
// elm runtime
// returns an object where:
// keys are names to be accessed in pure Elm
// values are either functions or values
var make = function make(elm) {
// If Native isn't already bound on elm, bind it!
elm.Native = elm.Native || {};
// then the same for our module
elm.Native.MyModule = elm.Native.MyModule || {};
// `values` is where the object returned by make ends up internally
// return if it's already set, since you only want one definition of
// values for speed reasons
if (elm.Native.MyModule.values) return elm.Native.MyModule.values;
// return the object of your module's stuff!
return elm.Native.MyModule.values = {};
};
// setup code for MyModule
// Elm.Native.MyModule should be an object with
// a property `make` which is specified above
Elm.Native.MyModule = {};
Elm.Native.MyModule.make = make;
You will also need to change elm-package.json
to be a bit different.
{
"version": "1.0.0",
"summary": "",
"repository": "",
"license": "MIT",
"source-directories": [
"src/"
],
"native-modules": true,
"dependencies": {
"elm-lang/core": "2.1.0 <= v < 3.0.0"
},
"elm-version": "0.15.1 <= v < 0.16.0"
}
notice the "native-modules": true,
line. Without this, you will not be able to use Native.
Let's make a Native module that allows you to increment a number in the Javascript side.
To begin, let's define our Elm code. Below is the file src/MyModule.elm
module MyModule (addOne) where
-- imports are weird for Native modules
-- You import them as you would normal modules
-- but you can't alias them nor expose stuff from them
import Native.MyModule
-- this will be our function which returns a number plus one
addOne : Int -> Int
addOne = Native.MyModule.addOne
Now, let's actually implement the Native side -
var addOne = function(a) {
return a + 1;
};
var make = function make(elm) {
elm.Native = elm.Native || {};
elm.Native.MyModule = elm.Native.MyModule || {};
if (elm.Native.MyModule.values) return elm.Native.MyModule.values;
return elm.Native.MyModule.values = {
'addOne': addOne
};
};
Elm.Native.MyModule = {};
Elm.Native.MyModule.make = make;
Tada! You've just written your first native module.
To see it practice, simply copy the bit below into src/Main.elm
module Main where
import MyModule exposing (addOne)
import Graphics.Element exposing (show)
main = show <| addOne 5