Sunday, May 28, 2017

Vue.js cheatsheet

If you ever wondered why Vue.js is so easy take a look at this cheatsheet!

Vue/Vuex - a natural way forward

For a few days I have been creating an application to help with retrospection meetings in our distributed team. Obviously, as one might have guessed, the backend is in Node.js and, obviously, the frontend is in Vue.js. After a trial and error of a few approaches I decided that the state management is basically killing me so I went for Vuex to do its job. I knew little to nothing about Vuex but obviously I have had a lot of experience with Redux and since both do the same thing I thought things won't be too difficult. And I was right!

I followed this great article by Matt Bradford on how to get started with Vue+Vuex and I need to say that he hit the nail in the head with that article. Easy to follow, clear in message - just perfect. Then I went on to the official docs and, as usual with all things related to Vue.js, the guide was just perfect. It took me about 2 hours while creating the app to get used to it, learn the API, understand the difference between actions and mutations - basically a walk in the park!

The key takeaway from this experience for me is that documentation matters, a lot! It has to be good, easy to understand and fun to follow. Like a well written book that you can't take your eyes off late in the evening. Of course it helps if the thing the documentation describes is easy and fun but that is just about 30% - the rest is the craftsmanship of the author of the documentation. To underline that I have been reading some very ugly specs at work, written like someone didn't want to read what he wrote. That was just crazy! After that getting my hands on the Vuex guide helped me keep up the hopes for humanity :P

The bottom line is: if you feel like you're struggling with managing the state, even just a little bit - you need Vuex!

The next thing I desperately wanted to try was to make a system that through websockets to distribute the changes to other connected clients. This means that when you add a card on one browser that information is then posted via the websocket and the server broadcasts that information back to other browsers. I must say I am extremely surprised how well that worked! One thing to note is that when working on the store full page reloads do happen a lot. Each full reload causes the socket to be closed and reopened - which isn't all that bad. However restarting the server is a whole other story because websockets don't reconnect automagically. In this case, after trying out what I thought would work I ended up using reconnecting-websocket module. And it works absolutely great!

The server side uses the no database approach with a simple on-line events store and commands that mirror the mutations in Vuex. Easy and very, very fast! It looks like event sourcing is actually a good thing :)

You can find the sources for the project on Github.

Happy coding!

Thursday, May 18, 2017

Vue, Vue CLI, Webpack template, Nightwatch and page obect pattern

Today I tried to use the page object pattern with Nightwatch.js that is created when using the webpack template in vue-cli. It turns out they are not configured by default. This means you need to add

page_objects_path: ['test/e2e/pages'],
to your tests/e2e/nightwatch.conf.js file to start using it.

The usage scenario is quite simple

  1. Create a file describing the page
  2. Use it in a test

Everything you need to know about page object pattern and Nightwatch is here so don't hesitate to check it out. Here's a basic example, the initial e2e test created when the app was scaffolded, but this time rewritten using page object patter.

// For authoring Nightwatch tests, see
// http://nightwatchjs.org/guide#usage

module.exports = {
  'default e2e tests': function (browser) {
    // automatically uses dev Server port from /config.index.js
    // default: http://localhost:8080
    // see nightwatch.conf.js
    const devServer = browser.globals.devServerURL

    browser.page.home()
      .open(devServer)
      .assertMainContentPresent()
      .assertHeaderText('Welcome to Your Vue.js App')
      .assertMainLogoPresent()

    browser.end()
  }
}

And now the page definition in tests/pages/home.js:

module.exports = {
  elements: {
    container: {
      selector: "#app"
    },
    hello: {
      selector: ".hello"
    },
    title: {
      selector: "h1"
    },
    logo: {
      selector: "#app > img"
    },
  },
  commands: [ {
    open(url) {
      return this
        .navigate(url)
        .waitForElementVisible('@container', 5000)
    },
    assertHeaderText(content) {
      return this.assert.containsText('@title', content)
    },
    assertMainContentPresent() {
      return this.assert.elementPresent('@hello')
    },
    assertMainLogoPresent() {
      return this.assert.elementCount('@logo', 1)
    },
  } ]
}

Basically a page object is what a module exports. It is divided into 3 sections

  • elements - definition how to find certain elements
  • commands - pieces of work the page does
  • sections - (absent in this example)grouping mechanism for definitions

That's it

Wednesday, May 17, 2017

Performance of frontend frameworks

This is going to be just a quick note to myself

