Our Blog

Ongoing observations by End Point people

Cloudflare and Vue SSR; Client Hydration Failures

By David Christensen
June 11, 2019

Camera and instant photos

Photo by freestocks, used under CC0 1.0

I recently worked on getting a client’s Vue application converted to use Server Side Rendering (SSR). SSR works by generating the app’s initial HTML structure using a server-side process and then using client-side JavaScript to initialize or “hydrate” the application state on the client-side.

This worked out well in development and testing, however when it came time to roll things out to production, we ended up with a non-functioning application. While the server-rendered content was displaying inline, the client hydration piece was failing, and I was seeing browser console errors that I had never encountered before:

The error in Chrome:

chunk-vendors.342a7610.js:21 Uncaught DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.
...

The error in Safari:

[Error] HierarchyRequestError: The operation would yield an incorrect node tree.
    get (chunk-vendors.342a7610.js:27:30686)
    er (chunk-vendors.342a7610.js:27:30565)
    Le (chunk-vendors.342a7610.js:27:27806)
    xe (product-listing.0773c46e.js:1:18553)
[Error] TypeError: undefined is not an object (evaluating 't.$scopedSlots') — chunk-vendors.342a7610.js:27:27998
    on (chunk-vendors.342a7610.js:27:12025)
    rn (chunk-vendors.342a7610.js:27:11937)
    nn (chunk-vendors.342a7610.js:27:11584)
    (anonymous function) (chunk-vendors.342a7610.js:27:12759)
    fn (chunk-vendors.342a7610.js:27:12135)
    promiseReactionJob

Since the client hydration was failing, this resulted in a non-functioning front-end application which we had to quickly roll back. I’d scratched my head over this quite a bit, as this had been well-tested in development and staging.

After testing direct access to the origin server via /etc/hosts modification, we determined that the server itself was returning content that was working fine, so this pointed to something about the caching layer.

The errors being generated were similar to errors I’d...


vue cloudflare javascript

Vue.js Remote Devtools Review

By Patrick Lewis
June 1, 2019

Wrenches Photo by Marco Verch, used under CC BY 2.0

Most Vue.js developers will be familiar with Vue.js devtools in the form of Chrome or Firefox browser extensions/addons. The Vue.js devtools integrate nicely into Chrome and Firefox’s native developer tools in the form of a new ‘Vue’ tab that provides a developer with the ability to browse their component hierarchy, investigate the state of their application’s Vuex store, and several other useful features.

I was a longtime Safari user who eventually became disappointed with its limited extension support (as compared to Chrome or Firefox-based browsers); there was once a Safari version of Vue.js devtools that required some manual installation, but development on that version ended back in early 2018.

An alternative for Safari users, or developers who want to debug Vue.js applications running on other clients such as mobile devices, is the standalone vue-remote-devtools app. vue-remote-devtools is an Electron app that runs in its own window and is loaded in a Vue.js application via a remote connection. I was curious to see how the developer experience of using vue-remote-devools compared to the Chrome browser extension that I was familiar with.

Installation of vue-remote-devtools was simple, with just a single yarn global add @vue/devtools command. Once installed, I was able to run the app with a vue-devtools command which opened a new window on my desktop:

Vue.js remote devtools window

Then it was a matter of updating my Vue.js application to connect to Vue.js remote devtools running locally on my laptop. I added the <script src="http://localhost:8098"></script> tag to my application’s index page as described in the vue-remote-devtools documentation. When I loaded my Vue.js application in Safari I was confronted with a new problem: a Content-Security-Policy error preventing the browser from connecting to local port 8098:

Browser console error

My Vue.js application is served from a Rails application via webpacker and already had a CSP in place, so it was relatively...


vue browsers tools

GraphQL — An Alternative to REST

By Zed Jensen
May 11, 2019

Banner

GraphQL has become more and more popular recently as an alternative to traditional RESTful APIs since it was released as open source by Facebook in 2015. According to the GraphQL website, it is “a query language for APIs and a runtime for fulfilling those queries with your existing data”. In this blog post, I’ll go over some of what makes GraphQL different from other API solutions, and then show how to get a GraphQL API up and running so you can try it out yourself!

GraphQL is designed to fit on top of your database layer. With the help of libraries like Apollo GraphQL, it can be used with many different databases. Some of the main differences between GraphQL and more traditional RESTful APIs include:

  • GraphQL uses one endpoint. Most traditional APIs use an endpoint for each type of data; in my example, you’d probably have one each for users (/user), posts (/post) and comments (/comment). Each of these would return some JSON with the data you want. GraphQL, on the other hand, lives at one endpoint (usually /graphql) and changes what it returns based on what you ask for, as detailed in the next point.

  • You can get multiple types in one request. For instance, if you want to get information about an author plus all of their posts, instead of making a request for the author and a request for posts, you do just one request for the author and specify that you’d like their posts as well:

