Code for final

ふぁいなる向けのコード置き場です。すでにコードじゃないこともいっぱい。

Electron + Vue 3 + TypeScript + Element Plusで出たVSCodeの謎のエラーを解消する方法

作りたいアプリが思いついたのでvscodeで久々にElectronの環境を構築してみました。
いまはもうElectronはバージョン22で、Vue.js 3.0で、Vue CLIを使った構築も非推奨になってるんですね。。
とはいえ慣れた環境がしっくりくるのでVue CLIで構築しました。
memoを残しといてよかった。

以下の方法で2023年現在でも構築できました。

final.hateblo.jp

ただし、Node.jsは現時点の推奨版の18.xだとElectron Builderは以下のv3 alpha版を使わないと動かなかったです。

github.com

UIフレームワークはVue3に対応したシンプルなElement Plusを使用することにしました。

element-plus.org

ちなみにVue CLIプラグインにElement Plusのやつがありましたが、メンテされておらず動かなかったので、普通に公式の手順通りnpmでいれました。

で、環境構築できたものの、謎のエラーに苛まれました。
以下のようにelタグのところでエラーになるんです。

Argument of type '{ [x: string]: any; }' is not assignable to parameter of type 'App<any> & Partial<{ readonly type: EpPropMergeType<StringConstructor, "" | "default" | "text" | "success" | "warning" | "info" | "primary" | "danger", unknown>; ... 12 more ...; readonly autofocus: boolean; }> & Omit<...>'.
  Type '{ [x: string]: any; }' is missing the following properties from type 'App<any>': version, config, use, mixin, and 11 more.

これはtypescriptのエラーで実際動かす分には問題ないですが、コード書いているときに気になって集中できません。

で、いろいろ調べたのですが、なかなかわからなくてChatGPTにも聞きましたが、ググれと言われました。

最終的に調べまくってtsconfig.jsonが原因とわかりました。
以下のところの"element-plus/global"を削除すると解決しました!

