Canonical walkthrough for adding Javascript assets in Phoenix 1.4

Not being from a web programming background (scientific programmer here), I’m kind of confused as to how to add a javascript library to my brand new phx.new project. Between Webpack, NPM, and the various workflows, I’m completely lost I’m afraid.

Could someone give me a step-by-step recipe for adding babylon.js to my project, via npm if that is how it works, and what config files etc I will need to modify? Also how will I access it ie. will it need some template code to access it (as one does with images) or will it be direct?

By the way I’m finding it quite tough to get a “from scratch” tutorial on this on the web, most posts assuming either an upgrade from Phoenix 1.3, or fairly deep pre-existing understanding of web coding workflows and terminology.

Though not Phoenix specific some background may help: Modern JavaScript Explained For Dinosaurs

At least babylon.js seems to support ES2015 modules.

1 Like

For the sake of demonstration not installing ecto

$ mix phx.new hello --no-ecto
...
Fetch and install dependencies? [Yn] Y
...
We are almost there! The following steps are missing:

    $ cd hello

Start your Phoenix app with:

    $ mix phx.server

You can also run your app inside IEx (Interactive Elixir) as:

    $ iex -S mix phx.server

$ cd hello
$ mix phx.server

Compiling 12 files (.ex)
Generated hello app
[info] Running HelloWeb.Endpoint with cowboy 2.6.1 at http://localhost:4000

Webpack is watching the files…

Hash: b9641d0ecef2b0845a5b
Version: webpack 4.4.0
Time: 485ms
Built at: 11/28/2018 1:28:27 PM
                Asset       Size       Chunks             Chunk Names
       ../css/app.css   10.6 KiB  ./js/app.js  [emitted]  ./js/app.js
               app.js   7.23 KiB  ./js/app.js  [emitted]  ./js/app.js
       ../favicon.ico   1.23 KiB               [emitted]  
        ../robots.txt  202 bytes               [emitted]  
../images/phoenix.png   13.6 KiB               [emitted]  
   [0] multi ./js/app.js 28 bytes {./js/app.js} [built]
[../deps/phoenix_html/priv/static/phoenix_html.js] 2.17 KiB {./js/app.js} [built]
[./css/app.css] 39 bytes {./js/app.js} [built]
[./js/app.js] 493 bytes {./js/app.js} [built]
    + 2 hidden modules
Child mini-css-extract-plugin node_modules/css-loader/index.js!css/app.css:
    [./node_modules/css-loader/index.js!./css/app.css] ./node_modules/css-loader!./css/app.css 288 bytes {mini-css-extract-plugin} [built]
    [./node_modules/css-loader/index.js!./css/phoenix.css] ./node_modules/css-loader!./css/phoenix.css 10.9 KiB {mini-css-extract-plugin} [built]
        + 1 hidden module

Check in the browser http://localhost:4000/ to see the “Phoenix Framework” page.

^C
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution
a

$ cd assets
$ npm i babylonjs -D
npm WARN assets No description

+ babylonjs@3.3.0
added 1 package from 4 contributors and audited 14902 packages in 5.975s
found 0 vulnerabilities

$

Edit hello/assets/js/app.js

import css from "../css/app.css"
import "phoenix_html"
import * as BABYLON from 'babylonjs';

var canvas = document.getElementById('renderCanvas');
var engine = new BABYLON.Engine(canvas, true, {preserveDrawingBuffer: true, stencil: true});
var createScene = function(){
    var scene = new BABYLON.Scene(engine);
    var camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5, -10), scene);
    camera.setTarget(BABYLON.Vector3.Zero());
    camera.attachControl(canvas, false);
    var light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), scene);
    var sphere = BABYLON.Mesh.CreateSphere('sphere1', 16, 2, scene, false, BABYLON.Mesh.FRONTSIDE);
    sphere.position.y = 1;
    var ground = BABYLON.Mesh.CreateGround('ground1', 6, 6, 2, scene, false);
    return scene;
}
var scene = createScene();
engine.runRenderLoop(function(){
    scene.render();
});
window.addEventListener('resize', function(){
    engine.resize();
});

