技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

JavaScript (+LWC)のチュートリアル: リバーシを作る(1)

概要

第一回目は LWC (オープンソース版)のインストールと、基本的使い方まで

前提知識

基本的な JavaScript コードが書ける前提。

目次

LWC インストール

Python3 系統がインストール済みの Windows の場合、WSL にインストールする手もあります。LWC …と言うより Nodejs の関連リソースが Python2.7 を要求してくるためです。
尚、LWC にインストールして起動した場合、ファイル更新だけでは画面が更新されません。どうやらファイル監視処理がキックされないご様子…

NodeJS のインストール(Windows)

NodeJS を Windows にインストールする方法はいくつかあります。
公式サイト からダウンロード・インストールする方法と、Chocolatey を使う方法があります。
MAC 使いなら Homobrew の Windows 版と言えばわかりやすいですかね?

公式サイトからのインストール

https://nodejs.org/ja/

こちらより LTS 版をインストールすればOKです。
インストーラーはイエスマンをしておけば大丈夫ですね。

一つだけ注意点はセットアップ最後の下記画面、「Tools for Native Modules」ではチェックボックスを入れましょう。

インストールダイアログを閉じたあとで追加のインストーラーがコンソールアプリで起動します。これもイエスマンすればOKです。

追加で、Python2.7 もインストールしておきます。
なんで Python かというと、LWC 開発の 一部依存モジュール が Python 2.7 に依存してしまっているからですね…。

...パッケージ腐ってんじゃねぇかゴルァとも思わなくない瞬間。

https://www.python.org/downloads/ を参照して、最新の 2.7.XXX をダウンロード&インストールしましょう。

Chocolatey を使ったインストール

Chocolatey は Windows で Linux 的なパッケージマネージを行いたい人のためのコンソールです。
個人的にはこっちがオススメですね…

Chocolatey はこちらからインストールします。 https://chocolatey.org/install
ただしくらしいインストール方法は今回の本題から外れるので、URL の先が英語ですが頑張ってください…

インストールコマンドは下記です。

choco install nodejs-lts

Python2.7 も入れておきましょう。

choco install python2 でインストールできます。

LWC の Ubuntu (Ubuntu 22.04.1 LTS)へインストールする

LWC で NodeJS を行う場合も説明します。
特に Windows 環境を汚したくない人向けですね…

pyenv をインストールする

NodeJS の一部ライブラリで Python2.7 に依存があるので、最新の Python (この記事の時点で 3.11) と共存させるための設定を行います。

$ curl https://pyenv.run | bash で pyenv (Pythonのバージョン管理コマンド)をインストールして、PATHを設定します

$ cat << 'EOF' >> ~/.bashrc
export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
EOF

そしたら必要なライブラリをインストールして

$ sudo apt update; sudo apt install build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev curl \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

Python 2.7 をインストールします。

$ pyenv install 2.7.18
$ pyenv global 2.7.18
$ pyenv rehash

すると

$ python --version
Python 2.7.18

NodeJS インストール

NodeJS は n コマンド で管理することにします。

$ sudo apt install nodejs npm -y
$ sudo npm install n -g
$ sudo n stable

ここまでで安定版の nodejs がインストールされます。
こうなったら apt でインストールされた nodejs は邪魔なので消してしまいましょう。

$ sudo apt purge -y nodejs npm

 LWC のセットアップ

開発に使う作業ディレクトリを作成し、npm init lwr を実行します。
プロジェクト名は lwc_reversi LWCシバーシとでもしておきましょう。

アプリケーションのジャンルは Single Page App で、プロジェクトテンプレートは LWC を選択します。
LWC(Typescript) もありますが、Typescript は別言語なので、今回は扱いません。

実行できたら、続いて以下のコマンドを実行します

> cd lec_reversi
> npm install

ちなみに、Python3 系が入ってると、優先的にそちらを参照して下記の様なエラー吐き出すので、混乱を避ける意味では削除したほうが安全です。

