定年後にWeb開発者目指す https://software.pitang1965.com 2019年1月から学習開始 Sun, 15 May 2022 14:16:31 +0000 ja hourly 1 https://wordpress.org/?v=5.9.3 https://software.pitang1965.com/wp-content/uploads/2021/06/cropped-yama512-32x32.png 定年後にWeb開発者目指す https://software.pitang1965.com 32 32 Frontity使ってみた https://software.pitang1965.com/2022/05/15/frontity-getting-started/ https://software.pitang1965.com/2022/05/15/frontity-getting-started/#respond Sun, 15 May 2022 14:16:28 +0000 https://software.pitang1965.com/?p=4081 既存のWordPressサイトをReactベースでヘッドレス化するのにFontityをちょっと試してみました。

動機

GatsbyでヘッドレスWordPressのブログを運営しています。しかし、面白くない問題に遭遇しました。ホームページから各記事をクリックした場合は問題がないのですが、各記事のURLを直接入力したり、各記事でリロードすると、画像が消えてしまうのです。この原因は自分のコードではなく解決が難しい気がしました。

そこで、別のツールを試してみようと思いました。

人気度からいえば、Next.jsが一番でしょうが、FrontityというWordPressに特化したマイナー(npm trendsより)なやつを使ってみました。

npm trendsによるダウンロード数

青:frontity、オレンジ:gatsby、緑:nextです。

インストール

$ npx frontity create software-blog
? Pick a starter theme to clone: 
  @frontity/mars-theme (recommended) 
> @frontity/twentytwenty-theme 

インストールが終わると次のような画面になります。

frontityのプロジェクトの生成

プロジェクトの実行

次のコマンドで実行できます。

$ cd software-blog/
$ npx frontity dev

表示されるブログはTwenty Sixteenというテーマを用いたこちらのWordPressサイトのデータに基づくものです。見た目は同じではありません。

https://test.frontity.org に基づくサイト

プロジェクトの設定

これを自分のWordPressサイトに基づくために、frontity.settings.js を次のように編集しました。なおこの設定ファイルの編集方法の詳細はこちらにあります。

const settings = {
  "name": "software-blog",
  "state": {
    "frontity": {
      "url": "https://software.pitang1965.com/", <--- ★とりあえず変更
      "title": "定年後にWeb開発者目指す", <--- ★変更
      "description": "2019年1月から独学中の50代。" <--- ★変更
    }
  },
  "packages": [
    {
      "name": "@frontity/twentytwenty-theme",
      "state": {
        "theme": {
          "menu": [
            [
              "Home",
              "/"
            ], <--- ★Home以下は削除
          ],
          "featured": {
            "showOnList": false,
            "showOnPost": false
          }
        }
      }
    },
    {
      "name": "@frontity/wp-source",
      "state": {
        "source": {
          "url": "https://software.pitang1965.com/" <--- ★WordPressサイトを変更
        }
      }
    },
    "@frontity/tiny-router",
    "@frontity/html2react"
  ]
};

export default settings;

上図のサイトのバーガーメニューには、Homeの他にNature, Travel, Japan, About Usなどの項目がありますが、Home以外は一旦削除した状態です。そこから、自分のWordPressサイトに合わせて、”menu”を次に変更しました。

:
          "menu": [
            [
              "Home",
              "/"
            ],
            [
              "格安教材",
              "/skill-set"
            ],
            [
              "自己紹介",
              "/self-introduction"
            ],
          ],
:

あと、favicon.ico を変更しました。

デプロイ

Vercle, Layer0, Heroku にデプロイする方法がドキュメントに載っていますが、今回は使ったことがないLayer0にします。

ビルド

まずは、以下のコマンド等でビルドします。

$ npx frontity build

このコマンドでbuildフォルダに(変換された)Reactアプリとserver.jsFrontityNode.jsサーバー)が生成されます。

Layer0 CLIのインストール

CLIをインストールします。

$ npm i -g @layer0/cli

参考)私のWindows環境で、インストールやアンインストールがうまくいかなくなってしまったため、上記コマンドに --force を付けて最終的に実行しました。

プロジェクト設定

Frontityプロジェクトでlayer0を使うためのコマンドを実行します。

$ layer0 init

このコマンドでパッケージがdevDependenciesでいくつか追加され、package.jsonlayer0用のスクリプトが追加されます。また、sw\service-worker.jslayer0.config.jsroutes.jsも追加されます。

Layer0での実行状況のシミュレート

