Hello.

I am Paul Kinlan.

A Developer Advocate for Chrome and the Open Web at Google.

Grep your git commit log

Paul Kinlan

Finding code that was changed in a commit

Read More

Paul Kinlan

Trying to make the web and developers better.

RSS Github Medium

Performance and Resilience: Stress-Testing Third Parties by CSS Wizardry

Paul Kinlan

J’étais en Chine il y a quelques semaines pour la journée des développeurs Google et je montrais à tout le monde mon scanner QRCode, cela fonctionnait très bien jusqu’à ce que je passe au mode hors connexion. Lorsque l’utilisateur était hors ligne (ou partiellement connecté), la caméra ne démarrait pas, ce qui signifiait que vous ne pouviez pas prendre de code QR. Il m’a fallu un certain temps pour comprendre ce qui se passait, et il s’avère que j’ai démarré la caméra par erreur lors de mon événement onload et que la demande de Google Analytics était bloquée et non résolue rapidement. C’est ce commit qui l’a corrigé.

Because these types of assets block rendering, the browser will not paint anything to the screen until they have been downloaded (and executed/parsed). If the service that provides the file is offline, then that’s a lot of time that the browser has to spend trying to access the file, and during that period the user is left potentially looking at a blank screen. After a certain period has elapsed, the browser will eventually timeout and display the page without the asset(s) in question. How long is that certain period of time?

It’s 1 minute and 20 seconds.

If you have any render-blocking, critical, third party assets hosted on an external domain, you run the risk of showing users a blank page for 1.3 minutes.

Below, you’ll see the DOMContentLoaded and Load events on a site that has a render-blocking script hosted elsewhere. The browser was completely held up for 78 seconds, showing nothing at all until it ended up timing out.

Lire l’article complet.

Je vous encourage à lire le post car il y a beaucoup de perspicacité.

Chrome Bug 897727 - MediaRecorder using Canvas.captureStream() fails for large canvas elements on Android

Paul Kinlan

Le week-end, je jouais avec un encodeur vidéo à effet Boomerang, vous pouvez le faire fonctionner presque en temps réel (je l’expliquerai plus tard). Je l’ai obtenu sur Chrome sur le Bureau, mais cela ne fonctionnerait jamais correctement sur Chrome sur Android. Voir le code ici.

Cela ressemble à lorsque vous utilisez captureStream () sur un <canvas>Avec une résolution relativement importante (1280x720 dans mon cas), l’API MediaRecorder ne pourra pas encoder les vidéos, elle ne provoquera pas d’erreur et vous ne pourrez pas détecter qu’elle ne peut pas encoder la vidéo à l’avance.

(1) Capture a large res video (from getUM 1280x720) to a buffer for later processing. (2) Create a MediaRecorder with a stream from a canvas element (via captureStream) sized to 1280x720 (3) For each frame captured putImageData on the canvas (4) For each frame call canvasTrack.requestFrame() at 60fps

context.putImageData(frame, 0, 0); canvasStreamTrack.requestFrame();

Demo: https://boomerang-video-chrome-on-android-bug.glitch.me/ Code: https://glitch.com/edit/#!/boomerang-video-chrome-on-android-bug?path=script.js:21:42

What is the expected result?

For the exact demo, I buffer the frames and then reverse them so you would see the video play forwards and backwards (it works on desktop). In generall I would expect all frames sent to the canvas to be processed by the MediaRecorder API - yet they are not.

What happens instead?

It only captures the stream from the canvas for a partial part of the video and then stops. It’s not predicatable where it will stop.

I suspect there is a limit with the MediaRecorder API and what resolution it can encode depending on the device, and there is no way to know about these limits ahead of time.

As far as I can tell this has never worked on Android. If you use https://boomerang-video-chrome-on-android-bug.glitch.me which has a 640x480 video frame it records just fine. The demo works at higher-resolution just fine on desktop.

Lire l’article complet.

Si vous voulez jouer avec la démo qui marche sur les deux, alors cliquez ici

Why Microsoft and Google love progressive web apps | Computerworld

Paul Kinlan

