目まぐるしく技術が入れ替わり続けるフロントエンド。
1日単位でトレンドの移り変わることも多く、最新技術をスピーディに取り入れられることは大きなメリットです。
しかし、ひとえに最新技術と言っ ても、一筋縄ではいかないこともあるでしょう。
本当に使われているのはどんなサービスなのか、実際にどれくらいの企業が最新技術を活用しているのかは気になるところです。
開発実績が 100件を超えるインプルの実績に基づき、企業の採用技術や利用状況をカテゴリ別に集計しました。
本記事では、ランキングをもとに利用推移の背景を紐解くとともに、注目すべき技術を紹介します。
CSS の観点から見た技術トレンド
あまり技術を知らないという方でも、ウェブサイトが基本的にこれで作られていることは知っているかたも多いでしょうか。
ここでは、特に CSS について取り扱いたいと思います。
ランタイム vs ゼロランタイム vs ハイブリッド
さて、昨今は ランタイムCSS から ゼロランタイムCSS へのパラダイムシフトが起こり始め、そうした2つの良いところどりをした ハイブリッドランタイムCSS などリリースされました。
ウェブサイトやアプリケーションで使用される CSS の新しいアプローチとして認識されつつあります。
それぞれ何が嬉しいのか伝わりづらいと思いますので、実際にどのような実装になるのか例示します。
ランタイム CSS
現代の ランタイムCSS で、今でも選択候補に上がりうるものとして、CSS Modules や Styled-Component があります。
その他にも、基本的に HTML に直書きしないタイプの CSS ライブラリは全て ランタイムCSS です。
const Component = styled.div< { primary: string }>`
background: ${({ primary }) => (primary ? 'palevioletred' : 'transparent')};
color: ${({ primary }) => (primary ? 'white' : '#333')};
`
// 以下のように定義したスタイルを渡せる
<Component primary={true} />
上記のように、スタイルを定義してからコンポーネントに渡すことによって、開発者体験が担保され、スタイルの使い回しも効きやすいため開発がスムーズであることがメリットとしてあります。
また、定義したクラスをコンポーネントに切り出すことが出来るため、コンポーネント単体で独立させることにより、プロパティの重複や命名規則に悩むことがなくなります。
その他にも、WEB サイトを作成する開発者に対しては良いことが沢山あります。
逆にデメリットとしては、この読み込みと生成に倍の時間かかってしまうことです。
- CSS コンポーネント → 解析 → JSX 生成 → 解析 → HTML 出力
- ライブラリによる解析とブラウザによる解析が2回起こる
また、のちの章でも取り扱いますが、最近では SSR が搭載された Next.js や Nuxt.js がトレンドであり、そもそも DOM にアクセスしないレンダリングが主流になりつつあります。
そのため、ビルド時に要素を解析する CSS-in-JS とは時代がそぐわなくなってきた背景があります。
■ SSR とは
例えば、ユーザーが投稿した内容をサーバー側で解釈し、「投稿した内容」が反映された HTML 要素を生成してそのままレンダリングするアーキテクチャのことを指します。
ゼロランタイム CSS
今日では、Tailwind CSS が ゼロランタイムCSS としては有名どころでしょうか。
また、2023年では先ほど紹介した「 CSS-in-JS 」においても、 vanilla-extract や Linaria が「 Zero-Runtime CSS-in-JS 」という名を上げ始めています。
また、 Emotion は ゼロランタイムCSS としても使えるようにサポートされ始めていますので、メンテナンスが活発であることが伺えます。
通常、CSS はウェブページの見た目やスタイルを定義するために使われます。
ゼロランタイムCSS は HTML に CSS を直書きする代わりに、JavaScript や TypeScript を使ってスタイルを適用します。
以下、Tailwind CSS の実装です。
自己説明的にクラスを付けて、タグ単位でスタイルを修飾するあたりが独特ですね。
<figure class="bg-slate-100 rounded-xl p-8 dark:bg-slate-800">
<img class="w-24 h-24 rounded-full m" src="/sarah-dayan.jpg" alt="" width="384" height="512">
<div class="pt-6 space-y-4">
<blockquote>
<p class="text-lg">
“Tailwind CSS is the only framework that I've seen scale
on large teams. It’s easy to customize, adapts to any design,
and the build size is tiny.”
</p>
</blockquote>
<figcaption>
<div>
Sarah Dayan
</div>
<div>
Staff Engineer, Algolia
</div>
</figcaption>
</div>
</figure>
また、ゼロランタイムCSS で有名な Tailwind CSS は独特な記法を採用しているため、Tailwind CSS が古くなったときに外しにくいというデメリットもあります。
そうした点が許容できない場合は、付け替えやすい CSS-in-JS の選定も良いと思います。
ハイブリッド CSS-in-JS
最近耳にすることが多くなってきた Kuma UI や Panda CSS がそれに当たります。
下記は Kuma UI の実装例です。
import { Box, Heading, css } from "@kuma-ui/core"
function App() {
return (
<Box as="main" display="flex" flexDir={["column", "row"]}>
<Heading className={css`font-sze: 24px;`} >
Kuma UI
</Heading>
</Box>
);
}
このように、CSS を解釈するオーバーヘッドがない形で CSS を指定することもでき、JavaScript や TypeScript の表現力を損なわないまま実装することが出来ます。
また、UI コンポーネントでもあるためスタイリングに一貫性を持たせることが可能で、そうした思想も ランタイムCSS のそれと似通っている部分があります。
かなり柔軟に書き方を変更することができ、ある程度の人数で開発する場合は運用の手法を考える必要が出てきそうです。
2年前の記事ですが、当時のそれぞれの技術について詳しく解説された記事が弊社ブログにございます。
以前までの CSS の勢力図やメリット・デメリットが気になる方はぜひご覧になってみてください。
言語の観点からの技術トレンド
現在のフロントエンドの技術選定は2極化しています。
以前までは型を書くのが面倒でしたが、現在では TypeScript が型推論や型解析を行ってくれることにより、選びやすくなったという背景があります。
ただ、現在でも Ruby などをバックエンドの言語として選択すると、サーバーレスポンスの型を返してくれなかったりと不便な点もあります。
そのため、型を返してくれる技術がスタンダードになるか、Next.js などのサーバーコンポーネントを持つ言語が全て補完してくれる形になれば、もっとメジャーな選択になるかもしれません。
JavaScript
JavaScript は、ウェブページを操作するためのプログラミング言語です。
ウェブ開発の重要な要素であり、ブラウザ上で直接動作する唯一のプログラム言語です。
例えば、ボタンをクリックした時にメッセージを表示させたり、画像を切り替えたり、フォームの入力をチェックしたりすることができます。
他にも、新しい要素をウェブページに追加したり、既存の要素を削除したり、内容を変更したりすることができます。例えば、チャットアプリで新しいメッセージをリアルタイムに表示することができます。
// JavaScriptの場合
const caliculateSum = (a, b) => {
return a + b;
}
const result = add(5, 10);
console.log(result); // 出力:15
TypeScript
TypeScript は前述の JavaScript の機能を兼ね備えています。
その機能に対して型を持つことが可能で、変数や関数の型を明示的に指定することができます。
これにより、「りんごの名前」という形を持った時に、「 Apple 」という値を受け渡せばエラーになりませんが、りんごの数を間違って渡した場合、バグになる前にエラーになるというメリットがあります。
また、TypeScript は型情報を含むことで、コードの意図を明確に表現することができます。
他の開発者がコードを読んだ際に、どのようなデータが流れているか理解しやすくなります。
他にも、エディタによる強力なコード補完をしてくれます。
設定した型情報に基づいて関数の使い方を教えてくれたり、間違った型のデータを入れようとするとエラーを教えてくれる点が便利です。
// 型の宣言
interface Numbers {
a: number;
b: number;
}
// 受け渡した値が文字列などだった場合、エラーになる
const sumCalculate = (props: Numbers) => {
const result = props.a + props.b;
return result;
};
フレームワーク全体で見た技術トレンド
フロントエンドのフレームワークは日々進化し続けています。
しかし、開発者としても最低限あると嬉しい機能はあるので、そちらをまず紹介します。
Progressive Web Apps (PWA)
PWA は、ウェブサイトとネイティブアプリの特徴を組み合わせたものです。
スマートフォンのホーム画面にアイコンを追加して、オフラインでも利用可能なアプリのような体験を提供します。
さらに、アプリの機能はネイティブアプリに匹敵します。
プッシュ通知のようなネイティブアプリ特有の機能もサポートされており、Web API を使用してカメラ、マイク、位置情報などのデバイス機能にアクセスすることができます。
WEB コンポーネント
WEB コンポーネントは、ウェブサイトを構成する小さな部品のようなものです。
例えば、おもちゃのレゴブロックを想像してみてください。
レゴブロックは、それぞれの形や色が違い、組み合わせることで様々な形を作ることができます。
ウェブサイトでも同じように、WEB コンポーネントは個別の部品のようなものです。
例えば、メニューバー、ボタン、画像スライダーなどがコンポーネントになります。
一つのコンポーネントが独立し、他のフレームワークやライブラリに依存することなく使えます。
これは、異なるブラウザやデバイスでも同じように動くことができる大きな利点です。
仮想 DOM (Document Object Mode)
仮想 DOM は、ページ全体を再描画するのではなく、変更があった部分のみを検出します。
全体のウェブページの読み込み後、ユーザーのブラウザで直接実行されます。
これにより、動的なコンテンツの追加、ユーザーの入力の処理 DOM に反映させることができます。
これにより、不必要な DOM 操作を最小限に抑え、ページの再描画コストを削減し、アプリケーションのパフォーマンスを向上させます。
フレームワークから見たトレンド
さて、ここではフロントエンドフレームワークのトレンドを扱います。
React
React は、2023年現在では最も使われているフロントエンドライブラリになります。
厳密にいうとReactはフレームワークではないですが、一応そのように使われている背景はあるため、ここで取り扱います。
React の良いところとして、次のような点が挙げられます。
React は非常に人気があり、世界中の多くの開発者が利用しています。そのため、問題が発生した際には、オンラインで解決策を見つけることができる可能性が高く、コミュニティによるサポートも充実しています。
React では、JSX という特殊な記法を使って、JavaScript のコードと HTML のような要素を一緒に書くことができます。これにより、コードがより直感的になり、開発がスムーズに進みます。
React 自体がライブラリなので単体で使うだけでなく、他のライブラリやフレームワークとも組み合わせて利用することができます。
また、React 自体の機能を拡張するためのプラグインや拡張機能も豊富にあります。
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect } from "react";
const NumberComponent: React.FC = () => {
// 変数の宣言
const [number, setNumber] = useState<number | undefined>();
/**
* 数を計算する関数
*
* @param {number} a 数値1
* @param {number} b 数値2
* @returns {number} 計算結果
*/
const sumCaliculate = (a: number, b: number): number => {
return a + b;
};
useEffect(() => {
const res = sumCaliculate(1, 1);
setNumber(res);
}, []);
// JSXを返す
return <div>{number}</div>;
};
export default NumberComponent;
Next.js
Next.js は React アプリケーションのためのフレームワークであり、以下の主な特徴があります。
Next.js では、サーバーサイドレンダリングをサポートしており、初期のページロード時にサーバーでコンテンツがレンダリングされ、パフォーマンスと検索されやすさを向上させることができます。
Next.js は静的サイトジェネレータとしても機能し、事前にページをビルドして静的ファイルとして配信することができます。これにより、サーバーの負荷を減らし、高速なページロードを実現します。
Next.js では、ファイルシステムを基にしたルーティングがサポートされており、ページの作成と管理が簡単です。
また、開発中にコードを編集した際に、自動的にページをリロードして即座に変更を確認できる便利な機能(ホットリローディング)があります。
また、Next.js は React ベースのフレームワークですが、Vue.js のように書きたい場合は Nuxt.js を選定する方が良いと考えます。
Next.js は React と共存するため、先ほどの React のコードを Next.js 形式のコンポーネントを作ることで簡単に使うことが出来ます。
Vue.js / Nuxt.js
Vue.js は、React と並んで非常に人気のあるフロントエンドフレームワークで、シンプルで直感的なAPIを持つことが特徴です。
ほぼ Next.js と嬉しさは一緒ですが、Vuex が使用できたり、Vue に知見がある人にとっては良い選択肢になるかと思います。
また、Vue は独自のコンポーネントを使用します。
そのため、ディレクトリ構成や書き味が React や Next.js とは全く違う形になります。
<!DOCTYPE html>
<html>
<head>
<title>Number Component</title>
</head>
<body>
<div id="app">
<number-component></number-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
// Vueコンポーネントの定義
Vue.component('number-component', {
data() {
return {
number: 0,
};
},
created() {
this.sumCalculate(1, 1);
},
methods: {
/**
* 数を計算するメソッド
*
* @param {number} a 数値1
* @param {number} b 数値2
*/
sumCalculate(a, b) {
const result = a + b;
this.number = result;
},
},
template: '<div>{{ number }}</div>',
});
// Vueインスタンスの作成
new Vue({
el: '#app',
});
</script>
</body>
</html>
Angular
Angular は、Google によって開発されたフロントエンドフレームワークで、大規模なアプリケーションの開発に適しています。
Angular では、入力した値をデータにバインドしたりする機能を提供しています。これにより、アプリケーションの状態とビューが自動的に同期され、データの変更がリアルタイムに反映されます。
Angular は強力なルーティング機能を持っています。
これにより、アプリケーションの異なるビュー(ページ)間をシームレスに切り替えること可能です。
また、依存性注入 (DI) というデザインパターンをサポートしています。
これにより、コンポーネントが必要とするサービスやデータを外部から注入することができます。
さらに、Angular は TypeScript を使用しています。
これにより、エラーを早期に検出することができ、コードの品質が向上します。
他にも、コンポーネントではなく、モジュール化されたアーキテクチャを採用しています。
アプリケーションを機能ごとにモジュール化して、コードの管理や開発の拡張性が向上します。
下記のように、コンポーネントを先に初期化して selector に記載されているものを<app-number></app-number>
のように HTML 構文の中で呼び出すことで利用することが出来ます。
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-number',
template: '<div>{{ number }}</div>',
})
export class NumberComponent implements OnInit {
number: number = 0;
/**
* 数を計算するメソッド
*
* @param {number} a 数値1
* @param {number} b 数値2
*/
sumCalculate(a: number, b: number): void {
const result = a + b;
this.number = result;
}
ngOnInit(): void {
this.sumCalculate(1, 1);
}
}
Svelte
Svelte は、React や Vue.js とは異なるアプローチを取ったフロントエンドフレームワークであり、ビルド時にコンパイルされるという特徴を持っています。
これにより、ランタイムのフレームワークが不要となり、生成されたコードが非常に軽量になります。以下に、Svelte の主な特徴とメリットを詳しく解説します。
Svelte は、コンパイル型のフレームワークであり、開発者がコードを記述した後、ビルドプロセスによって Svelte コンポーネントが純粋な JavaScript に変換されます。
Svelte 自体のランタイムが不要となり、生成されるコードが非常に軽量で効率的になります。
Svelte は自身のランタイムを持たないため、他のフレームワークやライブラリとの統合が容易です。
既存のプロジェクトに Svelte コンポーネントを組み込むことができます。
コンパイル時に最適化されたコードを生成するため、Svelte アプリケーションは高速に動作します。
ランタイムのオーバーヘッドがないため、ページの読み込み速度が向上し、ユーザーエクスペリエンスが向上します。
静的サイトを作る時に重宝するイメージでしたが、最近ではWEB開発においても主流な選択肢となっているようです。
<script>
// 変数の宣言
let number = 0;
/**
* 数を計算する関数
*
* @param {number} a 数値1
* @param {number} b 数値2
*/
function sumCalculate(a, b) {
const result = a + b;
number = result;
}
// コンポーネントが作成された後に実行
sumCalculate(1, 1);
</script>
<div>{number}</div>
まとめ
直近で発足するプロジェクトにおいて「より軽量に、より早く」といったところが要求として重視されつつある印象を受けます。
顧客の要望をできるだけ吸い上げて、実現する方法を模索していきましょう。