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

私は数週間前にGoogle Developer Dayで中国にいましたが、皆さんに私のQRCode scannerを公開していました。オフラインになるまではうまくいっていました。ユーザーがオフライン(または部分的に接続されている)の場合、カメラは起動せず、QRコードをスナップできませんでした。私は何が起こっているのか分かりませんでした。私は誤って onloadイベントでカメラを起動していました.Googleアナリティクスのリクエストはハングアップし、適時に解決されませんでした。それはそれを修正したこのコミットでした。

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.

全文を読む

私はあなたに大きな洞察力がたくさんあるので、投稿を読むことをお勧めします。

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

Paul Kinlan

週末にはBoomerangエフェクトビデオエンコーダを使って遊んでいましたが、ほぼリアルタイムで動作させることができます(後で説明します)。私はそれをデスクトップ上のChromeで動作させましたが、AndroidのChromeでは正常に動作しません。 コードはここにあるを参照してください。

captureStream()を ` (私の場合は1280x720)、MediaRecorder APIはビデオをエンコードすることができず、エラーもなく、事前にビデオをエンコードできないことを検出できません。

(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.

全文を読む

あなたが両方の作品で動作するデモで遊びたいのであればここをクリック

Why Microsoft and Google love progressive web apps | Computerworld

Paul Kinlan

マイク・エルガンのPWAに関する素晴らしい記事。マイクロソフトの目標はPWAではわかりませんが、私たちは非常に単純だと考えています。ユーザーがコンテンツや機能に即座にアクセスできるように、デバイス上で対話できるようにしたいと考えています。ウェブは、接続されたすべてのデバイスのすべての人に届くはずです。ユーザーは、自分の好みのモダリティにアクセスできる必要があります(モバイル、多分)、またはアシスタントなどでの音声

私たちはまだヘッドレスウェブから遠く離れている(0)が、記事では本当に私を驚かせた:

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

全文を読む

ウェブ上のサイトとアプリは分離されていないと思われますが、ウェブはリンク可能、インデックス可能、一時的です(0)。私たちは、プラットフォームがユーザーに簡単にサイト内外の*データを取得することを許可していないため、意図しないサイロを作成しています(1)。私はRDFやそのようなことについては言及していません。コピー&ペースト、ドラッグ&ドロップ、サイトへの共有、サイトからの共有などの基本的な操作は今日のWeb上で壊れています。と窓。

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

Paul Kinlan

あなたは、ブラウザでウェブだけを使ってビデオを作成し編集することができます。 Screenflowに似たユーザーインターフェイスを提供することで、複数のビデオ、画像、およびオーディオを1つのビデオにまとめて、YouTubeなどのサービスにアップロードできる出力ビデオを作成できるようにする必要があります。 私の前の投稿からビデオエディタの要件を簡単に説明した後、この記事ではスクリーンキャストでウェブカメラレコーダーをどのように作成したか、そしてスクリーンキャストを構築する方法レコーダー:) それはすべてき​​ちんとしていて、新しい navigator.getDisplayMedia APIを使用します。これにより、ユーザーは画面コンテンツへのアクセスを許可することができます。以下のコードは、私がこのビデオを作成するために使用したすべてのものです。 ビデオは非常に非常に生であり、現時点で私はビデオを編集することができないので、多くの間違いがあります:)私の目標は、このプロジェクトの終わりに、私は良いビデオをエンドツーエンドで作ることができるということです。 このビデオのコードデモ window.onload = () => { if('getDisplayMedia' in navigator) warning.style.display = 'none'; let blobs; let blob; let rec; let stream; let voiceStream; let desktopStream; captureBtn.onclick = async () => { download.style.display = 'none'; desktopStream = await navigator.getDisplayMedia({video:true}); voiceStream = await navigator.mediaDevices.getUserMedia({video: false, audio: true}); let tracks = [...desktopStream.getTracks(), ...voiceStream.getAudioTracks()] console.log('Tracks to add to stream', tracks); stream = new MediaStream(tracks); videoElement.srcObject = stream; blobs = []; rec = new MediaRecorder(stream, {mimeType: 'video/webm; codecs=vp9,opus'}); rec.

Read More

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

Paul Kinlan

最初の問題は、ウェブ上でビデオエディタを作成するです。

私は複数のビデオストリーム(デスクトップとウェブカム)を持っています。私はワンビデオ要素のビデオストリームを切り替えることができるようにしたいので、Webカメラとデスクトップを素早く切り替えることができ、 MediaRecorderを破ることはできません。

あなたが videoTracksオブジェクトのselectedプロパティを <video>要素が含まれていますが、トラックの配列に含まれる要素は1つだけです(MediaStreamの最初のビデオトラック)。

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.

全文を読む

Repro case。

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

あなたは、ブラウザでウェブだけを使ってビデオを作成し編集することができます。 Screenflowに似たユーザーインターフェイスを提供することで、複数のビデオ、画像、およびオーディオを1つのビデオにまとめて、YouTubeなどのサービスにアップロードできる出力ビデオを作成できるようにする必要があります。 この投稿は本当に単なる声明です。私はプラットフォーム上で利用できるものと利用できないものを整理し、今日までにどのくらい得ることができるかを見るための長いプロセスを開始するつもりです。 このプロジェクトのいくつかの考えの中で、私はカール・セイガンの瞬間を持っていました。つまり、リンゴ・パイを作るために宇宙を発明する代わりに、少なくともビデオ・エディタを構築するのに必要なすべてのツールを作成する必要があります。それを行うプロセス。この記事が存在するという事実は、私がいくつかの作品を用意して準備ができていることを知っているからです。 私は、他の誰かのためのビジネスでもある大規模なモノリシックな「ビデオエディタ」を作り出すつもりはないと思っていますが、私はそれを簡単にするために必要なすべての部分を工夫するつもりですウェブ上で素晴らしい動画を作成し、多くの人にウェブ上で可能なことを見せてもらいましょう。 以下は私の大まかな1ページプロジェクト計画です: 私が持っている使用例: *私は通常、Google I / OとChrome DevSummitのすべてのデバイスデモを記録し、オーバーレイなどを追加する必要があります。チームの全員がこれを行うことができます。 *チームはしばしばスクリーンキャストを記録し、シンプルなウェブサイトからすぐにそれを行い、最終的な出力をクリーンアップできるようにしたいと考えています。 *私は鋭く保つためにいくつかの製品を作る必要があります。 ;) 入力: [p0]マイクから音声を録音する [p0]ウェブカメラからビデオを録画する[完了 - 下記参照] [p0]ウェブ上にホストされている外部動画を埋め込む [p0]デスクトップを記録する [p1]リモートストリームを記録する [p1]&lt; canvas&gt;を記録します。素子 [p0]ローカルデバイスからファイルをロードする [p1]ローカルデバイスからファイルを共有する(android share intent) 操作: [p1]ウォーターマークを追加する [p1]フィルター効果を画像に追加する [p0]カスタム画像をレイヤーとして追加する [p0]ビデオとオーバーレイをキューに入れる [p0]オーディオとビデオの別々のトラックをオーバーレイする [p1]特定の時間にテキストを重ねる [p0]ビデオをサイズに切り抜く [p0]ビデオの位置決めとサイズ変更を有効にする [p0]ビデオ/オーディオのトリム [p0]スプライスビデオ/オーディオ 出力: [p0] webm形式のビデオファイル [p1] MTB情報 [p1] xyz形式のビデオファイル このビデオのコードデモ const init = () => { let blobs; let rec; let stream; captureBtn.onclick = async () => { stream = await navigator.

Read More

Barcode detection in a Web Worker using Comlink

Paul Kinlan

私はQRコードの大ファンです。実世界とデジタル世界の間でデータを交換するための非常にシンプルできれいな方法です。数年前から、私はQRSnapperと呼ばれる小さなプロジェクトを持っていました。まあそれはいくつかの名前を持っていますが、これは私が解決したものです&mdash;これは getUserMedia APIを使用してユーザのカメラからライブデータを取得し、ほぼリアルタイムでQRコードをスキャンすることができます。

このアプリの目標は、UIで60fpsを維持し、QRコードをすぐに検出できるようにすることでした。これは、検出コードをWebワーカー(かなり標準的なもの)に入れなければならないことを意味しました。この記事では、comlinkを使ってワーカーのロジックを大幅に単純化する方法を簡単に共有したいと思っていました。

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(ウェブワーカー)

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);

私は本当にComlinkが大好きです。特に、スレッド間で動作する慣用JavaScriptを作成する場合、ライブラリのゲームチェンジャーだと思います。最後にここでうまくいくのは、ネイティブのバーコード検出APIをワーカー内で実行できるため、すべてのロジックがUIからカプセル化されているからです。

全文を読む

Running FFMPEG with WASM in a Web Worker

Paul Kinlan

私はFFMPEG.jsが大好きです。これは、asm.jsでコンパイルされた素敵なツールです。そして、私はビデオをすばやく編集できるJS Webアプリケーションを作成しましょう。 FFMPEG.jsもWebワーカーと連携して、メインスレッドをブロックせずにビデオをエンコードすることができます。

私はComlinkも大好きです。 Comlinkでは、複雑な postMessageステートマシンを扱わなくても、関数やクラスを公開することで、Webワーカーと簡単にやりとりすることができます。

私は最近、この2つを組み合わせる必要があります。私はFFMPEGをWebアセンブリにエクスポートして実験しました(これはうまくいきます)、現在のFFMPEG.jsプロジェクトでpostMessageの作業をすべてクリーンアップしたかったのです。以下は、コードが今のように見えるものです - 私はそれがかなりきちんとしていると思います。私たちにはffmpeg.jsとcomlinkをインポートするワーカーがいて、単にffmpegインターフェイスを公開するだけです。次に、workerを読み込んだ後、comlinkを使ってffmpeg APIへのプロキシを作成するWebページがあります。

きちんとした

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);
   }),
});

私はComlink、Workers、WASMのコンパイルされたモジュールが一緒に演奏できる方法が本当に好きです。私はWASMモジュールと直接対話する慣用的なJavaScriptを取得し、それはメインスレッドから実行されます。

全文を読む

Translating a blog using Google Cloud Translate and Hugo

Paul Kinlan

私は最近、Google4Indiaイベント(近いうちに報告)に出席し、多くの企業や開発者と出会うためにインドへの旅行から帰ってきました。議論された最も興味深い変更の1つは、国のユーザーの言語でより多くのコンテンツを求めていたことでした。特に、ユーザーの言語で検索しやすくすること、コンテンツを見つけること、テキストまたは音声形式でユーザにそれを読み戻すことができます。

旅行全体が私に考えさせてくれました。私のブログはHugoで構築されています。 Hugoは現在、複数の言語で書かれたコンテンツをサポートしています。 Hugoは完全に静的なので、新しいコンテンツを作成することは、新しいファイルを作成してビルドシステムに魔法をかけることの問題です。翻訳ツールを使用して静的コンテンツを実行することで、より多くの人がコンテンツを利用できるようにすることができます。なぜなら、コンテンツの翻訳者は非常に高額なためです。

私の飛行前にイギリスに帰国する数時間前に、自分のマークダウンファイルを取得し、Google Cloud Translateで実行してクイック検索を作成するスクリプトを作成しました私はすぐにホストすることができますページの翻訳。ソリューション全体を以下に示します。これは比較的基本的なプロセッサーで、「コード」を無視したHugoプリアンブルを無視し、プル・クォートを無視しています。これらは常に書かれたままにしておくことを前提としていました。

注:翻訳用のラーニングソフトウェアのように見えるので、学習ツールでGoogle Translatedコンテンツをアルゴリズムの入力として使用しないようにページをマークアップすることが重要です(https://cloud.google.com/translate/マークアップ)。

// 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);

全体として、私はそのプロセスに非常に満足しています。機械翻訳は完璧ではないと私は考えていますが、英語ではなく自分の言語で検索している可能性のあるユーザーにコンテンツのリーチを広げることができると私は思っています。人。

これが実際に人々に役立つかどうかを確認するにはしばらく時間がかかりますので、データが増えたときに報告します。

Apple - Web apps - All Categories

Paul Kinlan

Web AppsがiPhoneでアプリを使用するために推奨される方法を覚えていますか?

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

全文を読む

2013年頃、Appleは/ webapps /トップレベルのディレクトリを/ iphone /

ことは、ディレクトリは実際にはかなり良かった、そこのアプリの多くは今日も動作しています。しかし、AppStoreを見ると、開発者が持っていたより多くの問題が解決されました。 AppStoreはまた、支払いに関してユーザーや開発者から取り除かれた摩擦を具体的に紹介し始めました。

Gears API

Paul Kinlan

私は初期のモバイルWeb APIに関するブログ記事を書いているし、Alex Russellは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

全文を読む

AppCacheとWebSQL、GeolocationとWebWorkersはGoogle Gearsのアイデアから出てきて、実際に生き残ったのは後者の2つだけです。 WebSQLは決して広くサポートされておらず、IndexedDBに置き換えられました。 ServiceWorkerに置き換えられたAppCache

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

Paul Kinlan

私たちはGoogleチャットを内部的に使用してチーム全体でコミュニケーションを取っています。また、RSSフィードを介してアクセスできる多くのコンテンツを作成し、すべて見ることができるチームフィードを持っています。最近まで、WebHooks(https://developers.google.com/hangouts/chat/how-tos/webhooks)経由で単純なポストオンリーボットを作成することはかなり簡単であることがわかりました。私にはアイデアが与えられました。私はRSSフィードをポーリングして、私たちのチームチャットに直接投稿できるWebhookに送信する簡単なサービスを作成できます。

最後はかなりシンプルで、以下のコードをすべて含めました。私はFirebaseの機能を使用しました - これは他のサービス機能サイトやSuperfeedrと同じように簡単だと思われます。 SuperfeedrはPubsubhubbub ping(現在WebSub)を聞くことができるサービスで、Pubsubが設定されていないRSSフィードもポーリングします。フィードが見つかると、新しく見つかったフィードデータをXMLまたはJSON形式で構成されたURL(私の場合、FirebaseのCloud機能)にpingを実行します。データを解析して何かをするだけです。

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);

完全な記事を読む

私は驚いて、セットアップがいかに簡単かについて喜んでいました。

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がChrome OSに移行しました(一時的に):

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

全文を読む

彼女の主なマシンが壊れたので、ルースはChrome OSに移行するという大きな記事を書いています。

私は4ヶ月前(Google I / Oの前)にChrome OSにフルタイムで移行し、PixelBookを壊したためにMacに移行しました(現在は修正済み)。

私のために、それは今日そこにある最高のウェブ開発機の一つです。それは私が ‘真のモバイル’をテストできる唯一のデバイスです - あなたはそれにARCプラットフォームを介して、モバイル、サムスンのブラウザ、ブレイブなど、モバイル上のモバイルをインストールすることができます。 CrostiniはChrome OSのゲームチェンジャーでもあります.Chrome OSにLinux Appエコシステムの多くをもたらし、Chrome OS上で私にとって巨大なアプリケーションギャップを埋めるようになります。私はFirefox、vim、git、VSコード、ノード、npm、すべてのビルドツール、GIMP、Inkscapeを持っています…それは完璧だとは言えませんが、Crostiniはもっと速くて、GPUはまだ加速していません。 Filemanagerなどとの統合がさらに進んでいき、最終的にPixelBookには物理的なポートがさらに必要になります.2つの4kスクリーンを接続することはできますが、同時に充電することはできません。

私はルースのまとめも非常に正確だと思うが、PixelBookは高価なマシンだが、これはますます多くのデバイス(特に低価格帯のデバイス)になることを非常に喜んでいる。

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.

うん。

PWA: Progressive Web All-the-things

Paul Kinlan

PWA。プログレッシブウェブアプリ。 Frances BerrimanとAlex Russellは、2015年に「プログレッシブウェブアプリ:私たちの魂を失うことなくタブを逃れる」(0)という、「プログレッシブウェブアプリ」という言葉を主張しています。 3年後、我々は長い道のりを歩んだ。当初は1つのブラウザエンジンでしか実装されていなかったサービスワーカー、マニフェスト、ホーム画面に追加、Web Pushというゆるやかな技術の集まりから、企業や開発者と業界全体に密着し始めたブランド、ブラウザベンダーは大多数の ‘PWA’スタックを実装しています。 野生のPWAの数を大まかに把握するのに役立つappディレクトリ、toolsがあります。 PWA](3)。しかし、PWAは何を定義していますか?フランシスとアレックスはこの特徴のリストを思いついた: Responsive: to fit any form factor Connectivity independent: Progressively-enhanced with Service Workers to let them work offline App-like-interactions: Adopt a Shell + Content application model to create appy navigations & interactions Fresh: Transparently always up-to-date thanks to the Service Worker update process Safe: Served via TLS (a Service Worker requirement) to prevent snooping Discoverable: Are identifiable as “applications” thanks to W3C Manifests and Service Worker registration scope allowing search engines to find them

Read More

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

Paul Kinlan

ムスタファは次のように書いている。

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.

全文を読む

私はこれを非常に興味深い投稿と見なしました。これは、ウェブ開発者の課題について書いた記事の補足でもあります。ブラウザの互換性が問題であることは驚くべきことではありませんが、まだ懸念されるのは、IE11を構築することはまだ業界を後押ししていることです。同様に、Mustafa氏は、レスポンシブデザインのツールにはまだ問題が残っていると指摘しています。また、単一のレスポンシブルなソリューションに重点を置くと、常にムスタファのポストにあります。

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

これは私たちがまだ苦労していると思う問題です。一方では、誰もがすべてのデバイスのフォームファクターで誰にでも役立つことができる応答性の高いソリューションを構築したいと考えています。一方、ユーザーコンテキストは重要であり、しばしば特定の時間に特定のアクションを実行するだけです。小売業や商工業では多くの人々が見ています。人々はモバイルでブラウジングしてデスクトップで完成し、このマルチモーダルモデルをより多くの人に提供したり、すべてのデバイスで一貫した体験を構築したりできます。その答えは「それは依存している」と疑われますが、製品チームからエンジニアリングチームまで、誰にとっても難しい問題のいずれかです。

Page Lifecycle API - Philip Walton

Paul Kinlan

Philip Walton氏は、ブラウザがタブをアンロードしたときの対応方法をChrome開発者がコントロールするために、Chromeチームが取り組んでいる新しいAPIについて深く掘り下げています。

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.

完全な記事を読む

私の最初のコメントは、あなたがフィリップスの記事を読むべきだということです。それは信じられないです。

モバイルでは、ユーザーがブラウザを使用していないときにリソースを節約するために、ページをバックグラウンド(フリーズまたは破棄)するときにかなり攻撃的になる可能性があります(タブを入れ替えたり、AndroidのChromeアプリから移動するなど)あなたは伝統的にこれがいつ起こるのかを知らない開発者としてページを開いて、簡単に状態を保持したり、開いているリソースを閉じたりすることができず、アプリケーションが重要なときに状態をきれいに再水和します。開発者がコントロールできるようになると、情報に基づいた選択を行うことができ、ユーザーや開発者のエクスペリエンスに深刻な影響を与えることなく、ブラウザをより積極的に使用してリソースを節約できます。

最後に、下の図はそれをすべてうまく説明しています。

ページライフサイクルAPI

Add to homescreen changes in Chrome 68 - Pete LePage

Paul Kinlan

Pete LePageは、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.

全文を読む

多くの人が beforeinstallpromptイベントを処理していないので、Web APKのインストール数が急激に減少することを意味していたため、これは元々気になりましたが、実際には正しいことだと思います。

目標はWeb上で起こっている迷惑なプロンプトの数を減らすことです。業界で最後に必要となるのは、ユーザーがPWAをインストールしたいと思ったときに表示される比較的大きなプロンプトです。あなたがいつどこで**あなたがインストールを促すかを考えて、あなたはユーザージェスチャーに応じてそれをしなければなりません。

きちんとしたことは、私たち(Chrome)が、体験をインストールできることをユーザーに知らせるためのより多くの周囲の方法を導入していることです。最初の負荷に現れる小さなボトムバーです。ユーザーに行動を起こせることを知らせるより微妙な方法。