Un bel article sur PWA de Mike Elgan. Je ne suis pas sûr de l’objectif de Microsoft avec PWA, mais je pense que le nôtre est assez simple: nous voulons que les utilisateurs aient accès au contenu et aux fonctionnalités instantanément et d’une manière qu’ils espèrent pouvoir interagir avec ce contenu sur leurs appareils. Le Web doit atteindre tout le monde sur chaque appareil connecté et un utilisateur doit pouvoir accéder à sa modalité préférée, en tant qu’application si c’est ce à quoi il s’attend (mobile, peut-être), ou de la voix sur un assistant, etc.

Nous sommes encore loin du réseau sans tête, cependant, une chose m’a vraiment frappé dans l’article:

Another downside is that PWAs are highly isolated. So it’s hard and unlikely for different PWAs to share resources or data directly.

Lire l’article complet.

Les sites et les applications sur le Web ne sont pas censés être isolés, le Web est linkable, indexable, éphemeral, mais chaque site que nous construisons devient plus silencieux. Nous créons des silos inattendus car la plate-forme ne permet pas facilement aux * utilisateurs * d’importer * facilement * leurs données hors site. Je ne parle pas de RDF ou de quelque chose du genre, les opérations de base telles que copier / coller, glisser-déposer, partager sur site et partager à partir d’un site sont interrompues sur le Web d’aujourd’hui, et c’est avant que nous ne passions à IPC entre les images, travailleurs et des fenêtres.

Building a video editor on the web. Part 0.1 - Screencast

Paul Kinlan

Vous devriez pouvoir créer et éditer des vidéos en utilisant uniquement le Web dans le navigateur. Il devrait être possible de fournir une interface utilisateur semblable à Screenflow qui vous permet de créer une sortie vidéo combinant plusieurs vidéos, images et son en une seule vidéo pouvant être téléchargée vers des services tels que YouTube. Après mon précédent post qui décrit brièvement les exigences de l’éditeur de vidéo, je voulais simplement montrer rapidement, dans un screencast, comment j’ai construit l’enregistreur de webcam, et comment créer un screencast.

Read More

894556 - Multiple video tracks in a MediaStream are not reflected on the videoTracks object on the video element

Paul Kinlan

Le premier numéro que j’ai trouvé en essayant de créer un éditeur de vidéo sur le Web.

J’ai plusieurs flux vidéo (ordinateur de bureau et webcam) et je voulais pouvoir basculer entre les flux vidéo sur un élément vidéo afin de pouvoir basculer rapidement entre la webcam et le bureau et ne pas casser le MediaRecorder.

Il semble que vous devriez pouvoir le faire en basculant la propriété selected sur l'objetvideoTracks du <video>élément, mais vous ne pouvez pas, le tableau de pistes ne contient qu'un seul élément (la première piste vidéo sur le flux multimédia).

What steps will reproduce the problem? (1) Get two MediaStreams with video tracks (2) Add them to a new MediaStream and attach as srcObject on a videoElement (3) Check the videoElement.videoTracks object and see there is only one track

Demo at https://multiple-tracks-bug.glitch.me/

What is the expected result? I would expect videoElement.videoTracks to have two elements.

What happens instead? It only has the first videoTrack that was added to the MediaStream.

Lire l’article complet.

Cas de repro.

window.onload = () => {
  if('getDisplayMedia' in navigator) warning.style.display = 'none';

  let blobs;
  let blob;
  let rec;
  let stream;
  let webcamStream;
  let desktopStream;

  captureBtn.onclick = async () => {

       
    desktopStream = await navigator.getDisplayMedia({video:true});
    webcamStream = await navigator.mediaDevices.getUserMedia({video: { height: 1080, width: 1920 }, audio: true});
    
    // Always 
    let tracks = [...desktopStream.getTracks(), ... webcamStream.getTracks()]
    console.log('Tracks to add to stream', tracks);
    stream = new MediaStream(tracks);
    
    console.log('Tracks on stream', stream.getTracks());
    
    videoElement.srcObject = stream;
    
    console.log('Tracks on video element that has stream', videoElement.videoTracks)
    
    // I would expect the length to be 2 and not 1
  };

};

Building a video editor on the web. Part 0.

Paul Kinlan

