Blog

Phoenix & JSPM

Phoenix & JSPM

One of the things you start out with when you create a new Phoenix application is the default brunch setup for JavaScript. Since I’m not a big fan of manually copying dependencies for JS around, I opted for Brunch, due to its automatic integration with brunch and relative ease of use. Since Brunch isn’t being developed anymore, I began searching for an alternative that provides the same functionality.

JSPM just seems to fit the bill. It not only is built with the browser as top priority, but also already meant to be used via HTTP/2, which sadly hasn’t arrived yet in Cowboy, the server Phoenix uses (but they plan to release it towards end of the year, so keep your hopes up).

For sake of demonstration we’ll just use sqlite, though we could just as well use --no-ecto, I just wanted this to resemble an actual application as much as possible.

Installation in a new project without brunch

First we’ll cover how you can install JSPM in a new Phoenix application created with --no-brunch so you can see what is neccesary to add to get JSPM integrated.

mix phoenix.new brunchless --database sqlite --no-brunch
cd brunchless
mix ecto.create
mix phoenix.server

You should be seeing the good old default startpage of a new Phoenix application. So let’s get really started by installing JSPM. In case you don’t have NPM yet, it’s included in the Node.js JavaScript runtime.

Now we’ll need a file to store our packages installed via npm, which in this case will only be executables we use to compile files and JSPM itself. To create a full package.json simply run this command.

npm init --yes

We use the -S flag to install JSPM only for this project and add it to the dependencies.

npm install -S jspm

If you haven’t done so already, you might also want to add ./node_modules/.bin to your $PATH to make finding the jspm executable easier.

Now that the boring stuff is out of the way, we can finally get to using JSPM.

jspm init -p
Would you like jspm to prefix the jspm package.json properties under jspm? [yes]:
Enter server baseURL (public folder path) [./]:./priv/jspm/
Enter jspm packages folder [priv/jspm/jspm_packages]:priv/jspm/pkg
Enter config file path [priv/jspm/config.js]:
Configuration file priv/jspm/config.js doesn't exist, create it? [yes]:
Enter client baseURL (public folder URL) [/]:/jspm
Do you wish to use a transpiler? [yes]:
Which ES6 transpiler would you like to use, Babel, TypeScript or Traceur? [babel]:

This will put all things related to JSPM into the /priv/jspm directory, which will come in handy when we define the static paths later.

Next up comes defining the static paths for Elixir: In lib/brunchless/endpoint.ex just below the other Plug.Static, add following plug:

plug Plug.Static,
  at: "/jspm", from: {:brunchless, "priv/jspm"}, gzip: false,
  only: ~w(js pkg config.js)

This will serve requests from the browser at /jspm to our ./priv/jspm and allow us to serve all our JavaScript from there. I usually also delete the js entry from the plug Plug.Static at: "/" above, but that’s optional since we didn’t call our path js. Just keep in mind that anyything written to ./web/static/js and ./web/static/vendor won’t be served at all since it’s not being copied to ./priv/static/js by Brunch.

Something that I haven’t found a good solution for yet is the phoenix_html.js inclusion. For now it’s best to copy the file from ./deps/phoenix_html/priv/static/phoenix_html.js to ./priv/jspm/js/phoenmix_html.js. But I’d love any sugggestions regarding this hack, maybe adding a static plug just for it?

Next I’m taking you out for a little spin with:

jspm install spin

And to use the spinner, create ./priv/jspm/js/app.js with following code:

import './phoenix_html';
import Spinner from 'spin';

var target = document.getElementsByClassName("logo")[0];
var spinner = new Spinner({lines: 8}).spin(target);

This is simply menat to work with the default Phoenix layout and should display a spinner in the middle of the page. To actually load JSPM we also need to replace the <script src="<%= static_path(@conn, "/js/app.js") %>"></script> in ./web/template/layout/app.html.eex with this:

<script src="<%= static_path(@conn, "/jspm/pkg/system.js") %>"></script>
<script src="<%= static_path(@conn, "/jspm/config.js") %>"></script>
<script>System.import('js/app.js')</script>

That might look like a lot, but for production we’ll be able to replace it with a single line. This simply allows us to dynamically reload the files without any compilation time and speed up development compared to the old Brunch setup.

At this point we can already check in the browser that everything’s working correctly: Hello Phoenix with Spinner

For reloading, we still need to tell Phoenix the path to our JSPM folder. In order to do that, change the ./config/dev.exs section for :live_reload to look like this:

# Watch static and templates for browser reloading.
config :brunchless, Brunchless.Endpoint,
  live_reload: [
    patterns: [
      ~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
      ~r{priv/jspm/.*js$},
      ~r{web/views/.*(ex)$},
      ~r{web/templates/.*(eex)$}
    ]
  ]

Restart the server and try changing the number of lines for the Spinner. It should automatically reload and show the updated version.

Lies weiter →

LVM root vergößern trotz mangeldem Speicherplatz

Neulich stieß ich auf dieses Problem, und es brauchte ein wenig Zeit es zu beheben. Die äußerst hilfreiche Fehlermeldung war

[root@alpha ~]# lvextend --size 30G /dev/mapper/vg0-root
Couldn't create temporary archive name.
Volume group "vg0" metadata archive failed.

Nun, gab es einige Berichte darüber, dass ein “invalider” Hostname so etwas verursachen könnte, aber diese Berichte waren für einen längst behobenen Bug.

Die wirkliche Antwort war, das automatische Backup der Metadaten für diese Operation zu überspringen, da dafür leider nicht genügend Platz zur Verfügung war.

Daher die einfache Lösung ist es, die -A Option zu verwenden.

[root@alpha ~]# lvextend -A n -L +10G /dev/mapper/vg0-root
Size of logical volume vg0/root changed from 20.00 GiB (5120 extents) to 30.00 GiB (7680 extents).
WARNING: This metadata update is NOT backed up
Logical volume root successfully resized

Falls jemand noch eine besseren Vorschlag hat, hinterlasst doch bitte ein Kommentar.

Lies weiter →

Was ist Elixir

Elixir ist eine neue Programmiersprache mit Wurzeln die bis in die 80er Jahre zurückreichen. Damals hat bei Ericsson ein Informatiker namens Joe Armstrong ein System für die besonderen Anforderungen in der Telekommunikation geschaffen. Er gab dem System den Namen Erlang, und um es zu steuern, entwickelte er auch die gleichnamige Sprache.

Erlang Logo

Heute benötigen viele Anwendungen die besonderen Features von Erlang, aber durch die besonders eigenartige Syntax werden die meisten abgeschreckt und wählen Sprachen die vertrauter wirken. Um diesen Post übersichtlich zu halten, werde ich nicht weiter auf Erlang selbst eingehen, sondern euch erst einmal ein kleines Beispiel von Elixir zeigen.

for n <- 1..4, do: n * n
# [1, 4, 9, 16]

Hier nutzen wir eine sogenannte comprehension um einfach alle Zahlen von 1 bis 4 mit sich selbst zu multiplizieren.

Lies weiter →

Aller Anfang ist schwer

Aber das hält uns nicht auf. Jeder Schritt bringt uns näher an unsere Ziele, und das beste Gegenmittel für Faulheit ist ein gehöriger Schuss Disziplin.

Wir werden hier regelmäßig Neuigkeiten aus der Welt der Web-Entwicklung, Fotografie, Sozialen Medien, Design & Typographie, und vieles Mehr unter die Lupe nehmen.

Lies weiter →