query {
  user(id: "12345") {
    name
    posts {
      title
      body
    }
  }
}
  • You decide which parts of the data you want. Traditional REST APIs give you data based on which endpoint you’re querying (/post/:id, /user/:id, etc.), and the format of the data is generally the same. For instance, no matter which id you ask for at /posts/:id, you’ll always get something that looks like this back:
{
  "id":"123",
  "name":"Smash Mouth",
  "joined":"1994"
}

But what if we don’t need to know when they joined right now? Another example that better illustrates this problem (and...


graphql database

LinuxFest Northwest 2019

By Josh Williams
May 3, 2019

LinuxFest Northwest Logo Creative Commons Attribution-ShareAlike 4.0 International License

I’m sitting in an airport, writing this in an attempt to stay awake. My flight is scheduled to depart at 11:59 PM, or 2:59 AM in the destination time zone which I’m still used to. This is the first red eye flight I’ve attempted, and I’m wondering why I’ve done this to myself.

I have dedicated a good portion of my life to free, open source software. I’ll occasionally travel to conferences, sitting on long flights and spending those valuable weekends in talks about email encryption and chat bots. I’ve also done this to myself. But even with all this I have zero regrets.

This little retrospective comes courtesy of my experience at LinuxFest Northwest this last weekend in Bellingham, Washington.

Specifically I think it was some of the talks, painting things in broad strokes, that did it. I attended Jon “maddog” Hall’s beard-growing Fifty Years of Unix, and later sat in on the Q&A, which was a bit less technical than expected. So I didn’t ask about the “2038 problem.” But that’s okay.

I felt a little guilty, on one hand, doing these general interest sessions instead of something on a much more specific topic, like ZFS, which would have arguably had a more direct benefit. On the other hand, doing those general interest talks helps me stay grounded, I suppose, helps me keep perspective.

I did attend some more specialized talks, naturally. LFNW was a packed conference, often times there were a number of discussions I would have liked to attend happening at the same time. I’m hoping recordings will become available, or at least slides or other notes will appear. Some of the other talks I attended included, in no particular order:

  • Audio Production on Linux
    Like many other End Pointers, I dabble in a little bit of music. Unlike those other End Pointers, I’ve got no talent for it. Still, I try, and so I listened in on this one to find out a little more about how Jack works. I also caught wind of PipeWire, a project that’s aiming to supplant both PulseAudio and Jack....


conference linux open-source postgres

Introduction to Snapshot Testing Vue Components

By Patrick Lewis
May 2, 2019

Camera and instant photos Photo by freestocks, used under CC0 1.0

Snapshot Testing is one of the features of the Jest testing framework that most interested me when I began researching methods for testing Vue.js applications. Most of my testing experience has involved writing many verbose RSpec unit tests for Rails applications, and the promise of being able to use snapshot tests to cover more of a Vue component’s output while writing less code appealed to me. Snapshot testing does have its critics, so I have been interested to start exploring snapshot tests myself to see if they can be a valuable addition to my testing toolkit, or if they are not worth the effort.

Snapshot testing gets its name from the mechanism used to determine whether tests pass or fail by comparing them to a previously-approved reference point, or “snapshot”. With Jest snapshot testing of Vue components, the snapshot takes the form of a text file with a ‘.snap’ extension stored within a __snapshots__ subdirectory alongside the test files:

Directory structure

I decided to generate a new project using Vue CLI to do my first experiments with snapshot testing in a sample project. The project generated by Vue CLI includes one ‘HelloWorld’ component with a Jest unit test file included, so it made a good starting point for converting over to snapshot testing.

The generated test file was:

// HelloWorld.spec.js
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'

describe('HelloWorld.vue', () => {
  it('renders props.msg when passed', () => {
    const msg = 'new message'
    const wrapper = shallowMount(HelloWorld, {
      propsData: { msg }
    })
    expect(wrapper.text()).toMatch(msg)
  })
})

and I converted it to use a snapshot test by changing one expect line:

// HelloWorld.spec.js
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'

describe('HelloWorld.vue', () => {
  it('renders props.msg when passed', () => {
    const msg = 'new...

vue testing

Facial Recognition Using Amazon DeepLens: Counting Liquid Galaxy Interactions

By Ben Ironside Goldstein
May 1, 2019

I have been exploring the possible uses of a machine-learning-enabled camera for the Liquid Galaxy. The Amazon Web Services (AWS) DeepLens is a camera that can receive and transmit data over wifi, and that has computing hardware built in. Since its hardware enables it to use machine learning models, it can perform computer vision tasks in the field.

The Amazon DeepLens camera

DeepLens

This camera is the first of its kind—likely the first of many, given the ongoing rapid adoption of Internet of Things (IoT) devices and computer vision. It came to End Point’s attention as hardware that could potentially interface with and extend End Point’s immersive visualization platform, the Liquid Galaxy. We’ve thought of several ways computer vision could potentially work to enhance the platform, for example:

  1. Monitoring users’ reactions
  2. Counting unique visitors to the LG
  3. Counting the number of people using an LG at a given time

The first idea would depend on parsing facial expressions. Perhaps a certain moment in a user experience causes people to look confused, or particularly delighted—valuable insights. The second idea would generate data that could help us assess the platform’s impact, using a metric crucial to any potential clients whose goals involve engaging audiences. The third idea would create a simpler metric: the average number of people engaging with the system over a period of time. Nevertheless, this idea has a key advantage over the second: it doesn’t require distinguishing between people, which makes it a much more tractable project. This post focuses on the third idea.

To set up the camera, the user has to plug it into a power outlet and connect it to wifi. The camera will still work even with a slow network connection, though when the connection is slower the delay between the camera seeing something and reporting it is longer. However, this delay was hardly noticable on my home network which has slow-to-moderate speeds of about 17 Mbps down and 33 Mbps up...


machine-learning artificial-intelligence aws liquid-galaxy

Linux desktop Postfix queue for Gmail SMTP

By Jon Jensen
April 30, 2019

Winter view of snow, river, trees, mountains, clouds at Flagg Ranch, Rockefeller Parkway, Wyoming

On a Linux desktop, I want to start sending email through Gmail in a G Suite account using SMTP, rather than a self-hosted SMTP server. Since Gmail supports SMTP, that should be easy enough.

Google’s article Send email from a printer, scanner, or app gives an overview of several options. I’ll choose the “Gmail SMTP server” track, which seems designed for individual user cases like this.

However, since I am using two-factor authentication (2FA) on this Google account — as we should all be doing now for all accounts wherever possible! — my Gmail login won’t work for SMTP because the clients I am using don’t have a way to supply the 2FA time-based token.

Google’s solution to this is to have me generate a separate “App Password” that can sidestep 2FA for this limited purpose: Set up an App Password.

That works fine, but the app password is a randomly-generated 16-letter password that is not amenable to being memorized. For security reasons, my mail client doesn’t cache passwords between sessions, so I have to look it up and enter it each time I start the mail client. That’s generally only once per day for me, so it’s not a big problem, but it would be nice to avoid.

I also want other local programs — such as cron jobs, development projects underway, etc. — to be able to send mail out through my Gmail account. How can I do that, ideally without teaching each one separately how to do it?

As a server operating system at heart, Linux of course has many SMTP servers that can intermediate by acting as a local SMTP server, queue, and sending client. Such a server could have my Gmail password configured and stored under a separate user account, giving a bit more isolation from my main desktop user.

What local SMTP program to use?

esmtp

I first tried using the lightweight and ephemeral esmtp since I had already used it on my desktop computer to forward email through an SSH tunnel. I wasn’t able to get it working with Gmail, which could easily have been operator error...


sysadmin email linux

Job opening: Linux system administration and DevOps remote engineer

By Jon Jensen
April 18, 2019

computer monitors behind silhouetted head
Photo by Kevin Horvat on Unsplash

(This position has been filled.)

We are looking for a full-​time, salaried engineer to work during business hours in UTC-10 to UTC-6 (somewhere between Hawaii Time and Mountain Time) in the fun space where operations and development overlap!

End Point is a 23-​year-old Internet technology consulting company based in New York City, with about 50 employees, most working remotely from home offices. We collaborate using SSH, GitLab, GitHub, chat, video conferencing, and good old email and phones.

We serve many development and hosting clients ranging from small family businesses to large corporations.

What you will be doing:

  • Remotely set up and maintain Linux servers (mostly RHEL/​CentOS, Debian, and Ubuntu), with custom web applications
  • Audit and improve security, backups, reliability, monitoring
  • Support developer use of major language ecosystems
  • Automate provisioning with Terraform, Ansible, Chef, Puppet, etc.
  • Troubleshoot problems with performance, automation, security
  • Use open source tools and contribute back as opportunity arises
  • Use your desktop OS of choice: Linux, macOS, Windows

What you bring:

Professional experience with Linux system administration and web application support:

  • Cloud providers such as DigitalOcean, Linode, AWS, Azure, Google Cloud, Heroku, etc.
  • Networking
  • TLS and PKI
  • DNS
  • Web servers and HTTP
  • Databases such as PostgreSQL, MySQL, Solr, Elasticsearch, CouchDB, MongoDB, etc.
  • Libraries in Ruby gems, PHP PEAR/​PECL, Python PyPI, Node.js npm, Perl CPAN, Java/​JVM JARs, etc.
  • Security consciousness, and ideally familiarity with PCI DSS, HIPAA, etc.

And just as important:

  • Strong verbal and written communication skills
  • A good remote work environment
  • An eye for detail
  • Tenacity in solving problems
  • Ownership of projects to get things done well
  • Work both independently and as part of a team
  • Focus on customer needs
  • Be part of emergency on-call rotation including weekends
  • Willingness to shift work time after hours...

company jobs devops remote-work
Page 1 of 179 • Next page

Popular Tags


Archive


Search our blog