Vous devriez pouvoir créer et éditer des vidéos en utilisant uniquement le Web dans le navigateur. Il devrait être possible de fournir une interface utilisateur semblable à Screenflow qui vous permet de créer une sortie vidéo combinant plusieurs vidéos, images et son en une seule vidéo pouvant être téléchargée vers des services tels que YouTube. Ce message est vraiment juste une déclaration d’intention. Je vais commencer le long processus consistant à déterminer ce qui est disponible ou non sur la plate-forme et à voir jusqu’où nous pouvons aller aujourd’hui.

Read More

Barcode detection in a Web Worker using Comlink

Paul Kinlan

Je suis un grand fan des QRCodes, ils sont un moyen très simple et pratique d’échanger des données entre le monde réel et le monde numérique. Depuis quelques années, j’ai un petit projet parallèle appelé QRSnapper & mdash; Eh bien, il porte quelques noms, mais c’est celui sur lequel j’ai opté pour & mdash; qui utilise l’API getUserMedia pour extraire des données en direct de la caméra de l’utilisateur afin de lui permettre de rechercher les codes QR en temps quasi réel.

Le but de l’application était de maintenir 60 images par seconde dans l’interface utilisateur et de détecter le code QR de manière quasi instantanée. Cela signifiait que je devais mettre le code de détection dans un Web Worker (élément plutôt standard). Dans cet article, je voulais simplement partager rapidement la façon dont j’ai utilisé comlink pour simplifier massivement la logique du travailleur.

qrclient.js

import * as Comlink from './comlink.js';

const proxy = Comlink.proxy(new Worker('/scripts/qrworker.js')); 

export const decode = async function (context) {
  try {
    let canvas = context.canvas;
    let width = canvas.width;
    let height = canvas.height;
    let imageData = context.getImageData(0, 0, width, height);
    return await proxy.detectUrl(width, height, imageData);
  } catch (err) {
    console.log(err);
  }
};

qrworker.js (travailleur Web)

import * as Comlink from './comlink.js';
import {qrcode} from './qrcode.js';

// Use the native API's
let nativeDetector = async (width, height, imageData) => {
  try {
    let barcodeDetector = new BarcodeDetector();
    let barcodes = await barcodeDetector.detect(imageData);
    // return the first barcode.
    if (barcodes.length > 0) {
      return barcodes[0].rawValue;
    }
  } catch(err) {
    detector = workerDetector;
  }
};

// Use the polyfil
let workerDetector = async (width, height, imageData) => {
  try {
    return qrcode.decode(width, height, imageData);
  } catch (err) {
    // the library throws an excpetion when there are no qrcodes.
    return;
  }
}

let detectUrl = async (width, height, imageData) => {
  return detector(width, height, imageData);
};

let detector = ('BarcodeDetector' in self) ? nativeDetector : workerDetector;
// Expose the API to the client pages.
Comlink.expose({detectUrl}, self);

J’aime vraiment Comlink, je pense que c’est un changeur de jeu d’une bibliothèque, en particulier lorsqu’il s’agit de créer du code JavaScript idiomatique qui fonctionne sur plusieurs threads. Enfin, il est intéressant de noter que l’API de détection de code à barres native peut être exécutée à l’intérieur d’un serveur, de sorte que toute la logique soit encapsulée à l’écart de l’UI.

Lire l’article complet.

Running FFMPEG with WASM in a Web Worker

Paul Kinlan

