Using newly installed JS library

If I run npm install someJSlibrary , it ends up node_modules folder.But how do I use/include the javascript file in my app?

As you do in any other JavaScript… require("someJSlibrary") or whatever is written in their documentation…

Depending on your buildsystem used, there might be further steps necessary to make the buildsystem aware of the library, but since you didn’t tell us which you use, you have to figure that yourself or give more info. Also those steps might actually depend on the kind of librarby you are adding…

Thanks @NobbZ

To demonstrate - lets say we want to use this code that already works:


<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>Just some random JS code with lodash/fp</title>
  </head>
  <body>
    <pre id ="displayArea"></pre>
    <script type="text/javascript"
            src="https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)"></script>
    <script type="text/javascript">
     /*
        works with Chrome Version 60.0.3112.101 (Official Build) (64-bit)
        lodash/fp code re-purposed from:
        https://simonsmith.io/dipping-a-toe-into-functional-js-with-lodash-fp/#one-more-example
     */
     const displayArea = document.getElementById('displayArea');
     const items = [
       {name: 'baz'},
       {name: 'foo'},
       {name: 'bar'},
       {name: 'bar'},
       {name: 'foo'},
     ];
     const getBars = _.filter(
       _.flow(
         _.get('name'),
         _.isEqual('bar')
       )
     );

     displayArea.textContent = JSON.stringify(
       getBars(items)
     );

    </script>
  </body>
</html>

Spin up a practice project:

$ mix phx.new myapp --no-ecto

Now go into myapp/lib/myapp_web/templates/page/index.html.eex and add the target <pre> element:

<div class="jumbotron">
  <h2><%= gettext "Welcome to %{name}!", name: "Phoenix" %></h2>
  <p class="lead">A productive web framework that<br />does not compromise speed and maintainability.</p>
</div>

<!-- BEGIN: add this -->
<div>
  <pre id="displayArea"></pre>
</div>
<!-- END add this -->

<div class="row marketing">

To make things a bit more interesting - in myapp/assets/js create a new file my-module.js (learn more and then some):

// file: myapp/assets/js/my-module.js
                           // https://github.com/lodash/lodash/wiki/FP-Guide
import _ from "lodash/fp"; // Note "_" is now a local variable 
                           // inside the module - NOT a global
export default _.filter(
  _.flow(
    _.get('name'),
    _.isEqual('bar')
  )
); // i.e. this module exports exactly one function

Now to the end of app.js already found in myapp/assets/js append some code:

...
// to also remove its path from "config.paths.watched".
import "phoenix_html"

// Import local files
//
// Local files can be imported directly using relative
// paths "./socket" or full ones "web/static/js/socket".

// import socket from "./socket"

// BEGIN -- appended code
import getBars from "./my-module"; // i.e. giving the function exported 
                                   // by my-module.js the name "getBars"
const displayArea = document.getElementById('displayArea');
const items = [
  {name: 'baz'},
  {name: 'foo'},
  {name: 'bar'},
  {name: 'bar'},
  {name: 'foo'},
];

displayArea.textContent = JSON.stringify(
  getBars(items)
);
// END -- appended code

Make sure your current working directory is myapp and fire up the phoenix server with:

$ mix phx.server

and point your browser to http://localhost:4000/. The page will display - but the textContent of the added <pre> element is empty - checking the JavaScript console reveals some errors.

At another command prompt ensure that your working directory is myapp/assets and then issue the following command:

$ npm i lodash

At this point the phoenix page should reload and you should finally see

[{"name":"bar"},{"name":"bar"}]

in the added <pre> element.

Bonus: in myapp/assets/js/app.js you may have noticed

import "phoenix_html"

Now just like lodash it comes from myapp/assets/node_modules - but not exactly. Looking at myapp/assets/node_modules/phoenix_html it becomes clear that it’s a link rather than a folder and looking at myapp/assets/package.json it becomes clear why npm created it:

...
  },
  "dependencies": {
    "lodash": "^4.17.4",
    "phoenix": "file:../deps/phoenix",
    "phoenix_html": "file:../deps/phoenix_html"
  },
  "devDependencies": {
...

myapp/deps/phoenix_html contains among other things a package.json:

{
  "name": "phoenix_html",
  "version": "2.10.4",
  "main": "./priv/static/phoenix_html.js",
  "repository": {
  },
  "files": ["LICENSE.md", "package.json", "priv/static/phoenix_html.js"]
}

which essentially tells npm to use myapp/deps/phoenix_html/priv/static/phoenix_html.js.

So in this roundabout way

import "phoenix_html"

actually imports myapp/deps/phoenix_html/priv/static/phoenix_html.js.

Now be sure to review the Phoenix Static Assets Guide and if you decide to stay with Brunch as the asset management tool to give the Brunch Guide a good look (better yet, work through it). That being said Phoenix can be adapted to other tools.

9 Likes

Thanks @peerreynders for the detailed explanation.