Webアプリケーションの構成と開発技術
Webアプリケーションの構成と、Webアプリケーションの開発技術について調べたことをメモします。
普段は、ガチガチのデスクトップアプリケーションとサーバーアプリケーションで構成しているので、Webアプリケーションの構成はあっさりとの知識、開発技術については聞きかじりとJavaを使う技術(Servlet、JSP、JSFなどJEE関連)に関して自習レベルでの知識、Ruby on Railsについてプラグインを作った知識がある前提での調査です。
返答 (8)
フロントエンドと呼ばれるユーザー側の端末での構成 - 高橋 徹 さんが8ヶ月前に追加
ユーザーが操作するPC等の情報機器において、Webブラウザを使用し、Webサーバーで用意したHTML、CSS、JavaScriptのコードをHTTP通信で取得して描画するのが典型的な構成です。
最低限必要なコードはHTMLで記述されたコンテンツです。これに追加して、CSSでコンテンツの表示の制御(配置、色、フォントなどの制御)を行います。JavaScriptは、表示されるコンテンツに動的な処理を施します。(マウス操作に反応してコンテンツを変化させるなど)
フロントエンド:ブラウザ上で動作するHTMLとJavaScript、CSSで構成されるプログラムやデータ一式
「Real World HTTP 第3版」13.1 用語の整理より引用(渋川よしき著、オライリージャパン刊)
Webブラウザは、HTML、CSS、JavaScriptのコードを解釈して描画・実行するエンジンを搭載しています。
基本的な構成¶
- HTML(Hyper Text Markup Language)
文書構造をマークアップ言語で記述するもので、見出し、段落、箇条書き、ハイパーリンク、表、画像などをコンテンツと一緒に記述します。
HTMLの仕様は、WHATWG が制定する HTML Living Standard です。(HTML5ではなかった・・・)
- CSS(Cascading Style Sheets)
HTMLのマークアップ(タグ)に対して、見た目の修飾を記述するもので、配置、色、フォント、マウスオーバーの動きなどを制御できます。CSSは、HTMLの中に記述することも、外部ファイルに記述してHTMLから参照することもできます。
CSSの仕様は、W3C が制定しています。CSS Snapshot 2023(毎年更新されている)にその時点での仕様について記載がある模様。なお、CSS実装者向けの仕様です。
- JavaScript
プログラミング言語の一つJavaScriptをWebブラウザ上で実行し、コンテンツにざまざまな動きを付けます。
HTMLやCSSの構造にアクセスして動的に変化させることで、スライドショー、アニメーション、2Dグラフィックス(Canvasで図形表示)などを実行するほか、動画、サウンドの制御、フォームなどのチェック、様々なロジックの処理などを行います。
JavaScriptは、HTMLの中に記述することも、外部ファイルに記述してHTMLから参照して実行することもできます。
JavaScriptの言語仕様は、Ecma International がECMAScriptとして制定しています。また、JavaScriptがWebブラウザ上で利用できるAPIについては、WHATWGが制定しています。
WebAssembly¶
WebAssembly(Wasm)は、スタック方式のバイナリ命令語の仮想マシンでプログラムを小さく高速、かつセキュアに実行することを目的に開発されました。ブラウザに搭載され、計算処理などをJavaScriptに比べて高速に実行します。Wasmモジュールはサンドボックス内で実行されます。ただし、HTMLやCSSの構造にはアクセスすることはできません。
WebAssemblyは、W3Cで制定されています。
Wasm命令語には、いろいろなプログラミング言語から変換(コンパイル)することができます。
- Kotlin/Wasm : 2023/12にアルファ版リリース
- Rust : WebAssembly用プログラム開発によく使われている
- C/C++
- Go
- Java : TeaVMを使い、JavaバイトコードからWasmコードを生成 Getting started
WebGL¶
Webブラウザ上でGPUを活用したグラフィックス描画を行う機構です。HTMLのcanvas要素にJavaScriptでWebGLのAPIを呼び出し描画します。
WebGL 2.0 APIは、OpenGL EL 3.0をベースとしています。また、シェーディングにGLSL(OpenGL Shading Language)を使用することができます。
Webサイトの構成方式¶
- MPA (Multi Page Application)
ページが切り替わる際に、サーバーと通信しHTMLを取得する方式。HTMLのリンクでページ遷移する。 - SPA (Single Page Application)
ユーザー操作等で画面内容が動的に変化する方式。URLは基本は1つ。
レンダリング方式¶
ここでのレンダリングは、Webブラウザが解釈できるコンテンツ(HTML等一式)を生成するという意味です。HTML, CSS等を元にWebページを表示するレンダリングとは別の意味です。
- CSR (Client Side Rendering)
ブラウザのJavaScriptで動的にHTMLを出力する方式。React/Vue.jsによるSPAで使われる。 - SSR (Server Side Rendering)
CSRの課題を解決するために、初回(1回目のブラウザ表示)にサーバー側で動的にHTMLを出力する方式。 - SSG (Static Site Generator)
あらかじめHTMLを生成しておく方式。動的な生成は限定的(ビルド間隔に応じてコンテンツを変化させる程度)となる。 - ISR (Incremental Static Regeneration)
SSRの結果をキャッシュしておき、同じリクエストに対する応答はキャッシュを返すようにする方式。サーバー負荷を軽減、キャッシュの期限を設けて変化するデータにある程度対応できる。
参考書籍:「フロントエンドの知識地図」(池田泰延,西原翼,松本ゆき ら著、技術評論社刊)
フロントエンドでのJavaScript開発情報 - 高橋 徹 さんが8ヶ月前に追加
Webブラウザ上のJavaScript開発動向は、移り変わりが激しいようです。
- JavaScript自身の動向
- JavaScriptでWebアプリケーションの各機能の提供ライブラリ・フレームワークの動向
- 型安全なTypeScript
情報収集メモ¶
- 【2024年版】JavaScriptのおすすめライブラリ&フレームワーク40選
https://kinsta.com/jp/blog/javascript-libraries/ - 【2023年最新】JavaScriptのおすすめライブラリとフレームワーク44選
https://engineer-style.jp/articles/7395 - 2024年に学習したい!おすすめのJavaScriptライブラリ 10選
https://nnc-studio.jp/plugin/2023/12/18/2024-javascript-library-10/
画面構成のライブラリ
React¶
- JavaScriptをHTMLのように記述する構文 JSX を提供
- コンポーネントに props でデータを与える
- JavaScriptに近い書き方
Vue.js¶
- 単一ファイルコンポーネント(Vue Single File Component)で、HTML、CSS、JavaScriptを1つのファイルに記述
- トランジション機能(要素の出現、消失の際にアニメーションを追加)
Svelte¶
- 事前にコンパイル
Webサイト作成のフレームワーク
Next.js¶
Reactを拡張し、複数ページのルーティング、色々なレンダリング対応、データ取得などをサポート
Next¶
Vue.jsを拡張し、複数ページのルーティング、色々なレンダリング対応、データ取得など。
SvelteKit¶
Svelteを拡張し、複数ページのルーティング、色々なレンダリング対応
フロントエンド開発環境 - 高橋 徹 さんが8ヶ月前に追加
フロントエンド、すなわちWebブラウザ上で表示するコンテンツの表示・操作といったユーザーインタフェースは、HTML, CSS, JavaScriptなどを組み合わせて開発をします。
エディタ¶
JavaScript、HTML、CSSの言語仕様に応じて文法を解釈してインデント、色付け、補完をする機能を持つ編集環境として、VS CodeやWebStorm、IntelliJ IDEA Ultimateなどがあると良いです。
動作確認のためのWebサーバー¶
Webブラウザ上のコンテンツはWebサーバーが必要となります。コードを書きながら、表示・操作などを即座に確認できるよう、開発マシン上にローカルサーバーを立ち上げます。
コードの変更を即時にWebブラウザ上に反映できる HMR や Hot Reload 機能を活用すると効率が良い開発ができます。
Node.js環境¶
開発者のマシンに、JavaScriptをブラウザではなくコマンドライン環境で実行できるNode.jsを入れます。Node.jsでは、JavaScriptの実行だけでなく、ライブラリ、ツールなどのインストール・管理をするツールも利用します。
- Node.jsでは、パッケージ管理ツールnpmが主流でしたが、最近ではasdfが良いらしい
Webアプリケーションの動作パターン - 高橋 徹 さんが8ヶ月前に追加
ウェブアプリケーションは静的なHTMLファイルによるウェブサイトと異なり、データベースなどに格納した情報を元に、動的にページ内容が変わるサービスです。
「Real World HTTP 第3版」13.4節より
同書籍では、歴史的な経緯で次のように整理しています。
- 第1世代
サーバー上でデータベースなどにアクセスしたデータをテンプレートに流し込んでHTMLにする。テンプレートには、erb, Jinja2, JSP, JSFなど言語やフレームワークごとにより多数あり。データの送信(ブラウザ→サーバー)にはフォームを使いPOST送信に対応。 - 第2世代
Ajaxによりブラウザ上でJavaScriptで動的にページを更新する。 - 第3世代
SPA (Single Page Application)、Ajaxがさらに進化し、仮想DOMなどを使ってブラウザ上の画面を動的・高速に更新する。 - 第3.5世代
SPA + SSR (Server Side Rendering) で初回表示の待ち時間改善、SEO対策がされる。
第1世代は、画面更新の方式はMPAでHTMLの生成はサーバー側で行う動的なWebサイトの基本形となります。
第3世代は、第2世代の拡充として、画面更新の方式はSPAでHTMLの生成はクライアント側で行う動的なWebサイトで「モダンな」と言われるWebアプリケーションの基本形です。
第3.5世代は、第3世代の課題解決の改善形です。
Reactお試し - 高橋 徹 さんが8ヶ月前に追加
React公式サイトのスタートガイドを習います。
https://ja.react.dev/learn
ローカルマシンで Reactを使うフロントエンドの開発環境を用意します。およそ次の流れとなります。
- Node.jsをインストール
- Node.js上でcreate-react-appで開発ディレクトリを作成
- App.jsなどのコンテンツの編集
- nom startでローカルのWebサーバーを実行し動作確認
create-react-app を使わず、手で必要な作業を1つ1つ実施しようとしましたが、ローカルマシンでのWebサーバーを利用するためには多数の module が入ってしまい、あまり create-react-app と変わらないので中止。
- [Note]create-react-appは、React公式から外れてコミュニティのmaintenanceになった模様、代替手段の一つはvite
クイックスタート¶
MacOSで、node.jsがインストール済みの環境で実施しました。
- create-react-app でReactライブラリを使うフロントエンドのプロジェクトの雛形を生成
% npx create-react-app hello_react
:
生成されたディレクトリ、チュートリアルに関係するものを抜粋
hello_react +-- node_modules/ | +-- 800以上のディレクトリが生成、それぞれモジュールが置かれている +-- public | +-- index.html +-- src +-- App.js
src/App.jsを編集してスタートガイドを進めます。
public/index.htmlはコード中に%PUBLIC_URL% のような記述が含まれています。また、App.jsを呼び出すようなscriptのリンクは記述がありません。
ローカルWebサーバーを起動して、port 3000にアクセスするとApp.jsの記述が表示されます。推測を交えると次の動きと思います。
- public/index.html
- body要素に次のdiv要素が記述されている
<div id="root"></div>
- body要素に次のdiv要素が記述されている
- public/index.js
- rootのidを持つ要素をDOMから取得し、この中にApp.jsの内容を生成
- 合わせて、index.cssを読み込んでいる
App.jsはJavaScriptのソースファイルですが、JSXというReactで用意された記法を用いてHTMLコンテンツを定義します。
- UI要素(コンポーネント)は、JavaScriptの関数として定義
function MyButton() {
return (
<button>
I'm a button
</button>
);
}
- UI要素(コンポーネント)を定義する関数名は大文字で開始
- JSXの記述を返却、HTML記述の要素は1つ(ネストはOK)
divで囲むほか名前なしタグも使用可能 - HTMLの記述は、文字列ではなく、JavaScriptの構文拡張(JSX)として記述
- HTMLの記述でタグは全て小文字とする
- HTMLのタグは厳密に閉じる
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}
- export defaultで、トップレベルのUIコンポーネントを記述した関数を定義
- JSXでは、HTML属性のclassがJavaScript予約名と衝突するので、classNameと属性名を変更して記述
- CSSは、従来通りCSSファイルに記述
- JSXの中でJavaScriptの式を入れる際は、波括弧で囲み式を記述
<img className="avatar" src={user.imageUrl} />
- イベントの応答(クリックしたら処理を実行)
function MyButton() { function handleClick() { alert('You clicked me!'); } return ( <button onClick={handleClick}> Click me </button> ); }
- コンポーネント(関数)に状態を覚えさせることが可能(useState)
useで始まる関数は、フック関数で、コンポーネントのトップレベルでのみ呼び出し可能import { useState } from 'react'; function MyButton() { const [count, setCount] = useState(0); function handleClick() { setCount(count + 1); } }
- 現在の状態と、状態を更新する関数の2つを指定、上述は、状態名countと更新関数setCountを指定
処理の中で、countで状態を参照し、setCountで状態に値を設定することが可能。 - 複数のコンポーネントで状態を共有する場合、親のコンポーネントに状態を用意し、子コンポーネントのpropsで状態変数と更新関数を渡す
function MyApp() { const [count, setCount] = useState(0); : function handleClick() { ... } return ( <div> <MyButton count={count} onClick={handleClick} /> </div> ); } function MyButton({ count, onClick }) { return ( <button onClick={onClick}>Clicked {count} times</button> ); }
- 現在の状態と、状態を更新する関数の2つを指定、上述は、状態名countと更新関数setCountを指定
Vue.jsお試し - 高橋 徹 さんが7ヶ月前に追加
"Vue.js公式サイトのクイックスタートを習います。
https://ja.vuejs.org/guide/quick-start
2020年にリリースされたv3.0で導入のComposition APIを使います。
クイックスタート¶
MacOSで、node.jsがインストール済みの環境で実施しました。
npm create vue@latest でVue.jsフレームワークを使うフロントエンドのプロジェクトの雛形を生成
work % nom create vue@latest
Need to install the following packages:
create-vue@3.10.4
Ok to proceed? (y)
> npx
> create-vue
Vue.js - The Progressive JavaScript Framework
✔ Project name: … hello-vue
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit Testing? … No / Yes
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint for code quality? … No / Yes
✔ Add Vue DevTools 7 extension for debugging? (experimental) … No / Yes
:
Done. Now run:
cd hello-vue
npm install
npm run dev
- いくつか質問されますが、Project name以外はデフォルトのまま(ほとんどNoが選択)
- Project nameに入力した名前のディレクトリが生成される
- 生成されたディレクトリに移動し、npm installを実行して依存モジュールをインストール
- サーバー起動は、npm run dev実行
生成されるディレクトリ
hello-vue +-- index.html +-- jsconfig.json +-- node-modules/ +-- package.json +-- public/ +-- src/ | +-- App.vue | +-- assets/ | +-- components/ | +-- main.js +-- vite.config.js
サーバーの実行
hello-vue % npm run dev
> hello-vue@0.0.0 dev
> vite
VITE v5.3.1 ready in 430 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
Webブラウザで http://localhost:5173 を開くと、アプリが表示されます。
src/App.vue が単一ファイルコンポーネント SFC (Single File Component)で、ここにスクリプト、HTMLテンプレート、スタイルの記述をします。
<script setup>
import { ref, reactive } from 'vue'
const message = ref('Hello, World!')
const counter = reactive({
count: 0
})
counter.count++
</script>
<template>
<h1>{{message}}</h1>
<p>Count: {{counter.count}}</p>
</template>
<style>
.title {
color: red;
}
</style>
- SFC ファイル(拡張子.vue)は、大きく3つのブロック、script、template、およびstyleから構成
- <script setup> にJavaScriptでロジックを記述
ここに宣言したインポート、トップレベル変数、トップレベル関数はテンプレート内で直接使用可能 - <template> にHTMLを拡張したテンプレート構文を記述
JavaScriptの状態を使用した記述が可能、状態(reactive)が変わると自動的にHTMLが更新 - <style>にCSSのスタイルを記述
- <script setup> にJavaScriptでロジックを記述
- scriptとtemplateの連携
- タグに囲まれたテキスト部分に、二重波括弧でJavaScriptの式を記述
<h1>{{message.replace('_', ' ')}}</h1>
- タグの属性の値には、v-で始まる特別なディレクティブを使用しJavaScriptの式を使用可能
- v-bindで属性の値を動的に指定
<script setup> import { ref } from 'vue' const headerClass = ref('alert-header') : </script> <template> <h1 v-bind:class="headerClass">注意事項</h1> : </template>
- v-onでイベントの発行時にscriptの関数を呼び出す
<script setup> import { reactive } from 'vue' const counter = reactive({ count: 0 }) function increment() { counter.count++ } </script> <template> <p>Count: {{counter.count}}</p> <button v-on:click="increment">Increment</button> </template>
- v-bindで属性の値を動的に指定
- タグに囲まれたテキスト部分に、二重波括弧でJavaScriptの式を記述
- refかreactiveか
似た機能で、推奨はref
React.jsでTypeScript - 高橋 徹 さんが7ヶ月前に追加
React.jsライブラリを使ったWebクライアントアプリケーション作成プロジェクトで、ScriptをTypeScriptで記述する際の環境構築、コーディングのメモです。
LEAR REACT > インストール > TypeScriptの使用(公式サイトチュートリアル)
https://ja.react.dev/learn/typescript
プロジェクトの雛形を create-react-appで生成時にオプション --template typescript
を指定 実行結果を表示する隠す
% npx create-react-app --template typescript hello_type
Creating a new React app in /Users/torutk/work/hello_type.
Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts with cra-template-typescript...
added 1482 packages in 10s
262 packages are looking for funding
run `npm fund` for details
Initialized a git repository.
Installing template dependencies using npm...
added 42 packages, removed 1 package, and changed 2 packages in 2s
262 packages are looking for funding
run `npm fund` for details
We detected TypeScript in your project (src/App.test.tsx) and created a tsconfig.json file for you.
Your tsconfig.json has been populated with default values.
Removing template package using npm...
removed 1 package, and audited 1523 packages in 1s
262 packages are looking for funding
run `npm fund` for details
8 vulnerabilities (2 moderate, 6 high)
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
Created git commit.
Success! Created tictactoe_typescript at /Users/torutk/work/hello_type
Inside that directory, you can run several commands:
npm start
Starts the development server.
npm run build
Bundles the app into static files for production.
npm test
Starts the test runner.
npm run eject
Removes this tool and copies build dependencies, configuration files
and scripts into the app directory. If you do this, you can’t go back!
We suggest that you begin by typing:
cd tictactoe_typescript
npm start
Happy hacking!
生成されるアプリケーションのJSXファイルは、src/App.tsxとなっています。
TypeScriptの書き方メモ¶
- 関数は、引数、戻り値にそれぞれ型を指定
function add(a: number, b: number) { return a + b; }
- 変数は、型を指定
let name: string
組み込み型は、string, number, boolean, ..., 配列- タプルっぽい変数
let role: [number, string]
- ユニオン
let age: number | string
- タプルっぽい変数
- オブジェクトの型は、typeまたはinterfaceで定義
type Person = { name: string; age: number; }; let person: Person = { name: "Thomas", age:
Reactコンポーネントの定義
React.jsのUIコンポーネントの記述例を見ると、関数定義のものと、関数式(アロー関数)を変数に代入するものと大きく2つの記法を見かけます。
項目 | 関数定義 | 関数式 |
---|---|---|
型注釈なし |
|
|
型注釈あり |
|
|
- 関数式は、アロー関数で無名関数を定義し、それを定数(変数)に代入する記述となり一見複雑。簡易な場合(1つの式を評価して返却する)に、関数本体のブロックの波括弧とreturnの予約語を省略できる
- 省略好きなプログラマーに受けている?
- 省略された記法は慣れないと理解が難しい
- thisの扱い(アロー関数を定義したスコープのthisとなるとのこと)
- 関数式は変数の型が React.FC (React.FunctionalComponent)を明記できる(意味があるかどうか要検討)
- 公式サイトのチュートリアルでは、関数定義の記法を使用
- ブログ等の記事では関数式(アロー関数)の記法を多く見かける(観測範囲では)
記法の使い分けについての参考となる記事
- React+TypeScript Cheatsheets
- TypeScript: Function Declarations vs. Function Expressions
- もしReact関数コンポーネントの書き方で迷ったら
- Arrow Functions in React.js: A Practical Guide with Examples
簡潔に書ける、thisのスコープが定義した場所に基づく、がアロー関数のメリット - Typescript for React Components From Beginners to Masters YouTube
そのほか、書き方で悩みそうな項目
- 関数コンポーネントの戻り値型は、JSX.ElementかReactNodeか?
- 明記するならReactNodeにしておくのが良さそう(型推論ではJSX.Elementになるので明記しないでも良さそう)
- 省略しても型安全が壊れるわけではなく、推論によってJSX.Elementが戻り値型として検査される(はず)
- ただし、return直後に改行して次にJSX構文を記述すると、voidを戻り値にしたこととなり、型推論でvoidとなってしまう。改行されたJSX国文は、未到達コードとなる
- 型推論に任せて必要な(型安全を確保したい)ところに限定して型注釈を記述が良さそう
- JSX.Elementを記述する場合、JSX(グローバル名前空間)はdeprecatedとなっているので、React.JSX.Elementとする
- Propsの定義は typeかinterfaceか?
- 関数コンポーネント毎にPropsを定義するのか(面倒)、共通なPropsの定義を使い回すのか(余分なプロパティが多数含まれる)?
- 子要素(children)の扱い
- 都度、Propsの定義に
children: ReactNode
を記述するか - PropsWithChildrenをreactライブラリからインポートして独自のPropsと交差して使用
- 都度、Propsの定義に
React.jsでTypeScript(続) - 高橋 徹 さんが7ヶ月前に追加
TypeScriptでReactコンポーネントを記述する例
Propsを取る関数(引数が1つ)¶
型を指定しないとエラーとなります。Propsは次のように指定します。
JavaScriptコード | TypeScriptコード |
---|---|
|
|
Propsを取る関数(引数が複数)¶
ベタに並べる方法と、型を定義して指定する方法とがあります。
ベタに並べる | 型を定義して指定 |
---|---|
|
|
- typeまたはinterfaceで、UIコンポーネント関数のPropsに渡す型を定義し、コンポーネントの引数でこの型を型注釈する
命名の慣習として、コンポーネント名+Props (例、Squareの場合は、SquareProps) function Square({ props }: { props: SquareProps }) { ... }
と記述すると、関数内でprops要素にアクセスする際、props.value
のように少し冗長な記述になる。そこで、分割代入で propsのメンバーを個別の変数で受け取る
- ComponentProps がreactから提供されており、
ComponentProps<typeof Button>
とするとbutton要素の属性が利用可能となる
useStateでnullを指定したい場合¶
const [value, setValue] = useState<string | null>(null);
マウスクリックを扱う¶
function Square() {
const [value, setValue] = useState<string | null>(null);
const handleClick = () => setValue('X');
return (
<button className="square" onClick={handleClick}>
{value}
</button>
);
}
コールバック関数をアロー関数で定義して、JSXの要素で属性の値に指定しています。