J’aime FFMPEG.js, c’est un outil soigné compilé avec asm.js` qui me permet de créer des applications Web JS pouvant éditer rapidement des vidéos. FFMPEG.js fonctionne également avec les travailleurs Web afin que vous puissiez encoder des vidéos sans bloquer le fil principal.

J’aime aussi Comlink. Comlink me permet d’interagir facilement avec les travailleurs Web en exposant des fonctions et des classes sans avoir à traiter avec une machine à états postMessage complexe.

J’ai récemment eu à combiner les deux ensemble. J’essayais d’essayer de faire exporter FFMPEG vers Web Assembly (ça marche - oui) et je voulais nettoyer tout le travail postMessage du projet actuel FFMPEG.js. Le code ci-dessous ressemble à ceci: je pense que c’est assez chouette. Nous avons un opérateur qui importe ffmpeg.js et comlink. Il expose simplement l’interface ffmpeg. La page Web qui charge l’agent et utilise ensuite comlink pour créer un proxy pour l’API ffmpeg.

Soigné.

worker.js

importScripts('https://cdn.jsdelivr.net/npm/comlinkjs@3.0.2/umd/comlink.js');
importScripts('../ffmpeg-webm.js'); 
Comlink.expose(ffmpegjs, self);

client.html

let ffmpegjs = await Comlink.proxy(worker);
let result = await ffmpegjs({
   arguments: ['-y','-i', file.name, 'output.webm'],
   MEMFS: [{name: file.name, data: data}],
   stdin: Comlink.proxyValue(() => {}),
   onfilesready: Comlink.proxyValue((e) => {
     let data = e.MEMFS[0].data;
     output.src = URL.createObjectURL(new Blob([data]))
     console.log('ready', e)
   }),
   print: Comlink.proxyValue(function(data) { console.log(data); stdout += data + "\n"; }),
   printErr: Comlink.proxyValue(function(data) { console.log('error', data); stderr += data + "\n"; }),
   postRun: Comlink.proxyValue(function(result) { console.log('DONE', result); }),
   onExit: Comlink.proxyValue(function(code) {
     console.log("Process exited with code " + code);
     console.log(stdout);
   }),
});

J’aime beaucoup la manière dont les modules compilés par Comlink, Workers et WASM peuvent jouer ensemble. Je reçois du code JavaScript idiomatique qui interagit directement avec le module WASM et qui s’exécute à partir du thread principal.

Lire l’article complet.

Translating a blog using Google Cloud Translate and Hugo

Paul Kinlan

Je suis récemment rentré d’un voyage en Inde pour assister à l’événement Google4India (rapport prochainement) et rencontrer de nombreuses entreprises et développeurs. L’un des changements les plus intéressants abordés concernait la demande de contenu dans la langue des utilisateurs du pays et était particulièrement visible dans tous les produits de Google, allant de la recherche dans la langue de l’utilisateur à la recherche de contenu, et aussi de le lire aux utilisateurs sous forme de texte ou de voix.

Tout le voyage m’a fait réfléchir. Mon blog est construit avec Hugo. Hugo prend désormais en charge le contenu écrit en plusieurs langues. Hugo est entièrement statique, la création de nouveaux contenus consiste donc simplement à créer un nouveau fichier et à laisser le système de compilation faire de la magie. Alors peut-être que je peux créer quelque chose qui rendra mon contenu plus accessible à davantage de personnes en exécutant mon contenu statique via un outil de traduction, car la traduction humaine de contenu est très coûteuse.

Quelques heures avant mon retour au Royaume-Uni, j’ai créé un petit script qui prendra mes fichiers de démarques et les exécutera via Google Cloud Translate pour créer rapidement un fichier. traduction de la page que je peux ensuite héberger rapidement. La solution complète est présentée ci-dessous. C’est un processeur relativement basique, il ignore le préambule d’Hugo, il ignore le «code» et ignore les guillemets - mon hypothèse était que ceux-ci sont toujours destinés à rester tels qu’ils ont été écrits.

Remarque: il semble que notre logiciel d’apprentissage pour les traductions soit important, il est donc important de marquer votre page pour que les outils d’apprentissage n’utilisent pas le contenu Google Translated comme entrée dans ses algorithmes.

// Imports the Google Cloud client library
const Translate = require('@google-cloud/translate');
const program = require('commander');
const fs = require('fs');
const path = require('path');

program
  .version('0.1.0')
  .option('-s, --source [path]', 'Add in the source file.')
  .option('-t, --target [lang]', 'Add target language.')
  .parse(process.argv);

// Creates a client
const translate = new Translate({
  projectId: 'html5rocks-hrd'
});

const options = {
  to:  program.target,
};

async function translateLines(text) {
  if(text === ' ') return ' ';
  const output = [];
  let results = await translate.translate(text, options);

  let translations = results[0];
  translations = Array.isArray(translations)
    ? translations
    : [translations];

  translations.forEach((translation, i) => {
    output.push(translation)
  });

  return output.join('\n');
};

// Translates the text into the target language. "text" can be a string for
// translating a single piece of text, or an array of strings for translating
// multiple texts.
(async function (filePath, target) {

  const text = fs.readFileSync(filePath, 'utf8');

  const lines = text.split('\n');
  let translateBlock = [];
  const output = [];

  let inHeader = false;
  let inCode = false;
  let inQuote = false;
  for (const line of lines) {
    // Don't translate preampble
    if (line.startsWith('---') && inHeader) { inHeader = false; output.push(line); continue; }
    if (line.startsWith('---')) { inHeader = true; output.push(line); continue; }
    if (inHeader) { output.push(line); continue; }

    // Don't translate code
    if (line.startsWith('```') && inCode) { inCode = false; output.push(line); continue; }
    if (line.startsWith('```')) { inCode = true; output.push(await translateLines(translateBlock.join(' '))); translateBlock = []; output.push(line); continue; }
    if (inCode) { output.push(line); continue; }

    // Dont translate quotes
    if (inQuote && line.startsWith('>') === false) { inQuote = false; }
    if (line.startsWith('>')) { inQuote = true; output.push(await translateLines(translateBlock.join(' '))); translateBlock = []; output.push(line); }
    if (inQuote) { output.push(line); continue; }

    if (line.charAt(0) === '\n' || line.length === 0) { output.push(await translateLines(translateBlock.join(' '))); output.push(line); translateBlock = []; continue;} 

    translateBlock.push(line);
  }

  if(translateBlock.length > 0) output.push(await translateLines(translateBlock.join(' ')))

  const result = output.join('\n');
  const newFileName = path.parse(filePath);
  fs.writeFileSync(`content/${newFileName.name}.${target}${newFileName.ext}`, result);

})(program.source, program.target);

