2017年2月9日 星期四

electron 要用 async await 所需要的事

我現在用的是 “electron”: “^1.4.14”。沒辦法用 babel-preset-es2017。因為我用了 import {x} from “./y”,這句在 babel preset es2017 會直出,而 electron 不吃。

我會想用 preset 2017 是因為想要 asysnc await 句法,而 preset es2015 沒辦法翻。所以妥協的結果是,用 preset es2015 再加上 plugin

最後試成功的是這樣子的:

    "babel": "^6.5.2",
    "babel-core": "^6.21.0",
    "babel-loader": "^6.2.10",
    "babel-plugin-transform-runtime": "^6.22.0",
    "babel-preset-es2015": "^6.18.0",
    "babel-preset-es2017": "^6.22.0",
    "babel-preset-react": "^6.16.0",
    "babel-runtime": "^6.22.0",
    ```
雖然安裝了 `babel-preset-es2017`,但是在 webpack 設定還是用 `babel-preset-es2015`,在 loader 設定為:
    loaders: [
        {
            test: /\.js|\.jsx?$/,
            loader: 'babel-loader',
            include: [SRC_PATH],
            query: {
                presets: ['es2015', 'react'],
                plugins: ["syntax-async-functions","transform-regenerator","transform-runtime"]
            }
        },
        ...
    ]

“`

2017年2月8日 星期三

[nodejs] electron + drivelist + webpack 的小問題

為了要在 windows 系統列出磁碟機代號,用了 drivelist 這個套件,它是解譯系統指令的輸出來得到磁碟代號。

在沒有與 webpack 整合是沒問題,但是合在一起就出問題。

環境:electron, webpack, drivelist

第一個是解譯 json 的問題

當程式一引入 drivelist 就產生以下錯誤:

ERROR in ./~/drivelist/package.json
Module parse failed: C:\electron_project\electron\node_modules\drivel
ist\package.json Unexpected token (2:9)
You may need an appropriate loader to handle this file type.

因為它的 scripts.js 用到一句:

const debug = require('debug')(require('../package.json').name);

這個還好解決,首先是安裝 json-loader 使用指令 npm install --save-dev json-loader 然後在 webpack.config.jsloaders 裡加一個 { test: /\.json$/, loader: 'json-loader' } 這樣就解決了。不用改到程式。

第二個是執行路徑的問題

雖然解決了引入的問題,接下來要查詢的時候出現以下錯誤:

Uncaught Error: spawn \scripts\win32.bat ENOENT

原因是的 scripts.js 設定執行路徑是這樣做的:

const SCRIPTS_PATH = path.join(__dirname, '..', 'scripts');

在經過 webpack 打包之後, __dirname 在這裡已經變成根目錄 “/”,所以底下執行就找不到執行命令。另外,scripts 也沒有複製到目標目錄去。所以要改 webpack.config.jsscripts.js

webpack.config.jsplugins 底下的 CopyWebpackPlugin 裡面加一個 { from: path.resolve(node_modules_path, 'drivelist/scripts'), to: 'scripts' }

webpack.config.jsplugins 裡面加一個

new webpack.DefinePlugin({$dirname: '__dirname'})

這個 $dirname 就會是 main.js 執行的路徑,也就是原先 __dirname 的值。然後就要改 scripts.js 的程式碼,把 SCRIPTS_PATH 改成為:

const SCRIPTS_PATH = path.join($dirname, 'scripts')

改完之後,就可以由 electron 執行了。

註:這樣改法,node_modules 裡面的 drivelist 因為路徑關係,就沒辦法用命令列來執行了。

2017年1月18日 星期三

[electron]vscode debug

electron debug

因為 electron 本身有兩個行程, vscode 所以在 debug 的時候,在 main.js 這裡沒有問題,但是在 renderer.js 這裡就比較多問題。我搜尋了一下解法。

用 vscode 做 debug

我把原始教程 electron-quick-start 叫做 electron-quick-start-vanilla。要使用 vscode 對它做偵錯。

{
    // Use IntelliSense to learn about possible Node.js debug attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "啟動程式",
            "program": "${workspaceRoot}/main.js",
            "cwd": "${workspaceRoot}",
            "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd",
            "runtimeArgs": [
                ".",
                "--enable-logging"
            ],
            "env": {},
            "externalConsole": false,
            "sourceMaps": false,
            "outDir": null
        },
        {
            "type": "node",
            "request": "attach",
            "name": "附加至處理序",
            "port": 5858
        }
    ]
}

因為我是在 windows 環境所以才是 electron.cmd,如果是其他 os 就是 electron 即可。

