Try   HackMD

「再入門!フロントエンドエンジニアが押さえておくべき技術」

①JavaScript

基本構文

  • 割愛

DOM操作の仕方

  • DOM(DocumentObjectModel)とは
    • ブラウザが表示しているHTMLの要素をJavaScriptで操作しやすいようにしたデータ構造
    • 「操作しやすい」といっても、最近では直接DOMを扱うこと自体を避けるようにもなってきている
  • DOM操作の例
    ​​​​<!DOCTYPE html>
    ​​​​<html>
    ​​​​  <head>
    ​​​​    <meta charset="utf-8">
    ​​​​    <title>タイトル</title>
    ​​​​  </head>
    ​​​​  <body>
    ​​​​      <section>
    ​​​​        <img src="example.png">
    ​​​​        <p>リンクは<a href="https://foo.example.com/">こちら</a></p>
    ​​​​      </section>
    ​​​​  </body>
    ​​​​</html>
    
    • リンクの要素を取得する
      • const link = document.querySelector('a');
    • リンクの文字列を変更する
      • link.textContent = 'あちら';
    • リンクのURLを変更する
      • link.href = 'https://bar.example.com';
  • 「DOMを更新する」ことでユーザーの操作に対して結果を伝える(メッセージを表示する、ダイアログを表示する、色が変わる…)
  • JavaScriptフレームワークが代わりにやってくれたり、簡便に記述できたりするが、最終的にやっていることはコレなので重要な要素。

ES6(ES2015)以降の記法

  • ES(ECMAScript)とは
    • JavaScriptの標準規格を定めたもの
  • JavaScriptとECMAScriptの関係
    • JavaScriptはあくまでブラウザ上で動作するスクリプト言語で、厳密にはブラウザによって仕様が異なる
    • ECMAScriptはJavaScriptの標準規格で、各ブラウザはECMAScriptの仕様に沿ってJavaScriptを開発する
    • ひと昔前はよく聞いた「IE動かない問題」は古いIEほど標準規格に則ってなかったりするものの名残
    • 例:Promise.any
  • ES6(ES2015)とは
    • ECMAScriptの2015年に公開された規格。6世代目。ES6と言ったりES2015と言ったり。
    • それ以前のJavaScriptの構文から、モダンな構文に大きく変化があった世代。
    • ES6より前と後で大きく記述方法が異なるため、一つの区切りとされる。
  • Before ES6 / After ES6
    • let/const
      ​​​​​​​​// Before ES6
      ​​​​​​​​var a = 1;
      ​​​​​​​​// After ES6
      ​​​​​​​​let b = 2;
      ​​​​​​​​const c = 3
      
    • Promise
      ​​​​​​​​// Before ES6
      ​​​​​​​​    
      ​​​​​​​​// 1秒ごとにカウントダウンする(わざわざこんな書き方する必要はないのですが)
      ​​​​​​​​function countDown(count, callback) {
      ​​​​​​​​    setTimeout(function() {
      ​​​​​​​​        console.log(count)
      ​​​​​​​​        callback(count - 1);
      ​​​​​​​​    },1000);
      ​​​​​​​​}
      ​​​​​​​​    
      ​​​​​​​​// 非同期で実行する処理がどんどん入れ子になる
      ​​​​​​​​countDown(2, function(count){
      ​​​​​​​​    countDown(count, function(count) {
      ​​​​​​​​        countDown(count, function(count) {
      ​​​​​​​​            console.log("finish!");
      ​​​​​​​​        });
      ​​​​​​​​    });
      ​​​​​​​​});
      ​​​​​​​​    
      ​​​​​​​​// Promise
      ​​​​​​​​function countDown(count) {
      ​​​​​​​​    return new Promise(function(resolve, reject) {
      ​​​​​​​​        setTimeout(function() {
      ​​​​​​​​            console.log(count)
      ​​​​​​​​            resolve(count - 1);
      ​​​​​​​​        },1000);
      ​​​​​​​​    });
      ​​​​​​​​}
      
      ​​​​​​​​// 入れ子にならずに書ける
      ​​​​​​​​countDown(2)
      ​​​​​​​​    .then(countDown)
      ​​​​​​​​    .then(countDown)
      ​​​​​​​​    .then(function (count) {
      ​​​​​​​​        console.log("finish!");
      ​​​​​​​​    });
      
    • async/await
      ​​​​​​​​// 非同期で実行する関数定義は同じ
      ​​​​​​​​function countDown(count) {
      ​​​​​​​​    return new Promise(function(resolve, reject) {
      ​​​​​​​​        setTimeout(function() {
      ​​​​​​​​            console.log(count)
      ​​​​​​​​            resolve(count - 1);
      ​​​​​​​​        },1000);
      ​​​​​​​​    });
      ​​​​​​​​}
      
      ​​​​​​​​// async/await Promiseより直感的に書ける
      ​​​​​​​​async function asyncCall() {
      ​​​​​​​​  let count = await countDown(2);
      ​​​​​​​​  count = await countDown(count);
      ​​​​​​​​  count = await countDown(count);
      ​​​​​​​​  console.log("finish!");
      ​​​​​​​​}
      
      ​​​​​​​​asyncCall();
      