Dans l’ensemble, je suis très content du processus. Je comprends que la traduction automatique n’est pas parfaite mais je pense que je peux étendre la portée de mon contenu aux personnes qui pourraient chercher dans leur propre langue et non en anglais. Je peux augmenter la surface de découverte de mon contenu et, espérons-le, aider davantage gens.

Il faudra un certain temps pour voir si cela aide réellement les gens, alors je vais rapporter quand j’ai plus de données …. Maintenant, pour exécuter mon script sur plus de mon site :)

Apple - Web apps - All Categories

Paul Kinlan

Rappelez-vous que lorsque Web Apps était * une * méthode recommandée pour utiliser des applications sur l’iPhone?

What are web apps? Learn what they are and how to use them.

Lire l’article complet.

Vers 2013, Apple a commencé à rediriger le répertoire / webapps / top-level vers / iphone /

Le fait est que le répertoire était en fait très bon, beaucoup d’applications fonctionnent encore. Cependant, en regardant l’AppStore, cela résolvait beaucoup plus de problèmes que les développeurs avaient: Une meilleure découverte et une meilleure recherche en particulier parce que l’AppStore était directement sur l’appareil. L’AppStore commençait également à introduire des éléments qui éliminaient les frictions des utilisateurs et des développeurs, notamment en ce qui concerne les paiements.

Gears API

Paul Kinlan

Je rédige un article sur les premières API Web mobiles et Alex Russell m’a rappelé Google Gears

Gears modules include:

  • LocalServer Cache and serve application resources (HTML, JavaScript, images, etc.) locally
  • Database Store data locally in a fully-searchable relational database
  • WorkerPool Make your web applications more responsive by performing resource-intensive operations asynchronously

Lire l’article complet.

Je pense qu’il est intéressant de voir qu’AppCache et WebSQL, Geolocation et WebWorkers sont issus des idées de Google Gears et que seules les deux dernières ont réellement survécu. WebSQL n’a jamais été largement pris en charge et a été remplacé par IndexedDB; et AppCache remplacé par ServiceWorker

RSS Feed to Google Chat Webhook using Cloud Functions for Firebase and Superfeedr

Paul Kinlan

Nous utilisons beaucoup Google Chat pour communiquer au sein de notre équipe. Nous créons également beaucoup de contenu accessible via les flux RSS, nous avons même un flux d’équipe que vous pouvez voir tous. Ce n’est que récemment que j’ai découvert qu’il était assez facile de créer un simple post-only bot via WebHooks et que m’a donné l’idée, je peux créer un service simple qui interroge les flux RSS et les envoie ensuite à notre webhook qui peut poster directement dans notre chat d’équipe.