Edit hello/lib/hello_web/templates/page/index.html.eex at the end

  </article>
  <canvas id="renderCanvas"></canvas>
</section>
assets $ cd ..
hello $ mix phx.server
[info] Running HelloWeb.Endpoint with cowboy 2.6.1 at http://localhost:4000

Webpack is watching the files…

Hash: db7fb853b4bd33268f5d
Version: webpack 4.4.0
Time: 1292ms
Built at: 11/28/2018 2:34:55 PM
                Asset       Size       Chunks             Chunk Names
       ../css/app.css   10.6 KiB  ./js/app.js  [emitted]  ./js/app.js
               app.js   2.04 MiB  ./js/app.js  [emitted]  ./js/app.js
       ../favicon.ico   1.23 KiB               [emitted]  
        ../robots.txt  202 bytes               [emitted]  
../images/phoenix.png   13.6 KiB               [emitted]  
   [0] multi ./js/app.js 28 bytes {./js/app.js} [built]
[../deps/phoenix_html/priv/static/phoenix_html.js] 2.17 KiB {./js/app.js} [built]
[./css/app.css] 39 bytes {./js/app.js} [built]
[./js/app.js] 1020 bytes {./js/app.js} [built]
[./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 509 bytes {./js/app.js} [built]
    + 3 hidden modules

WARNING in ./node_modules/babylonjs/babylon.js
Module not found: Error: Can't resolve 'cannon' in '/Users/wheatley/sbox/phx/hello/assets/node_modules/babylonjs'
 @ ./node_modules/babylonjs/babylon.js 1:156-173
 @ ./js/app.js
 @ multi ./js/app.js

WARNING in ./node_modules/babylonjs/babylon.js
Module not found: Error: Can't resolve 'earcut' in '/Users/wheatley/sbox/phx/hello/assets/node_modules/babylonjs'
 @ ./node_modules/babylonjs/babylon.js 1:228-245
 @ ./js/app.js
 @ multi ./js/app.js

WARNING in ./node_modules/babylonjs/babylon.js
Module not found: Error: Can't resolve 'oimo' in '/Users/wheatley/sbox/phx/hello/assets/node_modules/babylonjs'
 @ ./node_modules/babylonjs/babylon.js 1:193-208
 @ ./js/app.js
 @ multi ./js/app.js
Child mini-css-extract-plugin node_modules/css-loader/index.js!css/app.css:
    [./node_modules/css-loader/index.js!./css/app.css] ./node_modules/css-loader!./css/app.css 288 bytes {mini-css-extract-plugin} [built]
    [./node_modules/css-loader/index.js!./css/phoenix.css] ./node_modules/css-loader!./css/phoenix.css 10.9 KiB {mini-css-extract-plugin} [built]
        + 1 hidden module
[debug] Live reload: priv/static/js/app.js
[debug] Live reload: priv/static/css/app.css
[debug] Live reload: priv/static/images/phoenix.png
[info] GET /
[debug] Processing with HelloWeb.PageController.index/2
  Parameters: %{}
  Pipelines: [:browser]
[info] Sent 200 in 16ms

Apparently babylon.js has issues isolating the cannon, oimo, and earcut dependencies.

Checking the browser at http://localhost:4000/ you should see

6 Likes

Thanks @peerreynders. Works perfectly. Couple of questions:
a) If we’re using NPM to install javascript packages, is that because we can then use it periodically to update to the latest ones?
b) what is the -D parameter in npm i babylonjs -D?

It’s used as the de facto package manager for the JavaScript ecosystem (i.e. not anything Phoenix has control over - therefore it is not technically part of Phoenix. Webpack is distributed with Phoenix as a convenience but as such isn’t an essential part of Phoenix). Before npm bower was in common use.

what is the -D parameter in npm i babylonjs -D ?

i is the alias for npm-install while -D is the short form for --save-dev. Given that the bundler (webpack) will include babylon.js in the bundle it becomes are “mere” development dependency (though the difference primarily exists for the benefit of projects that build node server applications).

1 Like