以下のコマンドでLayer0でのアプリの実行をシミュレートできます。

$ layer0 dev

代わりに以下のコマンドを実行することにより、エッジキャッシュの振る舞いをエミュレートできるそうです。

$ layer0 dev --cache

Layer0のアカウント作成

Layer0にデプロイするためにはこちらからサインアップしておく必要があります。サイト名の入力が求められますが、これは無視します。

デプロイの実行

以下のコマンドを実行します。ログインでは認証のためにブラウザで1クリックします。

$ layer0 login
$ layer0 deploy

これでデプロイが完了しました。URLはちょっと長くていけていませんが。

https://pitang1965-software-blog-default.layer0-limelight.link

はまったポイント

エックスサーバーの[WordPressセキュリティ設定]の[REST API アクセス制限]をオンにしていたため、開発環境でのLayer0用のエミュレーションで問題がないのに、Layer0にデプロイすると403エラーになった。

]]>
https://software.pitang1965.com/2022/05/15/frontity-getting-started/feed/ 0
改行の入ったテキストをきちんと改行させる方法 https://software.pitang1965.com/2022/05/13/how-to-properly-break-text-with-line-breaks/ https://software.pitang1965.com/2022/05/13/how-to-properly-break-text-with-line-breaks/#respond Fri, 13 May 2022 13:16:37 +0000 https://software.pitang1965.com/?p=4070 概要

次のように曜日毎に改行を入れて編集したテキストがあったとします。

改行を入れたテキストデータ

これをWebページで表示したら次のように改行が無視された状態になってしまいました。

改行が無視された

これを次のように表示するようにするための方法のメモです。

改行が聴いたうえで、はみ出さないように折り返している

方法

改行を効くようにする

もともと改行が無視されてしまったテキスト全体を<a>タグで囲っていたのですが、これを<pre>タグに変更しました。ただし、このままだと、上図の5/20のデータが折り返さずに切れてしまいました。

長過ぎるテキストを折り返すようにする

こちらは以下のCSSを設定しました。

white-space: pre-wrap;
]]>
https://software.pitang1965.com/2022/05/13/how-to-properly-break-text-with-line-breaks/feed/ 0
Vite (React, TypeScript)プロジェクトをPWA化 https://software.pitang1965.com/2022/04/23/how-to-make-a-vite-react-typescript-project-a-pwa/ https://software.pitang1965.com/2022/04/23/how-to-make-a-vite-react-typescript-project-a-pwa/#respond Sat, 23 Apr 2022 03:31:23 +0000 https://software.pitang1965.com/?p=4031 yarn create vite my-app --template react-ts で作ったプロジェクトをPWA化するための簡単なメモです。ここでのPWA化とはインストール可能とすることを目的としています。

PWA

方法

Vite Plugin PWAを使いました。

iOSSafari限定で「ホーム画面に追加」からおこないます。

詳細

パッケージのインストール

yarn add vite-plugin-pwa -D

public/robots.txtの追加

robots.txt は、検索エンジンのクロール(サイトを巡回し、ページの内容を収集・保存する処理)を制御するためのファイルだそうです。例えば私のGatsbyのブログのそれは https://blog.pitang1965.com/robots.txt のようにサイト名に/robots.txtを追加したURLで確認できます。

今回は次としました。

User-agent: *
Allow: /

アイコンの作成

以下のサイズの画像を用意して、public フォルダに配置します。

  • 180×180 // ファイル名の例:apple-touch-icon.png
  • 192×192 // ファイル名の例:icon-192×192.png
  • 256×256 // ファイル名の例:icon-256×256.png
  • 384×384 // ファイル名の例:icon-384×384.png
  • 512×512 // ファイル名の例:icon-512×512.png
  • favicon.ico

これをおこなうのに PWA Manifest Generator が便利でした。

具体的には、

  • 既に作成済のロゴのsvgファイルからInkscapeにて512×512サイズのlogo.pngを作り、それをPWA Manifest Generatorに次のように指定しました。manifest.zipが生成されるのでそれを伸張して使います。
PWA Manifest Generator
  • apple-touch-icon.png は作成済のロゴのsvgファイルからInkscapeにて180×180サイズで作ります。
  • 作成済のロゴのsvgファイルをfabicon.svgとします。
  • pngから Convertio にて favicon.icoに変換。

vite.config.tsの編集

以下のmanifestの部分は、PWA Manifest Generatorが生成した manifiest.webmanifest にある内容を元にしていますが、purpose: 'any maskable' のところを追加していることに注意します。