C’était assez simple au final, et j’ai inclus tout le code ci-dessous. J’ai utilisé les fonctions de Firebase - je pense que c’est aussi simple sur d’autres sites fonctionnels que le service - et Superfeedr. Superfeedr est un service qui peut écouter les pings de Pubsubhubbub (maintenant WebSub) et interroge également les flux RSS pour lesquels Pubsub n’a pas été configuré. Ensuite, lorsqu’il trouve un flux, il envoie une requête ping à une URL configurée (dans mon cas, ma fonction Cloud dans Firebase) avec une représentation XML ou JSON des données de flux nouvellement trouvées. Il vous suffit d’analyser les données et de faire quelque chose.

const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors');
const fetch = require('node-fetch');
const app = express();

// Automatically allow cross-origin requests
app.use(cors({ origin: true }));

app.post('/', (req, res) => {
  const { webhook_url } = req.query;
  const { body } = req;
  if (body.items === undefined || body.items.length === 0) {
    res.send('');
    return;
  }

  const item = body.items[0];
  const actor = (item.actor && item.actor.displayName) ? item.actor.displayName : body.title;

  fetch(webhook_url, {
    method: 'POST',
    headers: {
      "Content-Type": "application/json; charset=utf-8",
    },
    body: JSON.stringify({
      "text": `*${actor}* published <${item.permalinkUrl}|${item.title}>. Please consider <https://twitter.com/intent/tweet?url=${encodeURIComponent(body.items[0].permalinkUrl)}&text=${encodeURIComponent(body.items[0].title)}|Sharing it>.`
    })  
  }).then(() => {
    return res.send('ok');
  }).catch(() => {
    return res.send('error')
  });
})
// Expose Express API as a single Cloud Function:
exports.publish = functions.https.onRequest(app);

Lire l’article complet.

J’ai été surpris et ravi de la facilité d’installation.

Using HTTPArchive and Chrome UX report to get Lighthouse score for top visited sites in India.

Paul Kinlan

A quick dive in to how to use Lighthouse,HTTPArchive and Chrome UX report to try and understand how users in a country might experience the web.

Read More

Getting Lighthouse scores from HTTPArchive for sites in India.

Paul Kinlan

A quick dive in to how to use Lighthouse to try and understand how users in a country might experience the web.

Read More

'Moving to a Chromebook' by Rumyra's Blog

Paul Kinlan

Ruth John a déménagé à Chrome OS (temporairement):

The first thing, and possibly the thing with the least amount of up to date information out there, was enabling Crostini. This runs Linux in a container on the Chromebook, something you pretty much want straight away after spending 15 minutes on it.

I have the most recent Pixel, the 256GB version. Here’s what you do.

  • Go to settings.
  • Click on the hamburger menu (top left) - right at the bottom it says ‘About Chrome OS’
  • Open this and there’s an option to put your machine into dev mode
  • It’ll restart and you’ll be in dev mode - this is much like running Canary over Chrome and possibly turning on a couple of flags. It may crash, but what the hell you’ll have Linux capabilities ��
  • Now you can go back into Settings and in regular settings there’s a ‘Linux apps’ option. Turn this on. It’ll install Linux. Once this is complete you’ll have a terminal open for you. Perfect

Lire l’article complet.

Ruth a bien écrit sur le passage à Chrome OS parce que sa machine principale est tombée en panne.

J’ai déménagé à Chrome OS à plein temps il y a 4 mois (avant Google I / O) et je ne suis passé que sur Mac parce que j’ai cassé mon PixelBook (maintenant corrigé).

Pour moi, c’est l’une des meilleures machines de développement Web disponibles aujourd’hui. C’est le seul appareil sur lequel je peux tester le «vrai mobile» - vous pouvez installer Chrome sur Mobile, Firefox Mobile, Samsung Browser, Brave, etc. via la plate-forme ARC. Crostini est également un changement de jeu pour Chrome OS, car il apporte une grande partie de l’écosystème Linux App à Chrome OS et il commence vraiment à combler une énorme lacune d’application pour moi sur Chrome OS; J’ai Firefox, vim, git, VS Code, Node, npm, tous mes outils de construction, GIMP et Inkscape … Cela ne veut pas dire que ce soit parfait, Crostini pourrait être plus rapide, ce n’est pas encore accéléré par GPU et il pourrait être plus intégré au gestionnaire de fichiers etc, et enfin le PixelBook a vraiment besoin de plus de ports physiques - je peux y attacher deux écrans 4k, mais je ne peux pas charger en même temps.