這樣子的設定能做到:
1. 在 vscode 中,main.js 設中斷點可停下來,console.log 能寫到 vscode 的偵錯視窗,無法寫到 devTool 的偵點視窗。
2. renderer.js 設中斷點停不下來,console.log 能寫到 vscode 的偵錯視窗,也會寫到 devTool 的偵錯視窗。
3. 可以在 devTool 的 Source 視窗對 renderer.js 做中斷點偵錯。console.log 可寫到 devTool 的偵錯視窗。
4. 在 vscode 按下綠色三角之後,renderer.js 不在 Sources 頁籤裡,此時在程式主畫面要按 ctrl-r 重載程式,renderer.js 就會被載入 Sources 頁籤,就可以在 devTool 裡偵錯了。

小結:main.js 在 vscode 偵錯,renderer.js 在 devTool 偵錯。

參考

用 vscode 加 Debuger for Chrome 做 debug

要安裝 extension Debuger for Chrome, launch.js 改成如下:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Renderer Process",
      "type": "chrome",
      "request": "launch",
      //"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
      // Use the following for Windows
      "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd",
      "runtimeArgs": [
        "${workspaceRoot}/main.js",
        "--remote-debugging-port=9222"
      ],
      "webRoot": "${workspaceRoot}"
    }
  ]
}

這樣子的設定能做到:
1. 在 vscode 中,main.js 中斷點與 console.log 都無法寫到 vscode 的偵錯視窗裡。
2. 在 vscode 按下綠色三角之後,console.log 能寫到 vscode 的偵錯視窗,再按 ctrl-r 之後,renderer.js 的中斷點就可在 vscode 裡正常工作,據說是第一趟是 electron 啟動,remote debugger 還沒連上。
3. 因為 remote debugger 要連上,所以 electron 裡的 devTool 要關掉。不然 remote debug 會無法 attach。所以,DOM inspection 就沒辦法用了。

小結:這樣子用 vscode 專門偵錯 renderer.js 的部份。

參考

vscode 對 react jsx 加 webpack 做 debug

因為現在多數的前端開發,都會需要用到 babel 轉譯成 javascript,以及用到 webpack 做自動工作(例如打包),所以,以上的方法還需要做改進。xpbug 的方法是採用 main.js 用 vscode 偵錯,ui.js (renderer.js) 用 devTool 偵錯。

快速建構

下載原始碼

>git clone https://github.com/xpbug/electron-react-webpack.git

然後安裝所需套件

>npm install

生成程式,產生 app 目錄

>node node_modules\webpack\bin\webpack.js

執行程式

>node_modules\.bin\electron app

然後就可以在 devTool 裡對 ui.js 做偵錯,因為是轉譯過的,所以要對 webpack:///./src/ui/ui.js 做偵錯。這裡人比較好看得懂。

至於一步一步製作的方法,就請至 xpbug 的部落格參考。

這樣子的設定能做到:
1. 在 vscode 對 main.js 做偵錯,在 devTool 裡對 ui.js 做偵錯。

參考

[nodejs]打造自己的開發環境閱讀心得

前言

因為有點不知道除了 visual studio 之外的開發環境會長怎樣,所以研究了一下以下的文章,稍微了解一下現在的世界長怎樣了。 http://larry850806.github.io/2016/09/04/es7-environment/

我這篇算是心得報告,只有把我不會的地方加一些描述。要了解全部還請記得去原來的地方看。記得一定要感謝原作者 Larry Lu http://larry850806.github.io/about/
https://github.com/Larry850806/nodejs-ES7-template

了解生字

  • babel
    它看來是一個編譯器,把你寫的 javascript 轉成另一種寫法的 javascript。這大概就是目前 javascript 最有趣的地方吧…。 https://babeljs.io/
    類似的有:TypeScript, CoffeeScript

  • gulp
    這個看起來像是 gcc make 的系統,依照你寫的設定標,自動把編譯、複製、散佈等工作做完的系統。是 node.js 的套件之一。
    http://gulpjs.com/ http://abgne.tw/web/gulp/gulp-tuts-install-gulp-js.html

目錄安排

文章中的建議是因為有用了 gulp 做自動處理,所以會把檔案很乖地很分散在各個不同的目錄裡。

package.json
node_modules
gulpfile.js
index.js
src
    index.js
    utils.js
build
    index.js
    utils.js

package.json 與 node_modules 是 node.js 需要的。
gulpfile.js 是 gulp 的設定
最外面的 index.js 是程式執行的起點。但它只是轉一手讓 build/index.js 來執行。為了不要讓人太傷腦筋。
src 裡,原文是放 ES7 的程式,build 是被轉成 ES5 的程式。