{
  "compilerOptions": {
    "types": ["webpack-env", "element-plus/global"],

"element-plus/global"のTypeScriptの定義ファイルはあったのでなにが問題かいまだによくわかってないですが、解決してスッキリです。

Node.jsの自作ライブラリをTypeScriptでつくってnpmに公開して、アプリから参照するやりかた

Electronでアプリ開発していると共通ライブラリが作りたくなったので、
Node.jsのライブラリをTypeScriptでつくってnpmに公開するやり方をまとめます。
実際に"Firx"というライブラリを作成して公開するまでの手順なので適宜読み替えてください。

パッケージ名を決定

パッケージ名を決めます。なんでもいいですが、すでに公開されているものは使用できないのでnpmで確認してください。

www.npmjs.com

フォルダを作成

場所はどこでもOKなので、フォルダを作成します。パッケージ名がいいと思います。

typescriptをインストール

上記で作成したフォルダをvscodeで開き、ターミナルを開いて以下のコマンドを入力。

> npm install typescript

tsc --initを実行

以下のコマンドを実行して、tsconfig.jsonを作成します。
パスを通す方法がありますが、今回しか使わないのでこれで十分です。

> .\node_modules\.bin\tsc --init

npm initを実行

package.jsonを作成します。
以下のコマンドを実行して質問に答えていくとできます。あとから編集できます。

> npm init

package.jsonを編集

package.jsonを編集します。以下を参考にする。

{
  "name": "firx",
  "version": "0.0.1",
  "description": "Electron Application Develop Support Libraries",
  "main": "index.js",
  "types": "index.d.ts", // 追加:型定義のルート
  "dependencies": {
     "electron-store": "^5.1.1" // 追加:依存するライブラリがあれば記述する
  },
  "devDependencies": {
    "typescript": "~3.9.3" // 変更:typescriptのバージョンをアプリに合わせる
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "tsc", // 追加:buildでtypescriptをコンパイル
    "prepublishOnly": "npm run build" // 追加:publish前にビルドする
  },
  "author": "FINALSTREAM",
  "license": "MIT"
}

tsconfig.jsonを編集

tsconfig.jsonを編集します。以下を参考にする。

{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */

    /* Basic Options */
    // "incremental": true,                   /* Enable incremental compilation */
    "target": "es5",  // 変更:バージョンをアプリに合わせる       /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "commonjs",     
    ...
    "declaration": true,  // 変更:コメントをはずす。型定義を生成するオプション                   /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    // "sourceMap": true,  // 変更:コメントをはずす。デバッグ用のmapファイルを生成するオプション       /* Generates corresponding '.map' file. */,
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    "outDir": "./"  // 変更:コメントをはずす。コンパイルしたファイルの出力先 /* Redirect output structure to the directory. */,
   ...
   },
  "include": ["src/**/*.ts"],  // 追加:コンパイル対象のファイル 。srcフォルダの*.tsファイルを対象
  "exclude": ["src/**/*.spec.ts"]  // 追加:コンパイル対象外のファイル。テストコード(*.spec.ts)は含めない

npmignoreを作成

npmで公開するファイルで除外するものを記述します。
ソースやコンパイル定義は公開しないようにする。

tsconfig.json
src

ソースファイルを追加

srcフォルダを作成し、クラスのtsファイルを作成します。

src/AppStore.ts

import Store from "electron-store";

export default class AppStore {
  private static _store = new Store();

  public static get instance(): Store {
    return this._store;
  }
}

srcフォルダにindex.tsを作成

モジュールを公開するためのルートスクリプトを作成します。
クラスが複数ある場合は同じように複数行記述します。

src/index.ts

export * from "./AppStore";

npmでアカウントを作成

npmで公開するためにアカウントを作成します。

www.npmjs.com

npmにログイン

npm publishを実行する前にログインをするため、以下のコマンドを実行します。
ユーザ名とパスワードを聞かれるので入力します。

> npm adduser

最後に以下のような表示がされればログイン成功です。

Logged in as finalstream on https://registry.npmjs.org/.

ちなみにログインせずにnpm publishを実行すると以下のようなエラーがでます。

npm ERR! code E404
npm ERR! 404 Not Found - PUT https://registry.npmjs.org/firx - Not found
npm ERR! 404
npm ERR! 404  'firx@0.0.1' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\final\AppData\Roaming\npm-cache\_logs\2020-09-22T01_23_58_048Z-debug.log

npm publishを実行

npmに公開するため、以下のコマンドを実行します。
公開前にビルドが行われます。
一度publishしたら、同じバージョンではpublishできないので注意。

> npm publish

以下のように表示されれば成功です。

npm notice 
npm notice package: firx@0.0.9
npm notice === Tarball Contents ===
npm notice 706B AppStore.js
npm notice 759B index.js
npm notice 905B IpcResponse.js
npm notice 393B MessageLevel.js
npm notice 484B package.json
npm notice 288B AppStore.js.map
npm notice 148B index.js.map
npm notice 752B IpcResponse.js.map
npm notice 247B MessageLevel.js.map
npm notice 78B  README.md
npm notice 136B AppStore.d.ts
npm notice 94B  index.d.ts
npm notice 235B IpcResponse.d.ts
npm notice 112B MessageLevel.d.ts
npm notice === Tarball Details ===
npm notice name:          firx
npm notice version:       0.0.9
npm notice package size:  2.3 kB
npm notice unpacked size: 5.3 kB
npm notice shasum:        428062e0c8c521fdc210e3814c9b451a746922b2
npm notice integrity:     sha512-D7GBce7iKV3uE[...]YLiCLLnyBjNew==
npm notice total files:   14
npm notice
+ firx@0.0.9

npmで公開されていることを確認

以下のようにパッケージ名をurlに入れてアクセスすると公開されていることが確認できます。

https://www.npmjs.com/package/[パッケージ名]

成功していると以下のような感じ表示されます。

www.npmjs.com

アプリから使用

アプリの開発フォルダをvscodeで開いて、以下のコマンドをターミナルで実行します。
パッケージ名は作成したものを指定します。

> npm install firx

以下のようにインポートすると使用できます。
ポイントは"パッケージ名/クラス名"というように指定するところです。

import AppStore from "firx/AppStore";

最後に

TypeScriptだと型定義を自分で作らないといけないかなと思っていましたが、ソースから自動生成されるので心配無用でした。
いまのところ、このやり方でできていますが、開発を進めていったときにうまくいかないことが出たらまた追記したいと思います。

今回つくったライブラリはGitHubで公開していますので、うまく動かないときは参考にしていただければと思います。

github.com

GitHub Actionsを使ってElectron with Vue.jsアプリのWindows/MacOS/Linux向けパッケージを同時に自動リリースするやりかた

Electronアプリを作ってGitHub Actionsを使って自動でビルドしてリリースしたいと思って調べてできたやり方をまとめます。
C#アプリではAppVeyorでやっていましたが、あの頃はGitHub Actionsなんてものはなかったので、今回はGitHub Actionsを使います。

final.hateblo.jp

GitHub Actionsとは

いわゆるCI/CD(継続的インテグレーション/継続的デリバリー)というやつで、Jenkinsみたいなやつです。
ブランチにコードがコミットされたタイミングで自動でビルドして、自動でリリースする仕組みを構築できます。
GitHub ActionsではWindowsMacOSLinux(Ubuntu)の3環境でビルドできます。

ワークフローを作成する

GitHubリポジトリを開くと"Actions"があると思うので、そこをたたいて"New workflow"を選択します。
次の画面でテンプレートを選べますが、残念ながらElectronのテンプレートはないのでスキップします。
スキップは"set up a workflow yourself "を選択します。

自動ビルド&リリースのコードを記述する

AppVeyorは自動リリースする際、設定画面でいろいろするべきことが多かったですが、 GitHub Actionsはコードだけで完結します。
コードはyamlで記述します。
コードもブラウザ上で編集できます。

アプリはVue CLIを使っている必要がありますが、以下のコードを貼り付けるだけです。

name: Build Release Electron

on: [push]

jobs:
  build:

    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        os: [windows-latest, macos-latest, ubuntu-latest]

    steps:
      - name: Set Context
        env:
          GH_TOKEN: ${{ secrets.GH_TOKEN }} 
          GITHUB_CONTEXT: ${{ toJson(github) }}
        run: echo "$GITHUB_CONTEXT"
      - uses: actions/checkout@v1
        with:
          fetch-depth: 1
      - name: Set Node.js Version
        uses: actions/setup-node@v1
        with:
          node-version: 14.x
      - name: Install Yarn
        run: |
          yarn install
      - name: Install Vue CLI
        run: |
          yarn global add @vue/cli
      - name: Build for Windows
        if: matrix.os == 'windows-latest'
        run: |
          yarn run electron:build --windows nsis zip --x64  --publish never
      - name: Build for MacOS
        if: matrix.os == 'macos-latest'
        run: |
          yarn run electron:build --macos dmg --x64  --publish never
      - name: Build for Linux
        if: matrix.os == 'ubuntu-latest'
        run: |
          yarn run electron:build --linux AppImage --x64  --publish never
      - name: Upload Artifacts for Windows Zip
        if: matrix.os == 'windows-latest'
        uses: actions/upload-artifact@v2
        with:
          name: ${{ github.event.repository.name }}-Zip Package
          path: dist_electron/*.zip
      - name: Upload Artifacts for Windows Installer
        if: matrix.os == 'windows-latest'
        uses: actions/upload-artifact@v2
        with:
          name: ${{ github.event.repository.name }}-Windows Installer
          path: dist_electron/*.exe
      - name: Upload Artifacts for MacOS
        if: matrix.os == 'macos-latest'
        uses: actions/upload-artifact@v2
        with:
          name: ${{ github.event.repository.name }}-Dmg Package
          path: dist_electron/*.dmg
      - name: Upload Artifacts for Linux
        if: matrix.os == 'ubuntu-latest'
        uses: actions/upload-artifact@v2
        with:
          name: ${{ github.event.repository.name }}-AppImage Package
          path: dist_electron/*.AppImage
      - name: Release
        uses: softprops/action-gh-release@v1
        if: startsWith(github.ref, 'refs/tags/')
        with:
          files: |
            dist_electron/*.zip
            dist_electron/*.exe
            dist_electron/*.dmg
            dist_electron/*.AppImage
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

※ 2021/07/24 electron13に更新した際に以下のエラーが出て動かなくなっていたので修正

InvalidConfigurationError: GitHub Personal Access Token is not set, neither programmatically, nor using env "GH_TOKEN"

ちなみにリポジトリ固有の情報はないのでそのままいけます。
nodeのバージョンのところはアプリに合わせて修正してください。

修正が終わったら右上の"Start commit"ボタンでコミットします。

ビルドをしてみる

ブランチにプッシュするだけで自動でビルドが始まります。
ビルド中は黄色でくるくる回ります。

f:id:finalstream:20200724124431p:plain

ビルドが完了したら緑のチェックマークになります。ビルドを選択するとビルドしたものをダウンロードできます。
ビルドしたものはArtifactsとして登録されています。

f:id:finalstream:20200724130747p:plain

左側にあるbuild(xxxx)を選択すると各プラットフォームごとのビルド結果の詳細を確認することもできます。
エラーが発生した場合はここを確認しましょう。
f:id:finalstream:20200724131030p:plain

リリースをしてみる

ブランチにプッシュしただけではリリースされません。
タグをうつとビルド後にリリースされます。
リリースされるとビルドしたものがAssetsとして登録されています。

f:id:finalstream:20200724131458p:plain

最後に

GitHub ActionはのGitHub機能なのでGitHubの連携設定とか不要で便利ですね。
またクロスプラットフォーム向けのビルドにも使えるので今後使っていきたいと思います。