import { VitePWA } from 'vite-plugin-pwa';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    VitePWA({
      includeAssets: [
        'offline.html',
        'favicon.svg',
        'favicon.ico',
        'robots.txt',
        'apple-touch-icon.png',
      ],
      manifest: {
        theme_color: '#ffffff',
        background_color: '#4a90e2',
        display: 'standalone',
        scope: '/',
        start_url: '/',
        short_name: '\u305f\u3066\u30c4\u30a4\u30fc\u30c8',
        description:
          '\u7e26\u66f8\u304d\u30c4\u30a4\u30fc\u30c8\u3092\u3059\u308b\u305f\u3081\u306e\u30c4\u30fc\u30eb\u3002',
        name: '\u305f\u3066\u30c4\u30a4\u30fc\u30c8',
        icons: [
          {
            src: '/icon-192x192.png',
            sizes: '192x192',
            type: 'image/png',
          },
          {
            src: '/icon-256x256.png',
            sizes: '256x256',
            type: 'image/png',
          },
          {
            src: '/icon-384x384.png',
            sizes: '384x384',
            type: 'image/png',
          },
          {
            src: '/icon-512x512.png',
            sizes: '512x512',
            type: 'image/png',
          },
          {
            src: '/icon-512x512.png',
            sizes: '512x512',
            type: 'image/png',
            purpose: 'any maskable',
          },
        ],
      },
    }),
  ],
});

index.htmlの編集

OGPの設定は省略しますが、次のようにしてみました。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>たてツイート</title>
    <meta
      name="description"
      content="縦書きでツイートするためにテキストを変換します。"
    />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <link
      rel="alternate icon"
      href="/favicon.ico"
      type="image/png"
      sizes="16x16"
    />
    <link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180" />
    <link rel="mask-icon" href="/favicon.svg" color="#FFFFFF" />
    <meta name="theme-color" content="#ffffff" />


:


  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
    <!-- PWA -->
    <script>
      if ('serviceWorker' in navigator) {
        window.addEventListener('load', () => {
          navigator.serviceWorker
            .register('./serviceWorker.js')
            .then((reg) => console.log('サービスワーカーの登録成功', reg.scope))
            .catch((err) => console.log('サービスワーカーの登録失敗', err));
        });
      }
    </script>
  </body>
</html>

public/serviceWorke.js の追加

index.htmlscript タグで参照している serviceWorker.js を次の内容で public フォルダに配置しました。オフラインのときに表示する offline.html を指定しています。また、このファイルは vite.config.ts でも指定しています。

const CACHE_NAME = 'version-1';
const urlsToCache = ['index.html', 'offline.html'];

// Install SW
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
      console.log('Opened cache');
      return cache.addAll(urlsToCache);
    })
  );
});

// Listen for requests
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then(() => {
      return fetch(event.request).catch(() => caches.match('offline.html'));
    })
  );
});

// Activate the SW
self.addEventListener('activate', (event) => {
  const casheWhitelist = [];
  casheWhitelist.push(CACHE_NAME);

  event.waitUntil(
    caches.keys().then((casheNames) =>
      Promise.all(
        casheNames.map((casheName) => {
          if (!casheWhitelist.includes(casheName)) {
            return cashes.delete(casheName);
          }
        })
      )
    )
  );
});

public/offline.htmlの追加

オフラインでキャッシュにない場合は次のような画面を表示するためのHTMLを追加してみました。

オフライン時のフォールバック
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>たてツイート</title>
    <style type="text/css">
      body {
        display: flex;
        flex-direction: column;
        background: #00aff9;
        height: 100vh;
        margin: 0;
        color: white;
      }
      h1 {
        margin: 0.8em 3rem;
        font: 4em Roboto;
      }
      p {
        margin: 0.2em 3rem;
        font: 2em Roboto;
      }
    </style>
  </head>
  <body>
    <div>
      <h1>おっと!!!</h1>
      <p>このページはオフラインでは表示できません。</p>
      <p><a href="../index.html">ホームページに戻る </a></p>
    </div>
  </body>
</html>

]]>
https://software.pitang1965.com/2022/04/23/how-to-make-a-vite-react-typescript-project-a-pwa/feed/ 0
コードからツイートする方法 https://software.pitang1965.com/2022/04/22/how-to-tweet-from-the-code/ https://software.pitang1965.com/2022/04/22/how-to-tweet-from-the-code/#respond Fri, 22 Apr 2022 14:24:35 +0000 https://software.pitang1965.com/?p=4039 コードからツイートする方法のメモです。