註:ES7 與 ES5 是指 ECMA Script 7 與 ECMA Script 5。是 Javasript 目前的正式學名。兩個在語法上有不同,所以必須要分兩個名字來講。目前可以靠程式把新語法轉成舊語法,以利舊瀏覽器/舊環境執行,減少大家開發上轉換的痛苦。這一點也是獨特之處。

開發流程

開發時只動 src 裡的東西,其他的動作靠 gulp 來幫忙。
真正執行的起點是 ./index.js,而它會去執行 build/index.js。

gulp 設定

因為是靠 gulp 來處理轉譯與搬檔案,所以要了解一下它的用法。https://github.com/nimojs/gulp-book

文章內使用的設定是:

// gulpfile.js

var gulp = require('gulp');
var babel = require('gulp-babel');

gulp.task('babelify', function(){
    return gulp.src('src/**/*.js')
        .pipe(babel({
            presets: ['es2015', 'es2016', 'es2017'],
            plugins: [
                [
                    "transform-runtime", {
                        "polyfill": false,
                        "regenerator": true
                    }
                ]
            ]
        }))
        .pipe(gulp.dest(build))
});

使用方法是在命令列輸入 gulp babelify,gulp 就會把 src 裡所有的 js 用 babel 轉成 ES5 的程式碼,丟到 build 裡去。所需要的模組是:

{
    "babel-plugin-transform-runtime": "^6.12.0",
    "babel-preset-es2015": "^6.13.2",
    "babel-preset-es2016": "^6.11.3",
    "babel-preset-es2017": "^6.14.0",
    "gulp-babel": "^6.1.2"
}

babel 轉譯錯誤的輸出

