React

[Electron] ファイルオープンダイアログとファイル読み込みに保存ボタンを追加して、ファイル保存ダイアログの表示とファイル保存処理を追加した。

まるっと、新しいソースもアップしておく。

保存ボタンを押した時の処理をあげておく。

        // ファイル保存ダイアログを表示する
        dialog.showSaveDialog(remote.getCurrentWindow(), {
            filters:[
                { name: "Text File", extensions:["txt"]},
                { name: "All Files", extensions: ["*"]}
            ]}, filename=>{
                if(filename) {
                    // ファイルに保存
                    fs.writeFile(filename, this.state.text, err=>{
                        if(err) {
                            alert(err);
                        }
                    });
                }
            });

dialog.showSaveDialogでファイル保存ダイアログを表示する。

第1引数は、親ウインドウでremote.getCurrentWindow()でレンダラープロセスで表示しているページのウインドウが取得できる。

第2引数は、ダイアログのオプションを指定する。
よく使いそうなのをピックアップして書いとく。詳細はドキュメントを見よ!

  • filters:表示するや選択できるファイルの種類を配列で指定する。
filters:[
    { name: "Text File", extensions:["txt"]},
    { name: "All Files", extensions: ["*"]}
],

第3引数は、コールバック関数。
入力したファイル名(フルパス)が渡される関数を指定する。
上に載せたソースでは、Node.jsのfs.writeFileを使ってTextAreaの内容を保存している。


まるっと、ソースをアップしておく。

ここにアップしたソースから、レンダラープロセスの頭の方に追加するのと、開くボタンをクリックした時の処理をあげとく。

import {remote} from "electron";
import * as fs from "fs";


const dialog = remote.dialog;
// ファイルオープンダイアログを表示する
dialog.showOpenDialog(remote.getCurrentWindow(), {
    filters:[
        { name: "Text File", extensions:["txt"]},
        { name: "All Files", extensions: ["*"]}
    ],
    properties: ["openFile"]
}, filePaths=>{
    if(filePaths.length != 0) {
        // ファイル読み込み
        fs.readFile(filePaths[0], { encoding:"utf-8"}, (err, data)=>{
            if(err) {
                alert(err);
            } else {
                this.setState({text:data});
            }
        });
    }
});

まず、import部分の説明。

dialogはメインプロセスでしか使えないのでremoteをインポートしてる。Electronでは、Node.jsのAPIが使用できるので、ファイルを読み込むためにfsをインポートしている。

クリックした時の処理。

dialog.showOpenDialogでファイルオープンダイアログを表示する。

第1引数は、親ウインドウを指定する。remote.getCurrentWindow()でレンダラープロセスで表示しているページのウインドウが取得できる。

第2引数は、ダイアログのオプションを指定する。
よく使いそうなのをピックアップして書いとく。詳細はドキュメントを見ればいいじゃんw

  • defaultPath:デフォルトのディレクトリ
  • filters:表示するや選択できるファイルの種類を配列で指定する。
filters:[
    { name: "Text File", extensions:["txt"]},
    { name: "All Files", extensions: ["*"]}
],
  • proprties:配列で使用する機能を指定する。
    • openFile:ファイル選択を可能にする。
    • openDirectory:ディレクトリ選択を可能にする。
      macOSの場合、openFile、openDirectoryの両方を指定すると、ファイルまたはディレクトリを選択できる。Windows、Linuxの場合はディレクトリのみ選択できる。
    • multiSelections:複数選択を可能にする。

第3引数は、コールバック関数。
選択したファイル名(フルパス)の配列が渡される関数を指定する。
上に載せたソースでは、Node.jsのfs.readFileを使って読み込んで最終的にTextAreaに設定している。(TextAreaに設定するあたりはRectを使っている)


パッケージングを行う。パッケージングを行うツールは、何種類かあるみたいだけど、electron-packagerを使うことにする。

[Electron] Hello World的なもの(2) index.htmlの置き場所を変える。からダウンロードできるソースに対して行っていく。

プロジェクトのフォルダでelectron-packagerをインストールする。

npm install electron-packager -D
npm run build:prod

でビルド後、

npx electron-packager dist --overwrite

って、やると実行したOS用のパッケージングが行われる。distはビルド後作成されるフォルダで、その中のファイルをパッケージングする。

32bitのWindows上で実行すると、webpack-electron-win32-ia32フォルダに作成される。このフォルダ名とexeのファイル名のwebpack-electronは、distフォルダにあるpackage.jsonのnameに書いてあるものが使用されている。

macOS用は、

npx electron-packager dist --platform=darwin --arch=x64 --overwrite
で、

64bitのWindows用は、

npx electron-packager dist --platform=win32 --arch=x64 --overwrite

で、x64のLinux用は、

npx electron-packager dist --platform=linux --arch=x64 --overwrite

で作れる。

ただし、Windows上で作ったmacOSのファイルたちをmacOSに持って行っても動かなかったんだよねー。詳しくは調べていないんでなんで動かないのかはわからん。実行権とかなんかの問題なんかな?

Linux、macOS上でWindows用のパッケージングを行うには、Wineをインストールする必要があるようだ。(試してない)

