Workers

Debugging Service Workers and Push with Firefox DevTools

Following the announcement of Web Push in Firefox 44, we’re now delivering the capability to develop and debug service workers and push notifications code with DevTools using Firefox Developer Edition 47.

Here’s a screencast that demonstrates the features described in this post:

Or if you prefer text, keep reading!

about:debugging

Service workers do not behave exactly as normal web workers, and their lifecycle is different, so we can’t show them alongside normal scripts in the Debugger tab of DevTools.

Instead, we’ve added a new dashboard that will collect all registered service workers and shared workers, amongst other debuggable items such as Add-ons.

Therefore, our debugging adventure starts by going to about:debugging in a new tab, and clicking on the Workers tab on the left.

about:debugging interface

Alternatively, you can access this dashboard by going to the Tools ? Web Developer ? Service Workers menu, or by clicking on the toolbar menu, then Developer, and finally Service Workers.

Accessing about:debugging using the application menuAccessing about:debugging with toolbar menu

Dashboard instant updates

The first time we access the dashboard “nothing yet” will be displayed under the Service Workers and Shared Workers sections. These sections will be updated automatically as workers get registered. The displayed buttons will change accordingly, showing Push and Debug if the worker is running, or just a Start button if the worker is registered, but inactive.

Try it! Open about:debugging in one window, and navigate to this simple service worker demo in another window. The service worker will be registered and displayed under the Service Workers section. No need for you to reload the dashboard!

Debugging service workers

To debug a service worker, the worker must already be running. Click on the associated Debug button, or Start the worker if it’s not running yet (as long as it has been registered, and thus is in the about:debugging Dashboard).

This will pop up a new window with the code of the service worker. Here you can do all the usual debugging you would expect: setting breakpoints, step-by-step execution, inspecting variables, etc.

Service Worker debugger pop up window

Push notifications

Code that uses the Web Push API can now be debugged as well, by setting a breakpoint in the listener for the push event of the service worker. When the push notification is received, the debugger will stop at the breakpoint.

Debugger stopped at the push event listener

This is very handy, but sometimes notifications can be delayed for reasons outside of our control, or the network might be temporarily unreachable. Luckily, you can still test code that relies on push events, by pressing the Push button on the worker.

This will send a push payload, and in turn, it will trigger the push event pretty much instantly. You can reduce your development time as you won’t have to wait for the server to deliver the push.

Debugging shared workers

There’s also support for debugging shared workers. The most important difference is that they will show up in their own dedicated section in about:debugging.

Debugging requests (and cached requests)

You can also now distinguish normal network requests from requests cached by the worker. These cached requests are displayed as Service Worker in the Transferred column, instead of displaying the amount of transferred data.

Network panel showing cached requests

Requests initiated by service workers can be intercepted and debugged by setting a breakpoint on the fetch event listener.

Stopping at the fetch event

We can inspect data such as the requested url, http headers, etc., by looking at the event object in the variables list when the debugger stops at the breakpoint.

Wrap up

Hopefully, this provides a good overview of the new features we’re working on.

The reference documentation for about:debugging is on MDN. If you want to learn more about service workers, you should check out the guide to Using Service Workers, and, of course, the Service Workers cookbook, which is loaded with great demos and examples.

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Offline Recipes for Service Workers

“Offline” is a big topic these days, especially as many web apps look to also function as mobile apps.  The original offline helper API, the Application Cache API (also known as “appcache”), has a host of problems, many of which can be found in Jake Archibald’s Application Cache is a Douchebag post.  Problems with appcache include:

  • Files are served from cache even when the user is online.
  • There’s no dynamism: the appcache file is simply a list of files to cache.
  • One is able to cache the .appcache file itself and that leads to update problems.
  • Other gotchas.

Today there’s a new API available to developers to ensure their web apps work properly:  the Service Worker API.  The Service Worker API allows developers to manage what does and doesn’t go into cache for offline use with JavaScript.

Introducing the Service Worker Cookbook

