Javascript and phoenix
Intro
While developing a modern web app, soon or later, you have to deal with javascript, in order to give your users better experiences and to avoid useless page reload and so on.
The radical choice is to use one of popular javascript framework to manage all front end stuffs with a spa app. This way you can totally decouple front end and back end and get some real amazing results, but you have to write a ton of code,often writing some features twice, one for the client and one for the server.
This time my goal is to learn at my best a new language and e new framework that claim to have built into it a lot of features that gaves the same good user experience of spa apps, with a lot less lines of code.
I mean phoenix channels, presences, sockets and so on, so i’d like to use the less javascript I can, without refuse to have an acceptable user experience.
The solution i found is Riot.js v3, which is by far lighter than most popular frameworks – polymer is 6 times heavier, angular much more, it’s component based and has a well written and complete documentation.
Here is a brief description about i integrated it into phoenix in order to make an heavy use of it’s capabilities.
Setup
Phoenix1.4 use Webpack 4 to manage static assets (prior versions used brunch, here a guide about), and it has defaults good enough to let you add 3rd party libraries available and ready to use with little or no effort.
All you have to do is to create a js folder under your asset/static path into the _web app to contains the libraries you want to use, and because of Riot.js needs also, at least, a file per component, i added into /assets/static/js/tags directory to contain them.
Webpack will copy them all into priv/static folder of your web app, ready to be served at usual urls.
So the struct fo that part of the app will something similar to:
nagger_web$ tree -d 1 -L 1 assets/ assets/ ├── css ├── js ├── node_modules ├── static │ ├── images │ └── js │ └── tags └── vendor
Then i copied into js folder the riot+compiler.min.js file, the only file needed by Riot to compile at runtime the components, and added it’s reference into the base app template, app.html.eex becouse i’m planning to use Riot every time i need some dom manipulation, in thisway it will be available everywhere.
I added superagent too, becouse it’s very practical when you have to deal with asyncronous ajax requests but you want to keep your code clean and readable.
The lines added are:
<script src="https://polyfill.io/v3/polyfill.min.js?features=Array.from,Promise,Symbol,Object.setPrototypeOf,Object.getOwnPropertySymbols"></script> <script src="https://cdn.jsdelivr.net/npm/superagent"></script> <script src="<%= Routes.static_path(@conn, "/js/riot_compiler.min.js") %>"></script>
And voilà, Riot is available everywhere ;-D
Just be sure to add these lines into the <head> tag of the page, this way their functions will be available into all your template when rendered.
Now i want to test if it’s really working, so i created the simplest riot tag ever and saved it as hello-world.tag into the assets/static/js/tags folder
<hello-world> <h3>Hello World from { opts.from }!!!</h3> <script> console.log('All fine...'); </script> </hello-world>
And added to my templates/pags/index.html.eex templates the three lines of code that should make it rendered on the DOM.
<div class="row"> <script src="<%= Routes.static_path(@conn, "/js/tags/hello-world.tag") %>" type="riot/tag"></script> <hello-world from="Sergio"></hello-world> <script> riot.mount('*'); </script> </div>
And launched the server with usual command:
$mix phx.server
in order to verify if everything is working as expected, aaand…
Enjoy!!