Je pense que le récapitulatif de Ruth est tout à fait exact, le PixelBook est une machine coûteuse, mais je suis très enthousiaste à l’idée de voir cela devenir de plus en plus nombreux (en particulier ceux à des prix nettement inférieurs).

Would I pay full price for it? I’m not sure I would pay full price for anything on the market right now. Point me in the direction of a system that will run my graphics software and makes a good dev machine (with minimal setup) and lasts more than 18 months, point me in the direction of a worthy investment and I will pay the money.

Ouaip.

PWA: Progressive Web All-the-things

Paul Kinlan

PWA. Applications Web progressives. Frances Berriman et Alex Russell ont inventé le terme “applications web progressives” en 2015 avec ce que je pense être un post séminal “Applications Web progressives: échapper des onglets sans perdre notre âme”. 3 ans plus tard, nous avons parcouru un long chemin. Depuis un ensemble de technologies - Service Worker, Manifest, Ajouter à l’écran d’accueil, Web Push - initialement implémentées dans un seul moteur de navigateur, à une marque qui a commencé à s’imposer dans le secteur avec les entreprises et les développeurs, et tous les principaux les fournisseurs de navigateurs implémentant la majorité de la pile ‘PWA’.

Read More

What are the pain points for web designers? - Mustafa Kurtuldu

Paul Kinlan

Mustafa écrit:

Tooling is complicated, we are a tooling focused industry, and they change so much. I have used maybe rough eight different tools, from Photoshop to Sketch. That’s before we add prototyping tools to the mix. This may be something we just have to accept. After all, type standards only really started to settle in the 90s, and typography is a 500-year-old discipline.

Designers are still finding it difficult to prove the importance of the process. I think this is something that we have to take on board: to learn how to educate and not just expect everyone to trust us by default. That takes time — perhaps using scenario-based design or design workshops like a design sprint would help. Getting non-designers to observe users while using a prototype they created is one of the best experiences I have seen in this field.

Cross-browser support is lacking crucial features. Designers need to understand developer tooling, to better scope out what is possible. I think using paired programming or the design process described above can help.

Responsive design is still challenging. I think this is in part due to the tools we use; I would love Chrome Design Tools that would help turn the browser into a creative tool. This space is where I think the next evolutionary step for site and web app creation is at. Mozilla is doing some fantastic work in this space, with their layout and shapes tooling.

All in all the challenges that we face seem to be all the age-old ones. Process, tools, and respect.

Lire l’article complet.

J’ai trouvé cette publication très intéressante qui complète également un article que j’ai écrit sur les défis pour les développeurs Web. Il n’est pas surprenant que le navigateur soit un problème, mais ce qui est encore préoccupant, c’est que la construction pour IE11 est toujours quelque chose qui retient l’industrie. De même, Mustafa souligne qu’il y a toujours un problème avec l’outillage autour de Responsive Design et que l’accent mis sur une seule solution réactive conduit toujours à ce qui suit (c’est dans le post de Mustafa):

Designing once and using everywhere is still hard to reach ambition.

C’est un problème avec lequel nous sommes tous encore aux prises. D’une part, nous voulons que chacun construise une solution réactive capable de servir tout le monde sur chaque facteur de forme de l’appareil, d’autre part, le contexte utilisateur est important et, souvent, l’utilisateur n’est disposé à effectuer certaines actions qu’à certains moments; nous le voyons beaucoup dans le commerce de détail et le commerce: les gens naviguent sur mobile, et terminent sur ordinateur, et la question est alors de savoir si vous répondez davantage à ce modèle multimodal ou si vous créez une expérience cohérente sur tous les appareils. soupçonne que la réponse est «ça dépend», mais de toute façon c’est un problème difficile pour tous, des équipes de produits aux équipes d’ingénierie.

Page Lifecycle API - Philip Walton

Paul Kinlan

Philip Walton a une formidable plongée dans une nouvelle API sur laquelle l’équipe Chrome a travaillé pour vous donner (le développeur) le contrôle de la réponse lorsque le navigateur décharge vos onglets.