API呼び出し

  • フロントエンド開発ではバックエンドのAPI呼び出しの知識が必須
    • この辺りもJSフレームワーク任せなことが多いが、基礎知識として。
  • XMLHttpRequest(XHR)
    • すごく古い書き方。古いプロダクトで稀に見かける。
    ​​​​// APIを呼び出した結果をconsoleログに出力
    ​​​​const url = 'https://foo.example.com/api'
    ​​​​let request = new XMLHttpRequest();
    
    ​​​​request.onload = function() {
    ​​​​  console.log(request.response);
    ​​​​};
    
    ​​​​request.open('GET', url);
    ​​​​request.responseType = 'text';
    ​​​​request.send();
    
  • jQuery
    • 一昔前の主流。割とまだ見かける。
    ​​​​// APIを呼び出した結果をconsoleログに出力
    ​​​​const url = 'https://foo.example.com/api'
    ​​​​$.ajax({
    ​​​​  type: "GET",
    ​​​​  url: url,
    ​​​​  success: function(text){
    ​​​​    console.log(text)
    ​​​​  }
    ​​​​});
    
  • FetchAPI
    ​​​​// APIを呼び出した結果をconsoleログに出力
    ​​​​const url = 'https://foo.example.com/api'
    ​​​​async function callApi() {
    ​​​​    const res = await fetch(url);
    ​​​​    const text = await res.text();
    ​​​​    console.log(text);
    ​​​​}
    
    ​​​​callApi();
    

②TypeScript

TypeScriptの特徴

  • JavaScriptに変換される

    • TypeScriptで書かれたプログラムを実行したい場合、TypeScriptをそのまま実行するのではなくTypeScriptをJavaScriptに変換させて実行する
    • TypeScript Playground
    ​​​​// typescript ​​​​const foo: string = 'foo';

    ​​​​// javascript ​​​​"use strict"; ​​​​var foo = 'foo';
  • 静的型システム

    • TypeScriptがJavaScriptに変換されるときに型チェックが行われる
    • 文字を入れるところに数値を入れたりしているとエラーを出してくれる
  • JavaScriptのスーパーセット