To introduce you to the Service Worker API we’ll be using examples from Mozilla’s new  Service Worker Cookbook!  The Cookbook is a collection of working, practical examples of service workers in use in modern web apps.  We’ll be introducing service workers within this three-part series:

  • Offline Recipes for Service Workers (today’s post)
  • At Your Service for More Than Just appcache
  • Web Push Updates to the Masses

Of course this API has advantages other than enabling offline capabilities, such as performance for one, but I’d like to start by introducing basic service worker strategies for offline.

What do we mean by offline?

Offline doesn’t just mean the user doesn’t have an internet connection — it can also mean that the user is on a flaky network connection.  Essentially “offline” means that the user doesn’t have a reliable connection, and we’ve all been there before!

Recipe:  Offline Status

The Offline Status recipe illustrates how to use a service worker to cache a known asset list and then notify the user that they may now go offline and use the app. The app itself is quite simple: show a random image when a button is clicked.  Let’s have a look at the components involved in making this happen.

The Service Worker

We’ll start by looking at the service-worker.js file to see what we’re caching. We’ll be caching the random images to display, as well as the display page and critical JavaScript resources, in a cache named dependencies-cache:


var CACHE_NAME = 'dependencies-cache';

// Files required to make this app work offline
var REQUIRED_FILES = [
  'random-1.png',
  'random-2.png',
  'random-3.png',
  'random-4.png',
  'random-5.png',
  'random-6.png',
  'style.css',
  'index.html',
  '/', // Separate URL than index.html!
  'index.js',
  'app.js'
];

The service worker’s install event will open the cache and use addAll to direct the service worker to cache our specified files:


self.addEventListener('install', function(event) {
  // Perform install step:  loading each required file into cache
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        // Add all offline dependencies to the cache
        return cache.addAll(REQUIRED_FILES);
      })
      .then(function() {
      	// At this point everything has been cached
        return self.skipWaiting();
      })
  );
});

The fetch event of a service worker is fired for every single request the page makes.  The fetch event also allows you to serve alternate content than was actually requested.  For the purposes of offline content, however, our fetch listener will be very simple:  if the file is cached, return it from cache; if not, retrieve the file from server:


self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        // Cache hit - return the response from the cached version
        if (response) {
          return response;
        }

        // Not in cache - return the result from the live server
        // `fetch` is essentially a "fallback"
        return fetch(event.request);
      }
    )
  );
});

The last part of this service-worker.js file is the activate event listener where we immediately claim the service worker so that the user doesn’t need to refresh the page to activate the service worker. The activate event fires when a previous version of a service worker (if any) has been replaced and the updated service worker takes control of the scope.


self.addEventListener('activate', function(event) {
  // Calling claim() to force a "controllerchange" event on navigator.serviceWorker
  event.waitUntil(self.clients.claim());
});

Essentially we don’t want to require the user to refresh the page for the service worker to begin — we want the service worker to activate upon initial page load.

Service worker registration

With the simple service worker created, it’s time to register the service worker:


// Register the ServiceWorker
navigator.serviceWorker.register('service-worker.js', {
  scope: '.'
}).then(function(registration) {
  // The service worker has been registered!
});

Remember that the goal of the recipe is to notify the user when required files have been cached.  To do that we’ll need to listen to the service worker’s state. When the state has become activated, we know that essential files have been cached, our app is ready to go offline, and we can notify our user:


// Listen for claiming of our ServiceWorker
navigator.serviceWorker.addEventListener('controllerchange', function(event) {
  // Listen for changes in the state of our ServiceWorker
  navigator.serviceWorker.controller.addEventListener('statechange', function() {
    // If the ServiceWorker becomes "activated", let the user know they can go offline!
    if (this.state === 'activated') {
      // Show the "You may now use offline" notification
      document.getElementById('offlineNotification').classList.remove('hidden');
    }
  });
});

Testing the registration and verifying that the app works offline simply requires using the recipe! This recipe provides a button to load a random image by changing the image’s src attribute:


// This file is required to make the "app" work offline
document.querySelector('#randomButton').addEventListener('click', function() {
  var image = document.querySelector('#logoImage');
  var currentIndex = Number(image.src.match('random-([0-9])')[1]);
  var newIndex = getRandomNumber();

  // Ensure that we receive a different image than the current
  while (newIndex === currentIndex) {
    newIndex = getRandomNumber();
  }

  image.src = 'random-' + newIndex + '.png';

  function getRandomNumber() {
    return Math.floor(Math.random() * 6) + 1;
  }
});

Changing the image’s src would trigger a network request for that image, but since we have the image cached by the service worker, there’s no need to make the network request.

This recipe covers probably the most simple of offline cases: caching required static files for offline use.

Recipe: Offline Fallback

This recipe follows another simple use case: fetch a page via AJAX but respond with another cached HTML resource (offline.html) if the request fails.

The service worker

The install step of the service worker fetches the offline.html file and places it into a cache called offline:


self.addEventListener('install', function(event) {
  // Put `offline.html` page into cache
  var offlineRequest = new Request('offline.html');
  event.waitUntil(
    fetch(offlineRequest).then(function(response) {
      return caches.open('offline').then(function(cache) {
        return cache.put(offlineRequest, response);
      });
    })
  );
});

If that requests fails the service worker won’t register since nothing has been put into cache.

The fetch listener listens for a request for the page and, upon failure, responds with the offline.html file we cached during the event registration:


self.addEventListener('fetch', function(event) {
  // Only fall back for HTML documents.
  var request = event.request;
  // && request.headers.get('accept').includes('text/html')
  if (request.method === 'GET') {
    // `fetch()` will use the cache when possible, to this examples
    // depends on cache-busting URL parameter to avoid the cache.
    event.respondWith(
      fetch(request).catch(function(error) {
        // `fetch()` throws an exception when the server is unreachable but not
        // for valid HTTP responses, even `4xx` or `5xx` range.
        return caches.open('offline').then(function(cache) {
          return cache.match('offline.html');
        });
      })
    );
  }
  // Any other handlers come here. Without calls to `event.respondWith()` the
  // request will be handled without the ServiceWorker.
});

Notice we use catch to detect if the request has failed and that therefore we should respond with offline.html content.

Service Worker Registration

A service worker needs to be registered only once. This example shows how to bypass registration if it’s already been done by checking the presence of the navigator.serviceWorker.controller property; if the controller property doesn’t exist, we move on to registering the service worker.


if (navigator.serviceWorker.controller) {
  // A ServiceWorker controls the site on load and therefor can handle offline
  // fallbacks.
  console.log('DEBUG: serviceWorker.controller is truthy');
  debug(navigator.serviceWorker.controller.scriptURL + ' (onload)', 'controller');
}

else {
  // Register the ServiceWorker
  console.log('DEBUG: serviceWorker.controller is falsy');
  navigator.serviceWorker.register('service-worker.js', {
    scope: './'
  }).then(function(reg) {
    debug(reg.scope, 'register');
  });
}

With the service worker confirmed as registered, you can test the recipe (and trigger the new page request) by clicking the “refresh” link: (which then triggers a page refresh with a cache-busting parameter):


// The refresh link needs a cache-busting URL parameter
document.querySelector('#refresh').search = Date.now();

Providing the user an offline message instead of allowing the browser to show its own (sometimes ugly) message is an excellent way of keeping a dialog with the user about why the app isn’t available while they’re offline!

Go offline!

Service workers have moved offline experience and control into a powerful new space.  Today you can use the Service Worker API in Chrome and Firefox Developer Edition.  Many websites are using service workers today as you can see for yourself by going to about:serviceworkers in Firefox Developer Edition;  you’ll see a listing of installed service workers from websites you’ve visited!

about:serviceworkers

The Service Worker Cookbook is full of excellent, practical recipes and we continue to add more. Keep an eye out for the next post in this series, At Your Service for More than Just appcache, where you’ll learn about using the Service Worker API for more than just offline purposes.

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