package.jsonのscriptsに

    "package": "electron-packager dist --overwrite"

を追加しておくと、

npm run package

で、パッケージングできる。

変更したソースをダウンロードできるようにしといた。





(更新!!)
webpack4にあわせて変更。

-------

最初、webpackを使わずに試してみようと思ったが面倒くさくなってきたので、最新版で学ぶwebpack 4入門を参考にビルド環境を用意した。
こっちにもざっくりと準備することを書いておく。

npm init -y

でpackage.jsonを用意する。

npm install webpack webpack-cli -D

でモジュールのインストールする。

package.jsonのscriptsのところを

  "scripts": {
    "build": "webpack --mode development",
    "build:prod": "webpack --mode production"
  },

に変更する。

これで

npm run build

とすると、とりあえずsrc/index.jsとindex.js内でimportしているモジュールをまとめてdist/main.jsを作ってくれる。

webpackのオプションに--mode developmentを指定すると、開発用のソースマップ有効のjsファイルが作られて、--mode productionで公開用の圧縮(?)されたjsが作られる。

次にtypescriptを使えるようにする。
まずは、モジュールのインストール。

npm install typescript ts-loader -D
tsc --init

でtsconfig.jsonを作る。

tsconfig.jsonのcompilerOptionに次のオプションを変更or追加する。

    "sourceMap": true,
    "target": "es5",
    "module": "es2015"

webpackの設定ファイル(webpack.config.js)を用意する。

module.exports = {   
    entry: "./src/index.ts",

    output: {
        path:`${__dirname}/dist`,
        filename: "main.js"
    },
   
    module: {
      rules: [
        {
          // 拡張子 .ts の場合
          test: /\.ts$/,
          // TypeScript をコンパイルする
          use: "ts-loader"
        }
      ]
    },
    // import 文で .ts ファイルを解決するため
    resolve: {
      extensions: [
        ".ts"
      ]
    }
};

src/index.tsとindex.ts内でimportしているモジュールをjsにコンパイルしたて、まとめてdist/main.jsを作ってくれる。

次にReactを使えるようにする。
Reactのモジュールをインストール。

npm install react react-dom @types/react @types/react-dom -S

tsconfig.jsonに次の項目を追加or変更する。

    "jsx": "react",
    "moduleResolution": "node",
    "lib": [
      "es2017",
      "dom"
    ]

ReactのサイトにあるHello Worldみたいなもののindex.htmlとsrc/index.tsxを用意する。

index.html

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div id="root"></div>
    <script src="dist/app.js"></script>
</body>
</html>

src/index.tsx

import * as React from 'react';
import * as ReactDOM from 'react-dom';

ReactDOM.render(
    <h1>Hello world!</h1>,
    document.getElementById('root')
);

webpackの設定ファイル(webpack.config.js)を変更する。まるっと、上げておく。

module.exports = {   
    entry: "./src/index.tsx",

    output: {
        path:`${__dirname}/dist`,
        filename: "app.js"
    },
   
    module: {
      rules: [
        {
          // 拡張子 .tsもしくは.tsx の場合
          test: /\.tsx?$/,
          // TypeScript をコンパイルする
          use: "ts-loader"
        }
      ]
    },
    // import 文で .ts ファイルを解決するため
    resolve: {
      extensions: [
        ".ts", ".tsx", ".js", ".json"
      ]
    }
};
npm run build

でビルド、index.htmlをブラウザで開けば、Hello world!って表示される。

ソースをダウンロードできるようにしといた。

(追記 2018/3/22)
package.jsonのscriptsにbuild:prodを追加した。




[Electron] Hello World的なもの(1)を少し変更する。

index.htmlをsrcフォルダに移動して、ビルドするとdistにコピーされるようにしたい。つまり、srcフォルダにすべてのソース、ビルドで生成されるファイル+実行に必要なファイルをdistに用意されるようになる。と、すると実行用のpackage.jsonも別途srcフォルダに用意しといた方がいいような気がするのでそれも行う。

webpackでビルド時にファイルをコピーする方法はいろいろあるようなんだけど、copy-webpack-pluginを使うことにする。

copy-webpack-pluginをインストールする。プロジェクトフォルダで

npm install copy-webpack-plugin -D

を実行する。

webpack.config.jsの頭のほうに、

const copyWebpackPlugin = require('copy-webpack-plugin');

を追加して、レンダラープロセスの設定に

    plugins: [
      new copyWebpackPlugin([
        { from: "./src/*.html", to:"[name].[ext]" },
        { from: "./src/package.json" },
      ])
    ]  

を追加する。

index.htmlをsrcフォルダに移動する。
index.htmlでdist/app.jsと指定しているところをapp.jsに変更する。
src/main/main/tsのloadURLで読み込んでいるindex.htmlの場所を変更する。

package.jsonのscriptsのstartを

    "start": "electron ./dist/"

起動用のsrc/package.jsonを用意する。

{
    "name": "webpack-electron",
    "version": "1.0.0",
    "main": "./main.js"
}

こんな感じかな?

変更したソースをダウンロードできるようにしといた。





↑このページのトップヘ