Don't base your choice on performance only. Currently pretty much all frameworks yield similar results (yes, even Ember is catching up with Glimmer, even though it is still slower than the other ones from the big 4). Use common sense, which is not so common, and let the simplicity and flexibility of use be your guiding star. If however the performance is not acceptable from the start and the framework doesn't have you on your knees begging to use it then just don't go for it.

Even though Ember is getting faster (I just threw up in my mouth a little bit) it doesn't mean it is sane to use it in any project of any size with Vue, Angular and React being out there

Happy coding

Monday, May 1, 2017

Vue directive NAME/V

Have you ever tried to remember the elements of a Vue's directive? But there are so many of them! Don't worry - they are very easy to remember!

Name - the part that comes right after "v-"

Argument - the part that comes right after the colon

Modifiers - the part that comes after dot

Expression / Value - the expression put inside the parameter value and the evaluated value

NAME / V - for short

Happy coding!

Tuesday, April 4, 2017

Recording screencast with Atom and Firefox

The need

I have recently started work on a video course about VueJS. The major part of it are screen recordings. I went through the original documentation my editor provided and it was just for Win/Mac (no surprise there) so I needed to go and figure it out for myself.

The how

As it turns out recording screen on Linux is quite easy. There are lots of good applications for it. I went with the good old ffmpeg

$ Xephyr :1 -ac -screen 1280x720 -br -reset &
$ sleep 2
$ setxkbmap -display :0 -print | xkbcomp - :1 &> /dev/null
$ DISPLAY=:1 evilwm -snap 50 &
$ DISPLAY=:1 atom &
$ DISPLAY=:1 firefox &

Now that we have all the apps running in a nice enclosure let's record the action:

$ ffmpeg \
    -f pulse -ac 2 -i default \
    -f x11grab -r 25 -s 1270x720 -i :1 -c:v libx264 \
    "./$(date).mp4"
This will create a new file with human readable timestamp each time you run this command encoding the 720p video in h.264 format and audio in AAC putting it all into an MPEG4 container.

Making Atom captures easy to edit

When editing the video in post production, for example using Blender's NLE, it is hard to fit the blinking intervals when cutting parts of the video. For that reason I recommend disabling the blink cursor in Atom. Select "Open your stylesheet" menu item and enter the following snippet

atom-text-editor.editor .is-focused .cursors .cursor {
  opacity: 1
}

That's it. Now the cursor is solid and editing is easy again

Happy recording!

Saturday, March 4, 2017

Sending logs from NodeMCU/Lua to Graylog2

Graylog2 is a great product. It might not be the most sophisticated one when it comes to log aggregation and interrogation, but it does its job very well. After employing Graylog2 to collect logs from all my Docker containers I thought that it would be absolutely fantastic to be able to manage logs from the IoT devices as well.

Installing the right input plugin

Before we can push stuff into Graylog2 we need to teach it the protocol of IoT devices - MQTT. Luckily enough there is a ready-made and supported input plugin just for that. To install it simply download it to the plugin folder in your Graylog2 installation and restart Graylog2. Done.

The next thing is to add an input for MQTT. Select System/Inputs and then create an input by selecting MQTT TCP (GEFL) from the drop-down list of available connectors. You need to specify the MQTT server and queue which the connector will subscribe to. In the example below I used system/logs so if you would go for a different name you need to adjust the code accordingly. And last but not least you need to start the input by pressing the Start input button. Done.

Programming in Lua

Lua and the NodeMCU environment is a beautiful thing. It is simple, powerful and it just rocks. For our little project we'll need to build ourselves a version with bmp085, cjson, wifi and mqtt modules. Then we need to download it to the module and we're all set to start coding in Lua.

The code here initializes WiFi connection, once the connection is established connects to the MQTT server, initializes the BMP085 sensor (here we're using pins D2-sda and D1-scl as per the documentation) and sets up a recurring alarm every second to read the sensor and send GEFL-formatted logs if MQTT has been connected. Easy.

Transferring files to NodeMCU

There are many great ways to send Lua files to the module. I like to use the one written in NodeJS called nodemcu-tool

$ npm install -g nodemcu-tool
$ nodemcu-tool upload init.lua
$ nodemcu-tool terminal

Now press the reset button and your NodeMCU should inform you of 3 things:

  1. That it connected to WiFi network and has an IP address
  2. That it has connected to the MQTT server
  3. That it is sending logs to MQTT server
There is not much more to it. Give it a try and if you stumble upon any challenges getting it to work feel free to leave a comment.

Happy logging!