How fast are web workers?

The next version of Firefox OS, the mobile operating system, will unleash the power of devices by taking full advantage of their multi-core processors. Classically, JavaScript has been executed on a single thread, but web workers offer a way to execute code in parallel. Doing so frees the browser of anything that may get in the way of the main thread so that it can smoothly animate the UI.

A brief introduction to web workers

There are several types of web workers:

They each have specific properties, but share a similar design. The code running in a worker is executed in its own separate thread and runs in parallel with the main thread and other workers. The different types of workers all share a common interface.

Web workers

Dedicated web workers are instantiated by the main process and they can communicate only with it.

Shared workers

Shared workers can be reached by all processes running on the same origin (different browser tabs, iframes or other shared workers).

Service workers

Service workers have gained a lot of attention recently. They make it possible to proxy a web server programmatically to deliver specific content to the requester (e.g. the main thread). One use case for service workers is to serve content while offline. Service workers are a very new API, not fully implemented in all browsers, and are not covered in this article.

Service workers have gained a lot of attention recently. They make it
possible to proxy a web server programmatically to deliver specific
content to the requester (e.g. the main thread). One use case for
service workers is to serve content while offline.
Service workers are a very new API, not fully implemented in all
browsers, and are not covered in this article

In order to verify that web workers make Firefox OS run faster, we need to validate their speed by benchmarking them.

The cost of creating web workers

This article focuses on Firefox OS. All measurement are made on a Flame device, powered by middle-end hardware.

The first set of benchmarks will look at the time it takes to create web workers. To do that, we set up a script that instantiates a web worker and sends a minimal message, to which the worker replies immediately. Once the response is received by the main thread, the time that the operation takes is calculated. The web worker is destroyed and the operation is repeated enough times to get a good idea of how long it takes on average to get a functional web worker. Instantiating a web worker is as easy as:

<code>// Start a worker.
var worker = new Worker('worker-script.js');
 
// Terminate a worker.
worker.terminate();

The same method is applied to the creation of broadcast channel:

// Open a broadcast channel.
var channel = new window.BroadcastChannel('channel-name');
 
// Close a broadcast channel.
channel.close();

Shared workers can’t really be benchmarked here because once they are created, the developer can’t destroy them. The browser is entirely responsible for their lifetime. For that reason, we can’t create and destroy shared workers at will to get a meaningful benchmark.

Web workers take about 40ms to be instantiated. Also, this time is pretty stable with variations of only a few milliseconds. Setting up a broadcast channel is usually done within 1ms.

Under normal circumstances, the browser UI is refreshed at a rate of 60 frames per second. This means that no JavaScript code should run longer than the time needed by a frame, i.e., 16.66ms (60 frames per second). Otherwise, you may introduce jankiness and lag in your application.

Instantiating web workers is pretty efficient, but still may not fit in the time allocated for a single frame. That’s why it’s important to create as few web workers as possible and reuse them.

Message latency

A critical aspect of web workers is having fast communication between your main thread and the workers. There are two different ways the main browser thread can communicate with a web worker.

postMessage

This API is the default and preferred way to send and receive messages from a web worker. postMessage() is easy to use:

// Send a message to the worker.
worker.postMessage(myMessage);
 
// Listen to messages from the worker.
worker.onmessage = evt => {
  var message = evt.data;
};

Broadcast Channel

This is a newly implemented API, only available in Firefox at the time of this writing. It lets us broadcast messages to all contexts sharing the same origin. All browser tabs, iframes, or workers served from the same origin can emit and receive messages:

// Send a message to the broadcast channel.
channel.postMessage(myMessage);
 
// Listen to messages from the broadcast channel.
channel.onmessage = evt => {
  var message = evt.data;
};

To benchmark this, we use a script similar to the one described above, except that the web worker is not destroyed and reused at each operation. The time to get a round trip response should be divided by two.

