Service Workers With Create-React-App


These days Service Workers are the latest craze in web apps. They are specifically in the area of Progressive Web Apps (PWAs). I’m futzing with a React app trying to get my own custom Service Worker logic to run and I hit a snag. Hi, I’m Cliff. You’re probably here because write web apps. (I still think it sounds funny to say “write web apps”. I think of physically writing with a pen and a pad when I say “write” and nobody writes any programming logic with anything other than a source editor… unless you’re extremely hard-core! In which case, I think there should be a contest on the most advanced computer program actually written with traditional tools, like a stone and chisel. Am I still typing under parenthesis?)

Yesterday I realized that the popular automation tool, “Create React App” or CRA for short, was never intended to be used with anything other than some caching service worker logic. If you try to do anything beside offline support you’re probably going to need to “eject”. If you’re new to React, “eject” is the last thing you want to do. To “eject” means to own all of the configuration that CRA offers which means you are now in “I know what I’m doing, don’t tell me nothing!” mode. In short, it’s not a good mode to be in because when you get that far you are basically writing your own Create React App tool.

At any rate, my task was to figure out if/how we could use a service worker to enable some sort of push notification support in our app. I’m still working through the details so I should probably wrap this up and get back to it. Before I close I did wanna share a couple of nuances. First, you won’t be able to easily add your own service worker logic to a react app for a few painful reasons. The registration script, which looks so innocently easy to change on the surface, actually locks you into using ONLY the service worker which is generated by the CRA tool. It looks to see if your browser has support for service workers then it tries to fetch the service worker by name. You can change the name of the file it attempts to fetch but then there’s the wrinkle of how to get a custom Javascript file to be individually pushed to the output folder without being webpack-ed in with the rest of your React files. I hacked one directly into my build output folder which sorta works but then… THEN… there’s this OTHER wrinkle! The JavaScript file, when fetched, has to be served with a Content-type HTTP header that includes “javascript” somewhere in it. Here’s where it’s ugly because there is a noop-serviceworker-middleware plugin included with the dev server and support stuff in webpack which always serves the file with Content-Type equal to “text/plain”. I dug deep in the source and found that it will ONLY use Javascript in the content type if the file name is EXACTLY equal to “service-worker” and this value is a HARD-CODED string! Now I could remove the check from the register ServiceWorker script but it just feels ugly at that point.

Time is going by and I should get back to the salt mill and figure out how to make all of this play nicely together. In the meantime, if you know of any CreateReactApp hax or work-arounds that would make life simpler please speak up!

Hi Super Nintendo Chalmers, I’m Learnding!!!


It was one of those surreal moments when I was looking at some idiomatic JavaScript code illustrating the newer features of the language when I couldn’t follow the syntax. Then it clicked, I had a Ralph Wiggum moment. Hi, I’m Cliff. You’re here because I just learned how to spell cat. I’m here because I like the way the cat meows.

I’ll give you an example of some Redux code that tripped me up:

import React from "react";
import { connect } from "react-redux";
const mapStateToProps = state => {
  return { articles: state.articles };
};

const ConnectedList = ({ articles }) => (
  <ul className="list-group list-group-flush">
    {articles.map(el => (
      <li className="list-group-item" key={el.id}>
        {el.title}
      </li>
    ))}
  </ul>
);

const List = connect(mapStateToProps)(ConnectedList);
export default List;

My understanding was just based on React. In React I could recognize ConnectedList as a functional component, or a function that returns the rendered part of a React component which does not need an entire class definition. I could also make sense of the redux magic that connects the state’s articles object to the articles property of the ConnectedList. What I couldn’t follow was the absence of any props parameter or references in the ConnectedList. I also was a little blurred on the initialization of the List object just prior to the export. It all looked a little foreign to me. Bear in mind, I’m still coming from a “Just Learned 1998-style JavaScript Last Night” background and the whole ECMA6 ES2015 stuff is still taking a minute to bake in. then it just clicked… automatically! I instantly recognized everything that was happening as if I had been working in this environment my entire career! Let me try to decompose this block and explain how I understood it.

ECMA6, destructuring, arrow functions, etc.
There are many new features in ES6 which give you enhanced expressiveness in your code. These features are borrowed from or inspired by similar features in other languages. Having several years of experience in other languages which expose features like closures, default return values, and collection destructuring, I tend to pick up on patterns. For eg. a piece of code that looks like this conveys a certain meaning or intention:

accounts.map.(each => each.name + ', ' + each.phone)

