I recently had several days of extremely frustrating experiences with service workers. Here are a few things I've since learned which would have made my life much easier but which isn't particularly obvious from most of the blog posts and videos I've seen.
I'll add to this list over time – suggested additions welcome in the comments or via twitter.com/rich_harris.
Chrome 51 has some pretty wild behaviour related to console.log
in service workers. Canary doesn't, and it has a load of really good service worker related stuff in devtools.
#!/usr/bin/env bash | |
# https://developers.supportbee.com/blog/setting-up-cucumber-to-run-with-Chrome-on-Linux/ | |
# https://gist.github.com/curtismcmullan/7be1a8c1c841a9d8db2c | |
# https://stackoverflow.com/questions/10792403/how-do-i-get-chrome-working-with-selenium-using-php-webdriver | |
# https://stackoverflow.com/questions/26133486/how-to-specify-binary-path-for-remote-chromedriver-in-codeception | |
# https://stackoverflow.com/questions/40262682/how-to-run-selenium-3-x-with-chrome-driver-through-terminal | |
# https://askubuntu.com/questions/760085/how-do-you-install-google-chrome-on-ubuntu-16-04 | |
# Versions | |
CHROME_DRIVER_VERSION=`curl -sS https://chromedriver.storage.googleapis.com/LATEST_RELEASE` |
import Service from 'path/to/service'; | |
import 'jasmine-ajax' | |
describe('Service', () => { | |
let request, promise; | |
let instance = Service; | |
let payload = {foo:'bar'}; | |
let path = '/path'; | |
let callback = jasmine.createSpy('callback'); |
console.log(1); | |
(_ => console.log(2))(); | |
eval('console.log(3);'); | |
console.log.call(null, 4); | |
console.log.apply(null, [5]); | |
new Function('console.log(6)')(); | |
Reflect.apply(console.log, null, [7]) | |
Reflect.construct(function(){console.log(8)}, []); | |
Function.prototype.apply.call(console.log, null, [9]); | |
Function.prototype.call.call(console.log, null, 10); |
# Define an instrumentation that performs the caching | |
class CachingInstrumentation | |
def instrument(_type, field) | |
return field unless field.metadata.include?(:cache_proc) | |
old_resolver = field.resolve_proc | |
new_resolver = -> (obj, args, ctx) do | |
# Get the caching key | |
cache_key = field.metadata[:cache_proc].call(obj, args, ctx) | |
Vue.js is an amazing framework, which can be as powerful as Angular or React, the two big heavy hitters in the world of front-end frameworks.
However, most of Vue's ease-of-use is due to the use of Observables - a pattern that triggers re-renders and other function calls with the reassignment of a variable.
- Website: https://stimulusjs.org/
- GitHub repo: https://github.com/stimulusjs/stimulus
- Handbook: https://stimulusjs.org/handbook/introduction
- Discourse: https://discourse.stimulusjs.org/
initialize
: once, when the controller is first instantiatedconnect
: anytime the controller is connected to the DOM
If you boil it all down, here is the basic flow through an app, for a single lazy-loaded piece of content. (The whole flow would be repeated for any other piece of lazy loaded content in the app.)
- A section of an existing view has a turbo_frame_tag wrapping a piece of place-holding text or functionality (like a spinner or some text). The options passed to the tag include an id and a src. The src is a url for a controller method.
- There is a view that contains the 'real' content that will replace the placeholder content. It's not a partial. This is because it must correspond to a controller method of the same name. The whole content in this view is wrapped in a turbo_frame_tag, and the id must match the id in the placeholder tag. There should not be a src declared in this tag. The view, of course, could simply call an existing partial from within the turbo_frame_tag.
- The url declared in the src is a route and a controller method that correspond to the view n