npm ERR! ValueError: invalid mode: 'rU' while trying to load binding.gyp
npm ERR! gyp ERR! configure error
npm ERR! gyp ERR! stack Error: `gyp` failed with exit code: 1
npm ERR! gyp ERR! stack     at ChildProcess.onCpExit (D:\OneDrive\workspace\study\LWC_Reversi\lwc_reversi\node_modules\node-gyp\lib\configure.js:351:16)
npm ERR! gyp ERR! stack     at ChildProcess.emit (node:events:513:28)
npm ERR! gyp ERR! stack     at ChildProcess._handle.onexit (node:internal/child_process:291:12)
npm ERR! gyp ERR! System Windows_NT 10.0.22621
npm ERR! gyp ERR! command "C:\\Program Files\\nodejs\\node.exe" "D:\\OneDrive\\workspace\\study\\LWC_Reversi\\lwc_reversi\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild"
npm ERR! gyp ERR! cwd D:\OneDrive\workspace\study\LWC_Reversi\lwc_reversi\node_modules\node-zopfli-es
npm ERR! gyp ERR! node -v v18.13.0
npm ERR! gyp ERR! node-gyp -v v7.1.0
npm ERR! gyp ERR! not ok

最後に以下のコマンドで開発サーバを作成しましょう。

npm run start

起動したら http://localhost:3000 にアクセスします。

確認したらコンソール画面で Ctrl + c でサーバを停止しましょう。
直井、この start はプロダクションモード(リリースで使う想定)での起動になります。

開発中は npm run dev を使います。

LWC を読み解いてみる

では今度はファイルを書き換えながら結果を確認してみましょう。
npm run dev でブラウザ上にて画面を表示しておきます。

LWC の基本セット

まずソースを見てみると、ソース改装は下記のようになっている。

実際に手を加えて挙動を確認してみましょう。
わかりやすいところで、 app.html を弄くる。

<template>
    <main>
        <img src="/public/assets/recipes-logo.png" alt="logo" />
        <h1>Hello World!</h1>
        <p>これが追加行でございます!</p>
    </main>
</template>

保存した瞬間に表示できます。

app.css スタイルシートで p タグの色を変えてみますか。

main {
    margin: 30px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

h1 {
    color: #1798c1;
}

/* 追加スタイル */
p {
    color: #ff0000;
}

イベントハンドラ

では今度は app.js から JavaScript 側からの画面修正を行いましょうか。
やることは画面で発生したイベントで、JavaScript 側で変数を更新、画面に反映するという流れです。

import { LightningElement, track } from 'lwc';

export default class HelloWorldApp extends LightningElement {

    /* ここから */
    @track count = 0;
    handleClick() {
        this.count++
    }
    /* ここまで */
}

app.html 側もこれに合わせて修正します

<template>
    <main>
        <p>Click count : {count}</p>
        <button type="button" onclick={handleClick}>クリック</button>
    </main>
</template>

ボタンをクリックするごとに handleClick が起動し、カウントされていきます。
track を指定すると、JavaScript 側の count が変化するたびに画面側の {count} が連動して変化することになります。

テンプレートロジック

IF 分岐

表示分岐のロジックです

import { LightningElement, track } from 'lwc';

export default class HelloWorldApp extends LightningElement {

    @track count = 0;
    handleClick() {
        this.count++
    }

    get over10() {  // 10 以上で true を返すゲッター
        return this.count >= 10;
    }
}

画面側は

<template>
    <main>
        <p>Click count : {count}</p>
        <button type="button" onclick={handleClick}>クリック</button>

        <!-- 追加行 -->
        <template if:false={over10}>10 未満です…</template>
        <template if:true={over10}>10 クリックを超えました!</template>
    </main>
</template>

クリック数が増えると

ループ表示

ループ表示にも対応しています。

import { LightningElement, track } from 'lwc';

export default class HelloWorldApp extends LightningElement {

    @track count = 0;
    @track datalist = [];

    handleClick() {
        this.count++
        this.datalist.push({
            count: this.count,
            message: `Current is ${this.count}`
        });
    }
}

画面側は

<template>
    <main>
        <p>Click count : {count}</p>
        <button type="button" onclick={handleClick}>クリック</button>

        <template for:each={datalist} for:item="item">
            <div key={item.count}>{item.message}</div>
        </template>
    </main>
</template>

すると画面は

注意点として、2点制限があります。

  • ループ内容直下は 1 つのタグであること
  • タグには key 属性が設定され、ユニークな値が設定されること

次回はコンポーネントの使い方について言及していきます。