It intends to change a collection of account objects into a collection of strings of name and phone numbers separated by a comma. It doesn’t fit my 1998 JavaScript way of thinking but my RxJava/Groovy/Kotlin/Swift/Python brain pulls pieces from its database and fills in gaps. These gaps are put in place by my early ECMA6 understanding. You see I know ECMA 6 adds a bunch of modern features and semantics but I’m not sure which ones. I know these other technologies include features like map/reduce. They also include other niceties such as being able to define a closure in place, optionally omit the enclosing curly braces, and optionally omit the return keyword. If I look at the outer piece as a vanilla Javascript function call that takes some newer Javascript syntax I get this:

accounts.map.(/*magical Javascript new stuff*/)

That much I can comprehend. It says we are probably using some newer map/reduce coolness to iterate a list of accounts. Nothing too intimidating, right? Now lets take the inner guts or magical Javascript parameter syntax and try to make sense of it.

each => each.name + ', ' + each.phone

This looks a lot like a Closure or anonymous function. It’s weird because there’s nothing around the naked initial each parameter, but that’s okay because many other languages make defining the function parameter with official types and parenthesis optional so maybe it’s optional here too. Also some languages make enclosing curly braces around the function body optional. It’s called syntax sugar. so I’m thinking the curly braces are optional in ECMA6 too. Lastly, other languages make it optional to specify the return keyword. Instead it is accepted in some languages to use the value of the last statement in a function as it’s return value. With that understanding in mind I can read the above as:

(each) => { return each.name + ', ' + each.phone; }

Which actually makes me understand the original single line statement as:

var closure = (each) => { return each.name + ', ' + each.phone; };
accounts.map.(closure);

Now that you get an idea how my multi-language brain operates let’s get back to the first piece of React/Redux magic that threw me. We have this:

const mapStateToProps = state => {
  return { articles: state.articles };
};

Which we understand as a closure or an anonymous function which is assigned to a variable named mapStateToProps. This function takes a state parameter and returns an object with an articles property which is set to the value of the articles property of the given state object. In essence, it merely transforms a state object into an object with a single property which is the articles property from the state.

Next we have this code, which really troubled me:

const List = connect(mapStateToProps)(ConnectedList);

The 2nd set of parenthesis triggered a thought. The Groovy programming language side of my brained jumped in here and said, incorrectly, “Ooh! I know what this is!!!” You can pass a closure parameter to a function outside of the closing parenthesis!!!” Then this part of my brain smiled intently just prior to running off to grab a donut. This was totally incorrect. Instead what’s happening is we are calling a function named connect and passing our anonymous function value as the parameter to this function. The connect function is actually returning a function, which we call in place and pass the ConnectedList react component. So, in actuality, connect is transforming the React functional component into another functional component and it is using the mapStateToProps function to do this.

But wait! What about this piece of code?

const ConnectedList = ({ articles }) => (
  <ul className="list-group list-group-flush">
    {articles.map(el => (
      <li className="list-group-item" key={el.id}>
        {el.title}
      </li>
    ))}
  </ul>
);

It almost looks like how I remember React functional components would look but there’s not props parameter. Instead it uses this weird syntax:

const ConnectedList = ({ articles }) => (
  /*JSX stuff here*/
);

Again, we’re missing enclosing curly braces and a return statement. We can mentally add those and come up with this:

const ConnectedList = ({ articles }) => { return (
  /*JSX stuff here*/
)};

Still there’s the weird parameter definition, “({ articles })”. My Python/Kotlin brain center kicked in and reminded me about object de-structuring. These languages allow you to decompose tuples or objects and literally declare and assign multiple variables in one shot. The pattern looks like this:

var {name, address, zip} = profile;

which is equivalent to:

var name = profile.name, address = profile.address, zip = profile.zip;

This is not the exact syntax from these other language, just pseudo code to illustrate the pattern.What this code does is take the name, address, and zip properties of the profile object and assign them to the name, address, and zip variables respectively. That’s a brief explanation of de-structuring. So maybe what’s happening is the props parameter is being de-structured into an articles variable. With that understanding we can read the original code as:

const ConnectedList = (props) => { 
var {articles} = props;
return (
  /*JSX stuff here*/
)};

This is just a little more syntax sugar that cleans up the noise of what would be a bunch of “props.” references in your code.

That’s a bunch to take in at once but it’s how I was able to make sense of some initial Redux examples without actually looking up the new features from ES6. Ultimately I referred to the new feature list to confirm my understanding but I was able to go a long way on my own.

(This message was brought to you in part by NBCC Community Church in Redwood City. Through constant prayer, Bible study, fellowship, service, and teachings from Pastor hurmon Hamilton one can understand even the most challenging programming environments. Other sponsors advise you to eat your veggies and always get at least 7 hrs of sleep nightly.)