ツイートといってもログインもせずに、単に次のようにツイートの編集画面を開く方法になります。つまり、これで省略できるのは以下の操作になります。

  1. テキストエリアからテキストをクリップボードへコピー
  2. Twitterを起動
  3. [ツイートする]ボタンをクリック
  4. ツイート編集画面にクリップボードからテキストを貼り付け
コードからツイート画面に遷移

方法

これは、Twitter公式のDevloper PlatformTweet buttonに説明がありました。

これの”How to add a Tweet button to your website”の1から4までの3を見ると次となっています。

<a class="twitter-share-button"
  href="https://twitter.com/intent/tweet?text=Hello%20world"
  data-size="large">
Tweet</a>

これで、”Hello world”というツイートが設定されたツイート編集画面が開きます。

そして、4で説明されている widgts.js を使うことによって、次のようなボタンも表示できました。

widgets.jsによるTweetボタン

しかし、この widgts.js を使う方法が難しかったです。詳細は省略しますが、WindowsやAndroidでは動作するのに、iOSやMacではうまく動作させることができませんでした。ここはあきらめて、次のようなコードでも見た目(と性能?)に妥協すれば問題がなかったです。

<a href='https://twitter.com/intent/tweet?text=Hello%20world'>Tweet</a>

最終的な実装

今回は、Mantineを利用しているのですが、最終的に次のコードとしました。

つまり、上のコードの見た目だけ整えた形です(本記事の冒頭の画像参照)。

import { Button} from '@mantine/core';

:
:

<Button
  component='a'
  target='_blank'
  rel='noopener noreferrer'
  href={`https://twitter.com/intent/tweet?text=${encodeURIComponent(
    tateTweet
  )}`}
  leftIcon={<BrandTwitter size={18} />}
  styles={(theme) => ({
    root: {
      backgroundColor: '#00acee',
      paddingRight: 20,

      '&:hover': {
        backgroundColor: theme.fn.darken('#00acee', 0.05),
      },
    },
    leftIcon: {
      marginRight: 10,
    },
  })}
>
  Twitterに飛ぶ
</Button>

スタイリングのコードは無視すると、ポイントは次です。

href={`https://twitter.com/intent/tweet?text=${encodeURIComponent(
  tateTweet
)}`}

tateTweet にツイートの文字列が格納されていて、それをencodeURIComponentにてURIエスケープしています。

]]>
https://software.pitang1965.com/2022/04/22/how-to-tweet-from-the-code/feed/ 0
Vercelで手動でデプロイをトリガーする方法 https://software.pitang1965.com/2022/04/07/how-to-triger-deploy-on-vercel/ https://software.pitang1965.com/2022/04/07/how-to-triger-deploy-on-vercel/#respond Thu, 07 Apr 2022 11:17:57 +0000 https://software.pitang1965.com/?p=4019 概要

Airtableの少量のデータを元にVercel上に構築されているNext.jsによるWebアプリに対し、非開発者によりAirtableのデータを更新し、それをデプロイされたWebアプリに反映してもらうため、Deploy Hooksデプロイフック)を使う方法を試しました。

  • 非開発者が使うパソコンはWindowsを想定しています。
  • ブログのように記事が追加されていくようなサイトではないため、ISR(Incremental Static Regeneration)は今回採用しないことにしました。

デプロイフックは、デプロイのトリガーやビルドステップの再実行のためにHTTP POSTリクエストを受け付けるURLです。今回はBATファイルからCurlコマンドを実行して呼び出します。

デプロイフックの作成

Gitに接続されたVercelのプロジェクトのSettingsGitDeploy Hooksにて、適当なデプロイフックの名称(例:”My Hook”)及びブランチ名”main”)を入力し、[Create Hook]ボタンをクリックしておこないます。

Deply Hooks
すると、https://api.vercel.com/v1/integrations/deploy/prj_*************************************** といった調子のURLが生成されます。

デプロイフックの呼び出し

ターミナルで次のように呼ぶだけです。

curl -X POST https://api.vercel.com/v1/integrations/deploy/prj_***************************************

Windowsでは、これを、例えばbuild.bat のような拡張子.batを持つファイルに書いておいて、ファイルをダブルクリックすることにより実行することができます。

]]>
https://software.pitang1965.com/2022/04/07/how-to-triger-deploy-on-vercel/feed/ 0