Application lifecycle is a key way that modern operating systems manage resources. On Android, iOS, and recent Windows versions, apps can be started and stopped at any time by the OS. This allows these platforms to streamline and reallocate resources where they best benefit the user.

On the web, there has historically been no such lifecycle, and apps can be kept alive indefinitely. With large numbers of web pages running, critical system resources such as memory, CPU, battery, and network can be oversubscribed, leading to a bad end-user experience.

While the web platform has long had events that related to lifecycle states — like load, unload, and visibilitychange — these events only allow developers to respond to user-initiated lifecycle state changes. For the web to work reliably on low-powered devices (and be more resource conscious in general on all platforms) browsers need a way to proactively reclaim and re-allocate system resources.

In fact, browsers today already do take active measures to conserve resources for pages in background tabs, and many browsers (especially Chrome) would like to do a lot more of this — to lessen their overall resource footprint.

The problem is developers currently have no way to prepare for these types of system-initiated interventions or even know that they’re happening. This means browsers need to be conservative or risk breaking web pages.

The Page Lifecycle API attempts to solve this problem by:

  • Introducing and standardizing the concept of lifecycle states on the web.
  • Defining new, system-initiated states that allow browsers to limit the resources that can be consumed by hidden or inactive tabs.
  • Creating new APIs and events that allow web developers to respond to transitions to and from these new system-initiated states.
  • This solution provides the predictability web developers need to build applications resilient to system interventions, and it allows browsers to more aggressively optimize system resources, ultimately benefiting all web users.

The rest of this post will introduce the new Page Lifecycle features shipping in Chrome 68 and explore how they relate to all the existing web platform states and events. It will also give recommendations and best-practices for the types of work developers should (and should not) be doing in each state.

Lire l’article complet.

Mon premier commentaire est que vous devriez lire l’article de Philips. C’est incroyable.

Sur mobile, Google Chrome peut être assez agressif pour la mise en arrière-plan (gel ou suppression) de la page afin d’économiser des ressources lorsque l’utilisateur ne l’utilise pas (par exemple, lorsque vous changez d’onglet ou que vous quittez l’application Chrome sur Android). page En tant que développeur, vous n’avez généralement aucune connaissance de ce qui se passe, de sorte que vous ne pouvez pas facilement conserver l’état ou même fermer des ressources ouvertes. Lorsque les développeurs ont le contrôle, ils peuvent faire des choix plus éclairés, ce qui signifie également que le navigateur peut être plus agressif en ce qui concerne la conservation des ressources à l’avenir sans avoir d’impact majeur sur l’expérience des utilisateurs ou des développeurs.

Enfin, le diagramme ci-dessous explique tout cela très bien.

API de cycle de vie de page

Add to homescreen changes in Chrome 68 - Pete LePage

Paul Kinlan

Pete LePage écrit à propos des changements importants à ajouter à l’écran d’accueil dans Chrome

Add to Home Screen changes

If your site meets the add to home screen criteria, Chrome will no longer show the add to home screen banner. Instead, you’re in control over when and how to prompt the user.

To prompt the user, listen for the beforeinstallprompt event, then, save the event and add a button or other UI element to your app to indicate it can be installed.

Lire l’article complet.

J’avais des sentiments mitigés à ce sujet à l’origine parce que beaucoup de gens ne gèrent pas l’événement beforeinstallprompt, cela signifie que soudainement, le nombre d’installations d’APK Web diminuerait considérablement, mais je pense que c’est la bonne chose à faire.

L’objectif est de réduire le nombre d’invites gênantes sur le Web, et la dernière chose dont nous avons besoin dans l’industrie, c’est qu’une invite relativement importante apparaisse lorsque nous pensons que l’utilisateur peut vouloir installer une PWA. pensez à où et quand ** vous voulez demander une installation et que vous devez le faire en réponse à un geste de l’utilisateur.

La chose intéressante est que nous (Chrome) introduisons davantage de moyens ambiants de faire savoir à l’utilisateur qu’une expérience peut être installée, en ce moment, c’est la petite barre inférieure qui apparaît sur le premier chargement, et nous espérons pouvoir explorer à l’avenir des moyens plus subtils de faire savoir à l’utilisateur qu’il peut agir.