なんでTypeScriptを使うのか

  • 開発者体験の向上

    • JavaScriptは動的型付け言語、TypeScriptは静的型付け言語
    • エラーに早く気づける
    • たとえば、これは実行時にエラー
    ​​​​// javascript ​​​​console.log(foo) ​​​​ ​​​​// foo is not defined
    • TypeScriptならコンパイル時にエラー
    ​​​​// typescript ​​​​console.log(foo) ​​​​// Cannot find name 'foo'
    • VSCodeのようなTypeScriptに対応したエディタを使ってるならコードを書いた瞬間に画面上で教えてくれる
    • ※ エラーにはなるがコンパイルはできる
    • あとはコードジャンプもエディタによる補完も効く
  • ドキュメントの役割

    • ここで言うドキュメントは変数だったり関数だったりがどういうものかを教えてくれるもの
    • TypeScriptを使うと半自動的に実現できる
    • たとえばこういう関数があったときに数値の足し算なのか、文字列の連結なのかわからない
    ​​​​// javascript ​​​​function add(a, b) { ​​​​ return a + b ​​​​}
    • TypeScriptを使うと足し算する関数なんだなとわかりやすい
    ​​​​function add(a: number, b: number): number { ​​​​ return a + b ​​​​}
    • コメント書けばいいじゃん?
    ​​​​// 数値を2つ引数に受け取りその和を返す ​​​​function add(a, b) { ​​​​ return a + b ​​​​}
    • コメントはあくまでコメントで合ってる保証はないし、将来実装に変更が入ってコメントはそのままということも
    • TypeScriptならちゃんとエラーになる
    ​​​​function add(a: string, b: number): number { ​​​​ return a + b ​​​​} ​​​​// Type 'string' is not assignable to type 'number'.
  • 古いJavaScriptに変換してくれる

    • JavaScript(EcmaScript)にはバージョンがある
    • 最新のJS使えばいいじゃん?
    • ブラウザが追いついていなかったり、ブラウザベンダーが頑張ってアップデートしてもユーザが更新していなかったりする。まだIE使ってるユーザも多い?
    • なのでES5くらいで書かなきゃいけないけど、開発者は最新のバージョンで書きたい
    • TypeScriptはESNextなコードをES5やES3に変換してくれる
    • お仲間にbabelとか

関連技術

③フレームワーク

フロントエンドフレームワークとは?

フロントエンドフレームワークの種類

  • メジャーなものを抜粋
    1. Vue.js
      • 公式ドキュメントの日本語訳が多い
      • SFC(単一ファイルコンポーネント)を採用
        • 部品(コンポーネント)に関するHTMLとCSSとJavaScriptを1つのファイルに記述する
        • 関心ごとを1つのファイルに集約できるかつ従来通りの文法をほぼそのまま使用できる
        • ​​​​​​​​​​​​​​<script> ​​​​​​​​​​​​​​export default { ​​​​​​​​​​​​​​ data() { ​​​​​​​​​​​​​​ return { ​​​​​​​​​​​​​​ greeting: 'Hello World!' ​​​​​​​​​​​​​​ } ​​​​​​​​​​​​​​ } ​​​​​​​​​​​​​​} ​​​​​​​​​​​​​​</script> ​​​​​​​​​​​​​​<template> ​​​​​​​​​​​​​​ <p class="greeting">{{ greeting }}</p> ​​​​​​​​​​​​​​</template> ​​​​​​​​​​​​​​<style> ​​​​​​​​​​​​​​.greeting { ​​​​​​​​​​​​​​ color: red; ​​​​​​​​​​​​​​ font-weight: bold; ​​​​​​​​​​​​​​} ​​​​​​​​​​​​​​</style>
    2. React
      • 公式でUIライブラリと言っているがVue.jsとよく比較されるので記載
      • コンポーネント指向であることはVue.jsと変わらないが、JSXと呼ばれる記法でJavaScriptの一部として画面構成を記述する
        • ​​​​​​​​​​​​​​import style from './style.css' ​​​​​​​​​​​​​​const HelloWorld () => { ​​​​​​​​​​​​​​ const greeting = 'Hello World!!' ​​​​​​​​​​​​​​ return ( ​​​​​​​​​​​​​​ <div className="style.greeting"> ​​​​​​​​​​​​​​ {greeting} ​​​​​​​​​​​​​​ </div> ​​​​​​​​​​​​​​ ) ​​​​​​​​​​​​​​}
          ​​​​​​​​​​​​​​.greeting { ​​​​​​​​​​​​​​ color: red; ​​​​​​​​​​​​​​ font-weight: bold; ​​​​​​​​​​​​​​}
      • 周辺ライブラリの選択肢が多い(=Vue.jsに比べ自由度が高い反面どれを選択するかの知識が必要)
    3. Angular
      • TypeScript標準採用(=開発に必須)
      • フルスタックフレームワークを自称しており、Viewの構成だけでなく一通りの機能が入っている
        • Vue.jsやReactだと周辺ライブラリ(公式のものを含む)を別途導入しなければならないものが多い