As you might expect, the simple postMessage is fast. It usually takes between 0 to 1ms to send a message, whether to a web or shared worker. Broadcast channel API takes about 1 to 2ms.

Under normal circumstances, exchanging messages with workers is fast and you should not feel too concerned about speed here. However, larger messages can take longer.

The size of messages

There are 2 ways to send messages to web workers:

  • Copying the message
  • Transferring the message

In the first case, the message is serialized, copied, and sent over. In the latter, the data is transferred. This means that the original sender can no longer use it once sent. Transferring data is almost instantaneous, so there is no real point in benchmarking that. However, only ArrayBuffer is transferable.

As expected, serializing, copying, and de-serializing data adds significant overhead to the message transmission. The bigger the message, the longer it takes to be sent.

The benchmark here sends a typed array to a web worker. Its size is progressively increased at each iteration. There is a linear correlation between size of the message and transfer time. For each measurement, we can divide the size (in kilobytes) by the time (in milliseconds) to get the transfer speed in kb/ms.

Typically, on a Flame, the transfer speed is 45 kb/ms for postMessage and 6b/ms using broadcast channel. This means that if you want your message to fit in a single frame, you should keep it under 350MB with postMessage and under 50MB when using the broadcast channel. Otherwise, it may introduce frame drop in your application.

In this benchmark, we use typed arrays, because it makes it possible to determine their size in kilobytes precisely. You can also transfer JavaScript objects, but due to the serialization process, they take longer to post. For small objects, this doesn’t really matter, but if you need to send huge objects, you may as well serialize them to a binary format. You can use something similar to Protocol Buffer.

Web workers are fast if used correctly

Here is a quick summary of various benchmarks related to web workers, as measured on a Flame:

Operation Value
Instantiation of a web worker 40ms
Instantiation of a broadcast channel 1ms
Communication latency with postMessage 0.5ms
Communication latency with broadcast channel 1.5ms
Communication speed with postMessage 45kB/ms
Communication speed with broadcast channel 6kB/ms
Maximum message size with postMessage 350MB
Maximum message size with broadcast channel 50MB

Benchmarking is the only way to make sure that the solution you are implementing is fast. This process takes much of the guesswork out of web development.

If you want to run these benchmarks on a specific device, the app I built to make these measurements, web workers benchmark, is open source. You are also welcome to contribute by submitting new types of benchmarks.

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Interview with Micah Elizabeth Scott, winner of the Web Workers Dev Derby

Micah Elizabeth ScottMicah Elizabeth Scott won the Web Workers Dev Derby with Zen photon garden, her impressive (and fun) interactive web raytracer. Recently, I had the chance to learn more about Micah: her work, her ambitions, and her thoughts on the future of web development.

The interview

How did you become interested in web development?

I’ve been into building things for as long as I can remember. I love
making things, and I’ll often learn new tools just for the sake of
giving myself a different set of challenges and constraints to work
with. My first big web project was an early collaboration tool for
open source development, dubbed “CIA” because it spies on your source
code commits.

Can you tell us a little about how Zen photon garden works?

Zen photon garden is a type of raytracer, which is to say it simulates
the path that individual rays of light take as they bounce around in a
scene. It’s a two-dimensional raytracer though, which opens up kind of
a neat new possibility for visualizing how light works.

A traditional three-dimensional raytracer traces rays “backwards”,
casting rays out from each pixel on a virtual camera, bouncing it off
of the objects in your scene, until it finally reaches a source of
light. Each pixel of the scene comes about by counting, on average,
how many photons would reach that portion of the virtual camera.

In Zen photon garden, light rays emanate from a lamp and move along
the image plane in two dimensions. Instead of visualizing the single
point where a ray reaches the camera, I visualize the entire ray as it
bounces through the scene. Each ray turns into a sequence of line
segments, beginning at the light source and bouncing off of any number
of objects before it’s eventually absorbed. This process repeats
hundreds of thousands of times, and the image you see is a statistical
average of these many light rays.

