Upgrade to Pro — share decks privately, control downloads, hide ads and more …

こえのブログでのPWA ~ 開発現場編 ~ / Koe-No-Blog PWA

こえのブログでのPWA ~ 開発現場編 ~ / Koe-No-Blog PWA

Frontrend × Bonfire Frontend (https://frontrend.connpass.com/event/124995/) での発表資料です。

「こえのブログ」はアメブロに追加された音声配信機能です。新機能開発における技術選定、開発フローやドキュメント作成など「開発現場」に焦点を当ててお話します。

関連ブログ: https://developers.cyberagent.co.jp/blog/archives/20506/

Kazunari Hara

April 16, 2019
Tweet

More Decks by Kazunari Hara

Other Decks in Technology

Transcript

  1. 2010 JavaScript 2011 Node.js 2016 React, Redux, DevOps 2018 CDN

    HTML5 Web Applicationの つくりかた https://ameblo.jp/ca-1pixel/entry-1100959 8050.html アメブロ2016 ~ React/Reduxでつ くるIsomorphic web app ~ https://developers.cyberagent.co.jp/blog/archives/ 636/ Optimized Server-Side Web Application In 2018 https://developers.cyberagent.co.jp/blog/archi ves/16818/ Amebaプラットフォームの 作りかた https://www.slideshare.net/herablog/ameba-2 2035207
  2. index.html voice-app.js voice-editor.js voice-home.js lazy-resources.js shared dependencies Entrypoint App Shell

    Lazy Load Fragment PRPL Pattern <script type=”module”> await import(); await import(); await import();
  3. コンポーネント指向での開発 <voice-app> <voice-header> <button type=”button”> メニューを開く</button> </voice-header> <voice-mic recording> </voice-mic>

    </voice-app> class VoiceMic extends LitElement { render() { const label = this.recording ? ‘停止する’ : ‘開始する’; } } class VoiceHeader extends LitElement { render() { return html` <slot></slot> `; } }
  4. :host { --mic-size: var(--voice-mic-size, 72px); } .mic { height: var(--mic-size);

    } .icon { … } font-family: sans-serif; <voice-mic> <voice-editor> voice-mic { --voice-mic-size: 100px; } Custom Property Cascading Scoped
  5. ブラウザの マイクを利用 navigator.mediaDevices .getUserMedia({ audio: { autoGainControl: false, channelCount: 1,

    echoCancellation: true, noiseSuppression: true, }, }) .then((stream) => { // use the stream }) .catch((err) => { // NotAllowedError or // NotFoundError });
  6. マイクパー ミッション を取得 const installMicPermissionWatcher = async callback => {

    const permissionStatus = await navigator.permissions .query({ name: 'microphone' }); // granted or prompt or denied callback(permissionStatus.state); permissionStatus .addEventListener('change', () => callback(permissionStatus.state) ); };
  7. FCP: 1.8s -> 1.5s (Updated) TTI: 4s -> 3s (Updated)

    App shell JS size: 120KB Chunk JS size: 20KB