シェア

コンポーネント指向

仮想DOM

④SPA(Single Page Application)

SPAとは

  • (極めてざっくり言うと)ユーザーがアクセスするWebページは空の最初の1ページのみで、バックエンドのAPIを呼び出し動的に画面の要素の構築、画面遷移を行うタイプのアプリケーション
  • 従来のような画面全体を切り替えて画面遷移を行うタイプのアプリケーションを対比でMPA(Multi Page Application)と呼んだり

なぜSPAが重要なのか

  • 近年では、Webアプリケーションでも、スマートフォンのアプリのような柔軟で表現に富んだ操作性や体験が求められることが多くなった
  • メリット/デメリット ※余談ですがメリデメって死語だったりするんですかね。pros/cons?
    • メリ
      • 前述の通り
      • イケてる感
    • デメ
      • 初回のJavaScript読み込みがMPAで作った時より相対的に増えるので、読み込みが遅くなりがち
      • Googleなどの検索エンジンにうまくインデックスされない場合がある。
        • が、Google側の巡回BOTも進化しているのでうまくインデックスされたりされなかったり
        • 確実にインデックスされてほしい場合だけ、後述の対策をするというのでも良さそう

SSR(Server Side Rendering)

  • SPAのデメリットを解消する方法の一つ。
  • サーバーサイドでJavaScriptを実行し、実行結果をブラウザに返す方法
    • Next.js/Nuxt.jsなど、ReactやVueでSSRを実現しやすくする上位フレームワークなども

SSG(Static Site Generator)

  • ビルド時に先にHTMLを生成する方法。
  • Aboutページなどユーザーや状態によって変化がなく、更新頻度の低い画面に有用
    • HTMLファイルを直接置いておくのと何が違うんだという話ですが
      • 表示する情報はDBなどから動的に構築するが、更新頻度が低いなどキャッシュ的な用途が適している
        • ブログ、デイリーでしか更新されないランキングページなど
      • ページ全体だけでなく、一部はキャッシュ、一部は動的に更新といった形も

⑤テスト

テストの種類

  • 静的テスト
  • 単体テスト
  • 結合テスト
  • E2Eテスト

↑の方が実行速度が速く、実行コストもメンテコストも低い

静的テスト

  • 型やLinterによる静的チェック
  • TypeScript, ESLint

単体テスト

  • 単一のメソッドやコンポーネントに対して入出力が正しいかチェック
  • ロジックが破綻していないか確認できる
  • Jest, Jasmine, Mocha, Ava

結合テスト

  • 複数のメソッドやコンポーネントを組み合わせたときに正しく動作するかチェック
  • 実際のユーザの操作に近いふるまいをテストできる
  • Jest, Testing Library, Enzyme

E2Eテスト

  • ブラウザ上でアプリケーションを操作して正しく動作するかチェック
  • ユーザ操作に着目するので実装の中身は関係しない
  • Cypress, Puppeteer, Selenium

どれをどらくらいやればいい?

⑥ブラウザ

メジャーなブラウザ

  • Google Chrome
  • Internet Explorer
  • Firefox
  • Safari
  • Microsoft Edge

ブラウザ間の差異

開発者ツールの活用