Web 与 Chrome 最新进展 @Google I/O 2019

Google I/O 2019 extend 成都站


DOM 与 BOM


延迟加载

<img src="path/to/image" loading="lazy" />

<iframe src="path/to/page" loading="lazy"></iframe>

loading 属性值

  • lazy 延迟加载
  • eager 立即加载
  • auto 浏览器自主判断加载策略(默认值)

  • loading 属性是早期提案 lazyload 属性的代替
  • 将在 Chrome 76 发布

门户框架

主页面

<portal src="path/to/page"></portal>
const portal = document.querySelector('portal');

portal
  .activate({ data: { key: 'value' } })
  .then(() => portal.postMessage({ hello: 'portal' }));

子页面

window.addEventListener('portalactivate', event => {
  console.log(event.data); // {key: 'value'}

  const portal = event.adoptPredecessor(); // 主页面

  document.body.append(portal);
});

window.addEventListener('message', event =>
  console.log(
    event.data, // {hello: 'portal'}
    window.portalHost // 主页面 window 对象
  )
);

Portal demo


分享网页

document.querySelector('button.share').addEventListener('click', async () => {
  const data = { title: 'Hello', text: 'World', url: 'https://web.dev/' };

  if (!navigator.canShare(data)) return;

  await navigator.share(data);

  console.log('Done!');
});
  • 网页由 HTTPS 打开
  • Android Chrome 61+
  • 分享调用在用户操作回调栈中发起
  • polyfill

在 PWA 的 manifest.json 中多加一段

即可成为分享目标(Chrome 71+)

{
  "share_target": {
    "action": "/path/to/share-target/",
    "method": "GET",
    "enctype": "application/x-www-form-urlencoded",
    "params": {
      "title": "your_title_key",
      "text": "your_text_key",
      "url": "you_url_key"
    }
  }
}

Share to PWA


形状检测

文字

const textDetector = new TextDetector();

const texts = await textDetector.detect(image);

texts.forEach(text => console.log(text));

条码

const barcodeDetector = new BarcodeDetector({
  formats: [
    'aztec',
    'code_128',
    'code_39',
    'code_93',
    'codabar',
    'data_matrix',
    'ean_13',
    'ean_8',
    'itf',
    'pdf417',
    'qr_code',
    'upc_a',
    'upc_e'
  ]
});

const barcodes = await barcodeDetector.detect(image);

barcodes.forEach(barcode => console.log(barcode));

人脸

const faceDetector = new FaceDetector({
  maxDetectedFaces: 5,
  fastMode: false
});

const faces = await faceDetector.detect(image);

faces.forEach(face => console.log(face));


更多草案 API


HTTP


# 站内跳转带 cookie
Set-Cookie: a=1; SameSite=Strict

# 跳转到本站带 cookie
Set-Cookie: b=2; SameSite=Lax

# 不限制 cookie
Set-Cookie: c=3; SameSite=None

RFC 6265 bis



Web 包协议



JavaScript


V8 提速、降费




原生类型增强

const integer = 14_0000_0000; // 1400000000

const bigInt = BigInt(Number.MAX_SAFE_INTEGER) + 1n; // 9007199254740992n

[
  [1, 2],
  [3, 4]
].flat(); // [1, 2, 3, 4]

Object.fromEntries([
  ['a', 1],
  ['b', 2]
]); // {a: 1, b: 2}

console.log(...'FCC成都社区,FCC中文社区'.matchAll(/\w+([^,]+)/g));
//  ['FCC成都社区', '成都社区']  ['FCC中文社区', '中文社区']

统一全局对象

const globalThis = (() => {
  // 浏览器主线程
  if (typeof window !== 'undefined') return window;
  // Web worker 线程
  if (typeof self !== 'undefined') return self;
  // Node.JS
  if (typeof global !== 'undefined') return global;
  // 其它运行时的非严格模式
  if (typeof this !== 'undefined') return this;
})();
  • Stage-3
  • Chrome 71、Firefox 65、Safari 12.1

国际化 API

相对时间

const formatter = new Intl.RelativeTimeFormat('zh-CN');

console.log(formatter.format(-1, 'day')); // 1天前

console.log(formatter.formatToParts(-1, 'day'));
/*
[
    {
        "type": "integer",
        "value": "1",
        "unit": "day"
    },
    {
        "type": "literal",
        "value": "天前"
    }
]
*/
  • Stage-3
  • Chrome 71、Firefox 65

短语列表

const and = new Intl.ListFormat('zh-CN', { type: 'conjunction' }),
  or = new Intl.ListFormat('zh-CN', { type: 'disjunction' });