若是在 babel 轉譯的時候有錯誤,要把錯誤寫出來,需要在 .pipe(babel({…}) 後面加上 on error 的處理函式

.on('error', function(err){
    console.log(err.stack);
    this.emit('end');
})

debug 用的 source map

在轉譯之後,有 exception 發生時,會 dump 出來的是已轉譯的程式碼(也就是 build/index.js),但是那個我們人類很難看,所以可借用所謂的 source map 來讓錯誤對應到 src/index.js 我們比較好修正。(本來設計也只能在 src 那裡動程式碼。)所以在 on(‘error’, … )的後面加上:

.pipe(sourcemaps.write({
            includeContent: false,
            sourceRoot: 'src'
}))

要讓 node 知道要採用 source map 來對應錯誤行號與內容,要在執行的 index.js 加上:

require('source-map-support').install();

要做到如此,source map 需要兩個模組:

{
    "gulp-sourcemaps": "^1.6.0",
    "source-map-support": "^0.4.2"
}

程式碼變動自動轉譯

這個功能原作者是用 gulp 來監視檔案有無變動,有的話就自動轉譯。要在 gulpfile.js 加上一段:

gulp.task('watch', function(){
    return gulp.watch(['src/**/*.js'], ['babelify']);
});

gulp.task('default', ['babelify', 'watch']);

最後

還可以多看一篇 http://larry850806.github.io/2016/07/25/react-optimization/ 這裡大概就可以知道為什麼 python 會有 mutable、immutable 的東西跑出來。

2017年1月4日 星期三

[rpi]apt-get 小抄

apt-get 小抄

rasbpberry pi 官方採用的 raspbian 是 debian 系統,ubuntu 也是源自於 debian。它們的套件管理系統是兩層建構(加上圖形化是三層),也就是 dpkg、apt,圖形化的第三層是 synaptic。

在以指令為主的環境中,主要使用的是 apt 層,它的指令是 apt-get。與 dpkg 的差別是它幫你處理相依性。

apt-get 的指令功能

  1. 安裝套件 apt-get install <package name>
  2. 移除套件 apt-get remove <package name>
  3. 移除套件及設定檔 apt-get remove --purge <package name>
  4. 更新套件列表 apt-get update
  5. 自動升級新套件 apt-get upgrade -y
  6. 清除套件暫存 /var/cache/apt/archives apt-get clean apt-get autoclean
  7. 搜尋套件 apt-cache search <keyword>
  8. 顯示套件詳細資訊 apt-cache show <package name>
  9. 移除沒用的套件 apt-get autoremove
  10. 列出已安裝套件 apt list --installed

dpkg 的指令功能

有時候不得已要手動處理套件,可能是相依性有的問題。這時就要用 dpkg 的指令。

  1. 不檢查相依性,直接安裝 dpkg -i <package name>
  2. 列出系統上已安裝的套件 dpkg -list
  3. 移除套件且清楚設定檔 dpkg -P <package name>
  4. 移除套件 dpkg -r <packag name>

圖形化套件管理程式

synaptic,這裡不介紹。請參考: http://blog.xuite.net/yh96301/blog/251085515-Ubuntu+14.04%E5%AE%89%E8%A3%9DSynaptic%E5%A5%97%E4%BB%B6%E7%AE%A1%E7%90%86%E7%A8%8B%E5%BC%8F

參考

2016年12月29日 星期四

electron 上手筆記

electron 上手筆記

這裡 electron 是說 github 推的跨平台桌面應用程式開發工具,使用 html, css, javascript 開發。

文件、範例哪兒找?

有無簡易模板?

請參閱 quick-start 那份文件,我這裡也略述之。

專案目錄檔案結構

專案名稱/
– package.json
– main.js
– index.html

package.json

package.json 的內容如下:

{
    "name":"專案名稱",
    "version":"0.1.0",
    "main":"main.js"
}

如果沒有 main 這欄,electron 會去找 index.js 來用。

main.js

main.js 的工作是建立 window 以及處理系統事件。(這裡的系統事件指的是 electron 裡的 app 物件事件)

以下是範例:

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

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win

function createWindow () {
  // Create the browser window.
  win = new BrowserWindow({width: 800, height: 600})

  // and load the index.html of the app.
  win.loadURL(url.format({
    pathname: path.join(__dirname, 'index.html'),
    protocol: 'file:',
    slashes: true
  }))

  // Open the DevTools.
  win.webContents.openDevTools()

  // Emitted when the window is closed.
  win.on('closed', () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    win = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (win === null) {
    createWindow()
  }
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

index.html

index.html 就等於是畫面定義。範例如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using node <script>document.write(process.versions.node)</script>,
    Chrome <script>document.write(process.versions.chrome)</script>,
    and Electron <script>document.write(process.versions.electron)</script>.
  </body>
</html>

開發時如何執行程式?

electron 安裝在 global

在專案目錄裡的命令列執行

electron .

electron 安裝在 local

在專案目錄裡的命令列執行

macOS/Linux

$ ./node_modules/.bin/electron .

Windows

$ .\node_modules\.bin\electron .

electron 是來自 binary download

Windows

$ .\electron\electron.exe your-app\

Linux

$ ./electron/electron your-app/

macOS

$ ./Electron.app/Contents/MacOS/Electron your-app/

有沒有現成的範例檔下載?

用 npm 來做:

# Clone the repository
$ git clone https://github.com/electron/electron-quick-start
# Go into the repository
$ cd electron-quick-start
# Install dependencies
$ npm install
# Run the app
$ npm start

2016年12月4日 星期日

[vscode]開發 extension 的豆知識

前置作業

開發 vscode 的 extension,要先知道的是:
* 開發語言是 TypeScript or JavaScript
* 開發電腦要裝 node.js,還有 Yeoman and the Yeoman VS Code Extension generator

npm install -g yo generator-code
yo code

產生起始開發專案

執行命令列 yo code 之後,會讓你選擇使用何種語言開發。
然後回答幾個問題,它就會產生一個目錄,再進去那個目錄裡執行 code .,就開始寫程式。需要一點時間,因為它需要下載相依套件,準備文件內容再啟動 vscode 編輯器。

debug

按 F5。會需要一點時間,它需要編譯相關檔案後,啟動 vscode 測試用編輯器。它的標題會寫[擴充功能開發主機],以標記為它實際是用來測試你寫的程式的。如果你有改程式,建議是在[擴充功能開發主機]按 ctrl-r 會比較快。如果是關掉它再按 F5 就會比較慢。至於文件上說直接按 F5 這招我就試不出來了。但是在[擴充功能開發主機]開著的情況下,有個 ctrl-shift-F5 是重新啟動,也很快速。

文件中有說,直接按 ctrl-r 重載入 會有用是因為 vscode 有為 .ts 的檔案註冊事件,只要有改變就會重新編譯,所以對於開發主機那裡只要重載入(ctrl-r)就行了。

vscode 的擴充功能的 API 也都有連帶放在 yo 所產生的檔案裡。就是 node_modules\vscode\vscode.d.ts

deploy

FileSystemWatcher

  • 一定要裝 .Net 4.5
  • 要監控的 path 那裡,請記得是它是 glob 的字串。要監控目錄,就是目錄再加 *.*

showInformationMessage

目前沒辦法自動消失

String.format

這個東西不在標配裡。在 typescript 也沒有。用幾個網路上找節的目前都無解。正在嘗試組合技。

參考