The inner loop of Zen photon garden is quite specialized. For each
light ray, I need to trace its path by intersecting it with the
objects in the scene, and each segment of this path is visualized by
drawing an anti-aliased line into a high-dynamic-range 32-bit
accumulation buffer. After tracing a bunch of these rays, the
high-dynamic-range buffer is mapped to an 8-bit-per-channel image
according to the current camera exposure setting, and that image is
drawn to a Canvas.

These anti-aliased lines need to be fast and very high quality. Any
errors in the uniformity of the line’s brightness, for example, will
affect the smoothness of the final image. To get the combination of
speed and accuracy I need, this line drawing algorithm is implemented
in pure Javascript by a pool of Web Worker threads. This pool has to
be managed carefully so that the app can draw with high throughput
when you leave it alone, but it can still respond with low latency
when you’re interactively adding objects to the scene.

What was your biggest challenge in developing Zen photon garden?

The hardest part of implementing Zen photon garden was making it run
as fast as possible on all of the latest web browsers. Thankfully
these days it’s relatively easy to write an app that runs on all
browsers, but making it run optimally is tricky when your application
is CPU-bound. Small changes to the inner loops would cause big
differences in how well each Javascript engine’s optimizer performs.
This required a lot of trial and error, and a few trips back to the
drawing board.

What makes the web an exciting platform for you?

To me the killer feature of the web is its universality. Modern web
browsers are nearly ubiquitous, and it’s the fastest way to take a
weird new experimental concept and get it into people’s hands right
now. As someone who loves exploring the intersection of art and
technology, this means it’s finally possible to send your friends a
link to your latest art project without having to worry about what
operating system they’re using or whether they have the right library
dependencies installed.

What new web technologies are you most excited about?

WebGL is really exciting to me, but as someone who used to write
graphics drivers and worry about security for a living it also kind of
terrifies me!

The web technology I’m most excited about would have to be asm.js
actually. I’ve always enjoyed getting my hands dirty with low-level
graphics code, and even in today’s world of GPU acceleration and
high-level 2D canvas APIs, I still find plenty of reasons to push
pixels. Having a way to get near-native performance in a very reliable
way across all major browsers would open up some great new creative
possibilities, and I’m excited to see where that leads.

If you could change one thing about the web, what would it be?

It’d be great if we could find a way to ease the tension between those
who see the web as a content platform and those who see it as a
software operating system. Right now it feels like HTML is too
unwieldy to be a document markup language, and it’s just barely
starting to get the services you’d expect from a modern operating
environment.

Do you have any advice for other ambitious web developers?

Plan to prototype a lot of things, keep the ideas that stick, and
throw the rest away. Respect the web as a platform, and try to be
playful about exploring its margins. Understand but don’t begrudge the
ways in which web programming is different from other kinds of
programming.

Further reading

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Custodial Workers

Mobile, newtoday.jpg Install/Maint/Repair Immediate opening for full or part time Custodial Workers Experience preferred Call Julie to apply at (850 )982-1150 web ID#34166243 text fl66243 to 56654 View full post on Monster Job Search Results (mobile)

View full post on WebProJobs.org

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

MOBILE CRISIS INTERVENTION WORKERS

PA-KITTANNING, PART-TIME MOBILE CRISIS INTERVENTION WORKERS WANTED. MUST HAVE A BACHELORS IN HUMAN SERVICES FIELD. CONTACT DAVID MIELE AT ARMSTRONG-INDIANA MH/MR AT 724-548-3451, MONDAY-FRIDAY, 8:30 A.M. – 3:00 P.M. View full post on Monster Job Search Results (mobile)

View full post on WebProJobs.org

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Testers with Workers Compensation, Medicaid or Medicare Experience

CSC Lanham, MD
Job description: …Public Sector. CSC's advanced capabilities include system design and integration, information technology and business process outsourcing, applications software development, Web and application hosting, mission support and management consulting. The company has been recognized as a leader in the… View full post on Dice.com – Web Application

View full post on WebProJobs.org

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)