デスクトップ Ubuntu 20.04 LTS が不安定なのでやったこと

私の環境では 16.04 LTS の頃から不安定だった Ubuntu 開発環境 #5 が 20.04 LTS へのアップグレード以降、コーディング中にフリーズしたり、突然リブートしたり、あげくにはGUIファイルマネージャ(Nautilus)が繰り返しクラッシュするようになりました。

ubuntu@os0101-Ontario:~$ uname -srvmpio
Linux 5.4.0-65-generic #73-Ubuntu SMP 
Mon Jan 18 17:25:17 UTC 2021 
x86_64 x86_64 x86_64 GNU/Linux

ファイルマネージャを起動して Home からディレクトリを移動しているとクラッシュしてウィンドウが消える。

darktable を開くと警告文が表示される。そして Visual Studio Code でデバッガを動かしていると、何の前触れもなく画面がフリーズして、キーボード入力もマウス入力も受け付けなくなります。

なにが Raising Skinny Elephants だ、一度も役に立ったことねえぞ?

と言えるぐらい Linux と AMD Ryzen の組み合わせは、わりと頻繁に問題を起こします

[toc]

CPU

$ lscpu
Architecture:                    x86_64
CPU op-mode(s):                  32-bit, 64-bit
Byte Order:                      Little Endian
Address sizes:                   43 bits physical, 48 bits virtual
CPU(s):                          16
On-line CPU(s) list:             0-15
Thread(s) per core:              2
Core(s) per socket:              8
Socket(s):                       1
NUMA node(s):                    1
Vendor ID:                       AuthenticAMD
CPU family:                      23
Model:                           1
Model name:                      AMD Ryzen 7 1800X Eight-Core Processor
Stepping:                        1
Frequency boost:                 enabled
CPU MHz:                         1845.354
CPU max MHz:                     3600.0000
CPU min MHz:                     2200.0000
BogoMIPS:                        7185.80
Virtualization:                  AMD-V
L1d cache:                       256 KiB
L1i cache:                       512 KiB
L2 cache:                        4 MiB
L3 cache:                        16 MiB

Continue reading “デスクトップ Ubuntu 20.04 LTS が不安定なのでやったこと”

Possible causes for errors in packaging an Electron App

While trying to build and package your Electron application, you may occasionally encounter file load errors. Your application works perfectly in development but the distribution returns nothing more than a blank white page.

You may get error messages such as Unable to load preload script: … resources/app.asar/preload.js, Not allowed to load local resource: file://src/index.html or even Application entry file “dist/main.js” in the linux-unpacked/resources/app.asar” does not exist. Seems like a wrong configuration.

All of the above-mentioned error messages stem from file path problems. Your packaged Electron application requires absolute paths to the HTML file, modules and extra resources. And the paths in the distribution package are not always the same as those in the development.

There are a NodeJS variable and Electron functions to avoid this problem. In whichever file (or on whichever operating system) you invoke your NodeJS process, __dirname always returns the absolute path of where you start it. Electron app API allows you to get and set paths to your application resources.

Instead of using the relative path that can cause an error in production, you can set up the paths using __dirname in the main process.

const path = require('path');
const glob = require('glob');
const { app, BrowserWindow } = require('electron');

let mainWindow:any = null;

function initialize ():void {
  makeSingleInstance();

  function createWindow () {
    const windowOptions = {
      width: 1080,
      minWidth: 680,
      height: 840,
      title: app.getName(),
      webPreferences: {
        nodeIntegration: false
      }
    }

    mainWindow.loadURL(path.join('file://', __dirname, '/index.html'));
}

If your application won’t load the HTML file using __dirname, your problem presumably won’t be related to Electron.

When bundled by Webpack, the variable __dirname doesn’t automatically show the path to build resources but to your project root, or a single forward slash ‘/’. This may be the cause of your trouble. In this case, you just need to open your webpack config and set false to node: {__dirname: }.

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {

  ...
  context: __dirname,
  node: {
    __dirname: false
  },

}

Then __dirname will return the path to the current application directory. Neither setting “asar”: false nor specifying “devEngines” is required. app.getPath(name) works in the same manner. This function is really useful for saving application settings and user data. Quite apart from userData, where your app’s configuration files are stored, it returns the absolute paths to User’s home, Desktop, Downloads and Documents as well.

All the Electron Docs! | Electron

For your reference, here is my version information.

$ node --version
v12.16.3

$ yarn --version
1.22.5

$ npm --version
6.14.8

$ tsc --version
Version 2.9.2

$ webpack --version
4.44.1

$ grep electron package.json 
    "electron-debug": "^3.1.0",
    "electron-devtools-installer": "^3.1.1",
    "electron-log": "^4.2.4",
    "electron-store": "^6.0.0",
    "electron-updater": "^4.3.5",
    "electron": "^10.1.3",
    "electron-builder": "^22.8.1",

$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.5 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

React コンポーネントに history がないときに確認すること

ReactJS を使ってシングルページアプリケーション(SPA)を作成する際、コンポーネント内に props.history が見当たらないことがあります。

$ tsc

src/components/User/Upsert.tsx:53:16 - 
error TS2339: Property 'history' does not exist on type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>'.

53     this.props.history.push('/user/list');
                  ~~~~~~~
プロパティ 'history' は型 'Readonly<{}> & Readonly<{ children?: ReactNode; }>' に存在しません。

例えば CRUD (DBMS) 操作を行った直後にリダイレクトを行う際などに、このエラーが生じるとページ遷移も DOM の書き換えも行われません。

そこでエラー表示を少し調べてみると this.props.history が見当たらないことはありえないとか、withRouter を使ってリダイレクトする方法があるなど、いろいろな(自然)言語で好き勝手なことが書かれていることが分かります。

しかし、このエラー表示が生じた環境において TypeScript をお使いの場合、コンポーネント、つまり props や state の各変数の型定義が行われていないことを最初に疑った方が良いかも知れません。

つまり interface にてコンポーネント内の変数の型を自身で定義して React.Component <{},{}> に渡すと問題が解決する場合があります。

以下に具体例を提示します。

interface IProps {
  history:string[],
}

interface IState {
  params:Array<object>,
}

class Upsert extends React.Component<IProps,IState> {
  constructor(props){
    super(props);
    this.state ={
      params:[],
    }
  }

}
export default Upsert;

少し考えてみると自明なことなのですが、ドキュメントを読み返してみても原因らしきものが思い当たらなくて困惑しました。最終的に解決に役立ったのはこちらです。


TypeScript and React – Hello React and TypeScript
https://charles-bryant.gitbook.io/hello-react-and-typescript/typescriptandreact


実行環境は下記のとおりになります。

$ tsc --version
Version 2.9.2

$ node --version
v12.16.3

$ npm --version
6.14.8

$ grep react package.json 
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-router-dom": "^5.2.0",
    "react-scripts": "^3.4.1",
    "react-select": "^3.1.0",
    "@types/react": "^16.9.49",
    "@types/react-dom": "^16.9.8",
    "@types/react-router": "^5.1.8",
    "eslint-plugin-react": "^7.21.1",
    "react-devtools": "^4.8.2",

この分野は変化が激しく、毎年のように仕様が変わるので解決法をお探しのかたは記事の書かれた時期とバージョンに細心の注意を払ってください。

最後に繰り返しになりますが、私はスクリプト言語もフロントエンドも心の底から嫌いです。嫌いなので仕事では絶対に触りたくありません。