const list = ['GDG', 'FCC', 'ThoughtWorks'];

console.log(
  and.format(list), // 'GDG、FCC和ThoughtWorks'
  or.format(list) // 'GDG、FCC或ThoughtWorks'
);
  • Stage-3
  • Chrome 72、Opera 60

Promise

.allSettled()

await Promise.allSettled([
  fetch('https://fcc-cd.dev/'),
  fetch('https://google.com/') // 没有科学上网
]);

console.log('所有请求已响应,部分可能失败');

.any()

const fastest = await Promise.any([
  fetch('https://cdn.jsdelivr.net/npm/web-cell/dist/web-cell.min.js'),
  fetch('https://unpkg.com/web-cell/dist/web-cell.min.js')
]);

console.log(fastest.url);

类实例成员

class Example {
  publicField = 1;
  #privateField = 2;

  publicMethod = () =>
    console.log(
      this.publicField, // 1
      this.#privateField // 2
    );
}
  • Stage-3
  • Babel 7
  • Node 12
  • Chrome 72 / V8 7.2(公开成员)
  • Chrome 74 / V8 7.4(私有成员)

垃圾回收 API

提案来源


WeakRef

const URI = 'path/to/file';

const file = await (await fetch(URI)).blob();

const ref = new WeakRef(file),
  cache = {};

cache[URI] = ref;

console.log(ref.deref()); // Blob {}

FinalizationGroup

const cleaner = new FinalizationGroup(iterator => {
  for (const URI of iterator) delete cache[URI];
});

cleaner.register(image, URI);

Google


Search How to


{
  "@context": "http://schema.org",
  "@type": "HowTo",
  "image": {
    "@type": "ImageObject",
    "url": "https://example.com/1x1/photo.jpg"
  },
  "name": "How to tie a tie",
  "description": "...",
  "totalTime": "PT2M",
  "video": {
    "@type": "VideoObject",
    "name": "Tie a Tie",
    "description": "...",
    "thumbnailUrl": "https://example.com/photos/photo.jpg",
    "contentUrl": "http://www.example.com/videos/123_600x400.mp4",
    "embedUrl": "http://www.example.com/videoplayer?id=123",
    "uploadDate": "2019-01-05T08:00:00+08:00",
    "duration": "P1MT10S"
  },
  "supply": [
    {
      "@type": "HowToSupply",
      "name": "A tie"
    },
    {
      "@type": "HowToSupply",
      "name": "A collared shirt"
    }
  ],
  "tool": [
    {
      "@type": "HowToTool",
      "name": "A mirror"
    }
  ],
  "step": [
    {
      "@type": "HowToStep",
      "name": "Preparations",
      "text": "...",
      "image": "https://example.com/1x1/step1.jpg",
      "url": "https://example.com/tie#step1"
    },
    {
      "@type": "HowToStep",
      "name": "Crossing once",
      "text": "...",
      "image": "https://example.com/1x1/step2.jpg",
      "url": "https://example.com/tie#step2"
    },
    {
      "@type": "HowToStep",
      "name": "Second crossing",
      "text": "...",
      "image": "https://example.com/1x1/step3.jpg",
      "url": "https://example.com/tie#step3"
    },
    {
      "@type": "HowToStep",
      "name": "Loop in",
      "text": "...",
      "image": "https://example.com/1x1/step4.jpg",
      "url": "https://example.com/tie#step4"
    },
    {
      "@type": "HowToStep",
      "name": "Pull and tighten",
      "text": "...",
      "image": "https://example.com/1x1/step5.jpg",
      "url": "https://example.com/tie#step5"
    }
  ]
}

结构化元数据


Material Design 夜间模式


性感谷歌,在线教学

https://web.dev/

https://developers.google.cn/web/

https://events.google.com/io/codelabs/

https://codelabs.developers.google.com/?cat=Web


关注 freeCodeCamp 成都社区

https://fcc-cd.dev/


上一篇
敏捷开发之我见 敏捷开发之我见
入职 ThoughtWorks 后,公司邮箱曾收到一篇内部博客大赛的文章《真正的敏捷工作流 —— GitHub flow》,我心想“我一个 GitHub 公民应该会很适应 TW 吧”? 果然…… 不要立 flag…… 敏捷不是什么大多数人对
2019-07-31
下一篇
FCC DevTalk - 水歌 FCC DevTalk - 水歌
freeCodeCamp 中文社区创始人 Miya 对我的采访 1. 简要介绍一下自己吧。艺名水歌、网名 TechQuery,Web/JavaScript 全栈开发者,是多个国内外开源软件项目的作者、贡献者。现为 freeCodeC
2019-04-23
目录