- 投稿日:2020-01-10T22:24:58+09:00
Windows10で快適な開発環境を得るための道のり~Node.js編~
はじめに
WSLのUbuntuにNode.js環境を作成します.
WSL環境作成手順はこちら → Windows10で快適な開発環境を得るための道のり~Docker編~
環境
- WIndows 10 Home
- WSL2
- Ubuntu 18.04
導入手順
node.js, npmをインストールする.
$ sudo apt install -y nodejs npm再ログイン後,バージョンの確認.(なぜか
nodejsでコマンドで登録される.)$ nodejs --version v8.10.0古い..
安定版の最新バージョンを使用したいのでn packageを導入する.
$ sudo npm install n --global /usr/local/bin/n -> /usr/local/lib/node_modules/n/bin/n /usr/local/lib └── n@6.1.3※n packageについては,こちらで詳しく紹介されています. → Node.jsのバージョンを管理するライブラリ「n」
n packageを用いて,安定版の最新バージョンをインストールする.
$ sudo n stable installing : node-v12.14.1 mkdir : /usr/local/n/versions/node/12.14.1 fetch : https://nodejs.org/dist/v12.14.1/node-v12.14.1-linux-x64.tar.gz installed : v12.14.1 (with npm 6.13.4) Note: the node command changed location and the old location may be remembered in your current shell. old : /usr/bin/node new : /usr/local/bin/node To reset the command location hash either start a new shell, or execute PATH="$PATH"最初に入れた古いnode.js, npmは削除する.
$ sudo apu purge -y nodejs npm $ exec $SHELL -lバージョンの確認
$ node --version v12.14.1→ OK!
参考
- 投稿日:2020-01-10T16:36:43+09:00
HomebrewでMySQL8を入れたが、node.jsから接続できない(認証方式変更)
エラー内容
Client does not support authentication protocol requested by server; consider upgrading MySQL client原因
MySQL8から認証方式が変わった(caching_sha2_password)ようで、
Homebrewからインストールできるmysqlはその認証方式に対応していないのが原因っぽい。やったこと
パスワードのポリシーを確認
SHOW VARIABLES LIKE 'validate_password%';認証方式の変更
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';反映
flush privileges;確認
SELECT user, host, plugin FROM mysql.user;参考
https://stackoverflow.com/questions/50093144/mysql-8-0-client-does-not-support-authentication-protocol-requested-by-server
https://its-office.jp/blog/web/2019/02/13/mysql8.html
https://qiita.com/ucan-lab/items/3ae911b7e13287a5b917
- 投稿日:2020-01-10T15:59:58+09:00
ServerlessFramework+Slackで運行遅延情報をお知らせする
はじめに
AWSLambdaで運行遅延情報をslackに通知するbotを作りました。
運行遅延APIを利用して、遅延が発生して入れば運行会社のWEBから遅延内容をスクレイピングしてSlackにお知らせします。
何番煎じか分かりませんが、lambdaとnodejsで書かれた記事が見当たらなかったので紹介します。作ったもの
GitHub
https://github.com/t-yasukawa/incoming-webhook環境
- macOS Catalina 10.15.2
- VSCode 1.41.1
- AWS(Lambda, CloudFormation)
- ServerlessFramework 1.60
- Node.js 12.14.1
- puppeteer 2.0.0
- chrome-aws-lambda 2.0.0
事前準備
- AWSアカウント
- SlackのWebhook URLの取得
- AWSCLIの導入 【真っさらな状態のMACにAWSCLIをインストールするまで】
- Node.jsの導入(nodebrewが便利)
1. ServerlessFrameworkの導入
まずはバージョン確認
$ npm ls --depth=0 -g /Users/t-yasukawa/.nodebrew/node/v12.14.1/lib └── npm@6.13.4ServerlessFrameworkを入れます。
npm i serverless -gでも良いのですが、他のプロジェクトでも使っているので今回はプロジェクト直下におきます。
npm initで生成されるpackage.jsonの初期値は適当に埋めてください。$ mkdir incoming-webhook $ cd incoming-webhook $ npm init package name: (incoming-webhook) version: (1.0.0) description: entry point: (index.js) test command: git repository: keywords: author: license: (ISC) $ npm i serverless $ npm ls --depth=0 incoming-webhook@1.0.0 /Users/t-yasukawa/git/incoming-webhook └── serverless@1.60.5無事インストールできました。
しかしこのままでは./node_modules/.bin/slsと毎回打たないといけないので面倒です。
方法は色々ありますが、安直にパスを追加します。$ echo 'export PATH=node_modules/.bin:$PATH' >> ~/.bash_profile $ source ~/.bash_profile $ sls -v Framework Core: 1.60.5 Plugin: 3.2.7 SDK: 2.2.1 Components Core: 1.1.2 Components CLI: 1.4.0これでOKです。
早速プロジェクトファイルをテンプレートから作成します。$ sls create --template aws-nodejs --path ./ Serverless: Generating boilerplate... Serverless Error --------------------------------------- The directory "/Users/t-yasukawa/git/incoming-webhook/" already exists, and serverless will not overwrite it. Rename or move the directory and try again if you want serverless to create it"はい、怒られました。
プロジェクトディレクトリはこのタイミングで作らないといけないようです。
serverlessをグローバルにしなかったせいですね。仕方ないので一旦パスを変えます。$ sls create --template aws-nodejs --path ./src/models/lambda Serverless: Generating boilerplate... Serverless: Generating boilerplate in "/Users/t-yasukawa/git/test/src/models/lambda" _______ __ | _ .-----.----.--.--.-----.----| .-----.-----.-----. | |___| -__| _| | | -__| _| | -__|__ --|__ --| |____ |_____|__| \___/|_____|__| |__|_____|_____|_____| | | | The Serverless Application Framework | | serverless.com, v1.60.5 -------' Serverless: Successfully generated boilerplate for template: "aws-nodejs"生成されたファイルを変更します。
$ mv src/models/lambda/serverless.yml ./ $ mv src/models/lambda/.gitignore ./ $ tree -a -L 1 . ├── .gitignore ├── node_modules ├── package-lock.json ├── package.json ├── serverless.yml └── src2.puppeteer導入
スクレイピング処理に
puppeteerを利用しますが、このままローカルで利用することができたのですが、
いざLambda上にデプロイしようとした時にLambdaの上限250MBを超えてしまう問題が発生しました。
An error occurred: SessionLambdaFunction - Unzipped size must be smaller than 262144000 bytes.そこで、軽量版の
puppeteer-coreとAWS上でchromiumが動くchrome-aws-lambdaを入れることでこれを回避します。
(ついでにAPI取得用のaxiosも入れます。)
※versionを揃えないと実行時にエラーとなるので注意
Error: Chromium revision is not downloaded. Run "npm install" or "yarn install"$ npm i chrome-aws-lambda puppeteer-core axios $ npm ls --depth=0 incoming-webhook@1.0.0 incoming-webhook ├── axios@0.19.1 ├── chrome-aws-lambda@2.0.0 ├── puppeteer-core@2.0.0 └── serverless@1.60.53.実装
- 遅延情報APIで遅延情報を取得
- お知らせしたい路線を検出
- 検出できたらWebに飛んでスクレイピング
- Slackに送信
handler.js'use strict' const axios = require("axios") const chromium = require("chrome-aws-lambda"); // 取得したい路線情報 const CHECK_LIST = [ { 'name': '常磐線', 'company': 'JR東日本', 'website': 'https://traininfo.jreast.co.jp/train_info/tohoku.aspx', 'selector': async (page) => await selectorForJrEast(page, '常磐線') }, { 'name': '東北本線', 'company': 'JR東日本', 'website': 'https://traininfo.jreast.co.jp/train_info/tohoku.aspx', 'selector': async (page) => await selectorForJrEast(page, '東北本線') }, { 'name': '仙台市営地下鉄', 'company': '仙台市交通局', 'website': 'https://www.kotsu.city.sendai.jp/unkou/', 'selector': async (page) => await selectorForSendaiSubway(page) }, ] module.exports.sendToSlack = async () => { // 鉄道運行遅延の情報を取得 const notifyDelays = await getNotifyDelays() if (notifyDelays.length == 0) { console.log('遅延情報はありませんでした。') return; } console.log('遅延情報が見つかりました。') // 遅延内容を取得 const messages = await getDelayMessage(notifyDelays) console.log(messages.join('\n')) // Sclackに送信 await postSlack(messages.join('\n')) } /** * 遅延情報を取得 */ async function getNotifyDelays() { const delay_url = process.env['TRAIN_DELAY_JSON_URL'] const notifyDelays = [] try { // 運行遅延情報を取得 const res = await axios.get(delay_url) // res = [{ // "name":"東北本線", // "company":"JR東日本", // "lastupdate_gmt":1578638905, // "source":"鉄道com RSS" // }] // 通知する路線のみ抽出 res.data.forEach(delayItem => { CHECK_LIST.forEach(checkItem => { if (delayItem.name == checkItem.name && delayItem.company == checkItem.company) { notifyDelays.push(checkItem) } }) }) } catch (error) { console.error(error) } return notifyDelays } /** * 遅延メッセージを取得 * * @param {Array} delays */ async function getDelayMessage(delays) { const messages = []; let browser = null try { browser = await chromium.puppeteer.launch({ args: chromium.args, defaultViewport: chromium.defaultViewport, executablePath: await chromium.executablePath, headless: chromium.headless }) const page = await browser.newPage() for(const i of delays) { // websiteから遅延情報をスクレイピング await page.goto(i.website) const detail = await i.selector(page) const message = `*・${i.company} \<${i.name}\>* (<${i.website}|jump>)\n ${detail}\n` messages.push(message) } } catch(e) { console.warn(e) } finally { if (browser !== null) { await browser.close() } } return messages; } /** * JR東日本(東北エリア)の遅延内容をスクレイピング * * @param {Page} page Page * @param {string} target 路線名 */ async function selectorForJrEast(page, target) { const selector = '#wrapper > div.main_con02 > div.table_access > table > tbody > tr' const messages = [] try { for (const item of await page.$$(selector)) { const lineName = await getTextContext(item, '.line_name') if (lineName == target) { const message = await getTextContext(item, '.status_text') messages.push(message) } } } catch (error) { console.error(error) return `:warning: ノードの取得に失敗しました。DOMが変更されている可能性があります。\n \`${selector}\` ` } return messages.join('\n') } /** * 仙台市地下鉄(南北・東西)の遅延内容をスクレイピング * * @param {Page} page Page */ async function selectorForSendaiSubway(page) { const selector = '#unkou_detail' try { const item = await page.$(selector) const text = await getTextContext(item) if (text == null) { return `:warning: ノードの取得に失敗しました。DOMが変更されている可能性があります。\n \`${selector}'\` ` } } catch (error) { console.error(error) return `:warning: ノードの取得に失敗しました。DOMが変更されている可能性があります。\n \`${selector}'\` ` } return text } /** * textContent取得 * * @param {ElementHandle} elementHandle * @param {string} target */ async function getTextContext(elementHandle, target) { const tag = await elementHandle.$(target) const prop = await tag.getProperty('textContent') const text = await prop.jsonValue() return text } /** * Slackへ送信 * * @param {string} message */ async function postSlack(message) { const slack_url = process.env['SLACK_WEBHOOK_URL'] const payload = { 'username': '運行遅延お知らせbot', 'icon_emoji': ':train:', 'attachments': [ { 'fallback': message, 'color': '#36a64f', 'pretext': '<!channel> 電車の遅延があります。', 'text': message, "mrkdwn_in": [ "text" ], 'channel': '#列車運行情報' } ] } const res = await axios.post(slack_url, payload) console.log(res) }serverless.ymlservice: incoming-webhook provider: name: aws runtime: nodejs12.x timeout: 300 profile: ${self:custom.profiles.${self:provider.stage}} region: ${opt:region, self:custom.defaultRegion} custom: defaultRegion: ap-northeast-1 profiles: dev: default package: exclude: - node_modules/serverless/** - node_modules/chrome-aws-lambda/** - chrome-aws-lambda/** functions: sendTrainDelayToSlack: handler: src/models/lambda/handler.sendToSlack events: - schedule: rate: cron(15 9,22,23 ? * MON-FRI *) ## 7:15,8:15,18:15 月~金 layers: - {Ref: ChromeLambdaLayer} environment: TRAIN_DELAY_JSON_URL: 'https://tetsudo.rti-giken.jp/free/delay.json' SLACK_WEBHOOK_URL: 'https://hooks.slack.com/services/****************' layers: chrome: package: artifact: ./chrome-aws-lambda/chrome_aws_lambda.zip4. 動作確認(問題発生)
動作確認のためにローカルでLambdaを実行するとchromiumが起動できないとエラーになりました。
$ sls invoke local --function sendTrainDelayToSlack 遅延情報が見つかりました。 Error: Failed to launch chrome! /var/folders/v8/ydzbmvkj6_zbm8msr6x730nr0000gn/T/chromium: /var/folders/v8/ydzbmvkj6_zbm8msr6x730nr0000gn/T/chromium: cannot execute binary file TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.mdMac環境でデバッグしようとするとPC内のChromeアプリのバイナリを利用しようとするのですが、
バイナリファイルのchromiumを実行することができませんでした。Chromeとモジュールのバージョンがリビジョン単位で違うけど、そのせい?よくわからず。。
Chromeバージョン:79.0.3945.117(2020/01/10時点)
puppeteer Version chrome-aws-lambda Version Chromium Revision 2.0.* npm i chrome-aws-lambda@~2.0.2 705776 (79.0.3945.0) 参照: https://github.com/alixaxel/chrome-aws-lambda
解決策
ローカルでは容量が大きいけど
puppeteerでchroniumのバイナリファイルをDLして利用し、
AWS上ではpuppeteer-coreとchrome-aws-lambdaを使うことにしました。$ npm i --save-prod chrome-aws-lambda puppeteer-core $ npm i --save-dev puppeteer Downloading Chromium r706915 - 111.8 Mb [====================] 100% 0.0s Chromium downloaded to /Users/t-yasukawa/git/incoming-webhook/node_modules/puppeteer/.local-chromium/mac-706915ただ、これだけではローカルで動かないのでデバッグ中だけ
executablePathを変える必要があります。browser = await chromium.puppeteer.launch({ args: chromium.args, defaultViewport: chromium.defaultViewport, - executablePath: await chromium.executablePath, + executablePath: null, headless: chromium.headless })もしくは上記でDLしたchromiumのパスでも行けると思います。
executablePath: `${process.cwd()}/node_modules/puppeteer/.local-chromium/mac-706915/chrome-mac/Chromium.app/Contents/MacOS/Chromium`5.動作確認(解決)
$ sls invoke local --function sendTrainDelayToSlack 遅延情報が見つかりました。 *・JR東日本 <東北本線>* (<https://traininfo.jreast.co.jp/train_info/tohoku.aspx|jump>) 東北本線は、釜石線内でのシカと衝突の影響で、盛岡~花巻駅間の上下線で一部列車が運休となっています。無事スクレイピングできました。・・・シカさん
![]()
6.解説
API関連は
axiosを使いました。とてもシンプルで使いやすい!const res = await axios.get(delay_url) const res = await axios.post(slack_url, payload)遅延情報はJR東日本と仙台市地下鉄の2サイトからスクレイピングしました。
地下鉄はノード指定ですんなり取得できましたが、JRの方はノード取得に癖があったので力技でした。スクレイピングのやり方ですが簡単に取得できます。(chromeの場合)
デベロッパーツールを開く(検証モード) → 指定ノードの箇所で右クリック → Copy → Copy selectorコンソール上で以下を入力することでも確認できます。
document.querySelector('{copyしたノード}').textContentjsなのでそのままコードで使えますが、今回は
puppeteerの用意したものを使います。const browser = await chromium.puppeteer.launch() const page = await browser.newPage() await page.goto({webUrl}) const tag = await page.$('#wrapper > div.main_con02 > div.table_access > table > tbody > tr:nth-child(21) > td > p.status_text') const prop = await tag.getProperty('textContent') const text = await prop.jsonValue() console.log(text) // 水郡線は、台風の影響で、西金~常陸大子駅間の上下線で当面の間運転を見合わせます。同区間でバスによる代行輸送を実施します。それにしても長い。。。
7.AWSへデプロイ
さぁ、最後はAWSへデプロイしてCloudWatchを使って定時実行させれば完成です。
Lambdaの容量をなるべく節約して使うため不要なモジュールたちを削除します。
ローカルで使っていたpuppeteerを除いた状態で再インストールします。
serverlessもLambdaには必要ないのですがデプロイコマンドで必要なのでproductionに含めます。$ rm -rf node_modules $ npm i --production
chrome-aws-lambdaもそこそこの容量なのでそのまま入れずzipに固めてLambda Layerに格納させます。
他のLambdaでスクレイピングしたい時はこのLayerが汎用的に使えて便利です。
READMEにしたがってzipに圧縮します。
パーミッションも変えないとデプロイできなかったので適宜変えてください。$ git clone --depth=1 https://github.com/alixaxel/chrome-aws-lambda.git $ cd chrome-aws-lambda $ make chrome_aws_lambda.zip $ chmod 777 chrome_aws_lambda.zipLambdaアプリをzipで固める前にさらに不要なファイルを除外します。
serverless.ymlpackage: exclude: - node_modules/serverless/** - node_modules/chrome-aws-lambda/** - chrome-aws-lambda/** layers: chrome: package: artifact: ./chrome-aws-lambda/chrome_aws_lambda.zip最後にデプロイして終了!
ちょっとしたアプリですがモジュールを入れるとそこそこのサイズになりますね。
incoming-webhook.zip file to S3 (25.49 MB)
chrome_aws_lambda.zip file to S3 (41.63 MB)$ sls deploy --verbose --profile dev Serverless: Packaging service... Serverless: Excluding development dependencies... Serverless: Uploading CloudFormation file to S3... Serverless: Uploading artifacts... Serverless: Uploading service incoming-webhook.zip file to S3 (25.49 MB)... Serverless: Uploading service chrome_aws_lambda.zip file to S3 (41.63 MB)... Serverless: Validating template... Serverless: Updating Stack... Serverless: Checking Stack update progress... CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - incoming-webhook-dev CloudFormation - UPDATE_IN_PROGRESS - AWS::Lambda::LayerVersion - ChromeLambdaLayer CloudFormation - UPDATE_IN_PROGRESS - AWS::Lambda::LayerVersion - ChromeLambdaLayer CloudFormation - UPDATE_COMPLETE - AWS::Lambda::LayerVersion - ChromeLambdaLayer CloudFormation - UPDATE_IN_PROGRESS - AWS::Lambda::Function - SendTrainDelayToSlackLambdaFunction CloudFormation - UPDATE_COMPLETE - AWS::Lambda::Function - SendTrainDelayToSlackLambdaFunction CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - incoming-webhook-dev CloudFormation - DELETE_IN_PROGRESS - AWS::Lambda::LayerVersion - ChromeLambdaLayer CloudFormation - DELETE_COMPLETE - AWS::Lambda::LayerVersion - ChromeLambdaLayer CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - incoming-webhook-dev Serverless: Stack update finished... Service Information service: incoming-webhook stage: dev region: ap-northeast-1 stack: incoming-webhook-dev resources: 7 api keys: None endpoints: None functions: sendTrainDelayToSlack: incoming-webhook-dev-sendTrainDelayToSlack layers: chrome: arn:aws:lambda:ap-northeast-1:*:layer:chrome:9 Stack Outputs SendTrainDelayToSlackLambdaFunctionQualifiedArn: arn:aws:lambda:ap-northeast-1:*:function:incoming-webhook-dev-sendTrainDelayToSlack:17 ChromeLambdaLayerQualifiedArn: arn:aws:lambda:ap-northeast-1:*:layer:chrome:9 ServerlessDeploymentBucketName: incoming-webhook-dev-serverlessdeploymentbucket-* Serverless: Removing old service artifacts from S3... Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.参考
- 投稿日:2020-01-10T11:30:56+09:00
[Electron] IPC には新しい ipcRenderer.invoke() メソッドを使ったほうが便利 (v7+)
TL;DR;
Electron v7 から、
ipcRenderer.invoke()、ipcMain.handle()が新たに追加されました。これは、従来まで利用されてきたipcRenderer.send()やipcRenderer.sendSync()の上位互換のようなものです。今後は積極的にこちらを使ったほうがよさそう。従来の Renderer <-> Main プロセス間通信 (IPC)
同期:
ipcRenderer.sendSync()文字通り、同期 (Sync) 的にプロセス間通信を行います。
この際に重要なのは、sendSync によって Main プロセスが呼ばれるとその間は Renderer プロセス上の処理は完全にブロックされます。Main プロセスからの応答があるまでは、renderer プロセス側の操作画面はいわゆるフリーズしたような状態になります。描画処理も止まるので、ローディング画面のような CSS アニメーションも容赦なく固まります。ドキュメントにも下記のように、どうしても使わざるを得ない状況下においてのみ最終手段として使う、そうでない場合は利用を避けることが推奨されています。
⚠️ WARNING: Sending a synchronous message will block the whole renderer process until the reply is received, so use this method only as a last resort. It's much better to use the asynchronous version,
invoke().renderer// renderer から Main プロセスを呼び出す const data = ipcRenderer.sendSync('sync-test', 'ping') console.log(data)mainipcMain.on('sync-test', (event, message) => { // message には 呼び出し元からのデータ ('ping') が入っている console.log(message) event.returnValue = 'pong' return })console> ping > pongMain プロセス側での処理が終わってから renderer 側で console.log が走るため、結果は上記のようになります。メリットとして、
event.returnValueを通じて呼び出し元にデータを返すことができます。非同期:
ipcRenderer.send()非同期実行のため、Main プロセスの処理中であっても renderer 側ではフリーズすることなく操作が可能です。
ただし Main プロセス側の処理がいつ終わったのか renderer 側では分からないので、これをトリガーに何らかの処理を行いたい場合、renderer 側で
ipcRenderer.on()を定義しておくことで、Main -> rendere 方向の戻りの通信が可能になります。renderer// main からの呼び出しを待ち受ける ipcRenderer.on('async-test-complete', (event, message) => { console.log(message) )} // renderer から Main プロセスを呼び出す ipcRenderer.send('async-test', 'ping') console.log('started')mainipcMain.on('async-test', (event, message) => { // message には 呼び出し元からのデータ ('ping') が入っている console.log(message) // main から renderer プロセスを呼び出す event.sender.send('async-test-complete', 'pong') return })console> started > ping > pong新しい Renderer <-> Main プロセス間通信 (IPC)
非同期:
ipcRenderer.invoke()ようやく本題です。Electron version 7+ から利用可能になりました。
こちらも非同期ですが、Main プロセスからは Promise が返ってきます。ですので、awaitを使って Main プロセスからのデータの受取を下記のようにシンプルに書くことができます。renderer// renderer から Main プロセスを呼び出す const = data = await ipcRenderer.invoke('invoke-test', 'ping') console.log(data)mainipcMain.handle('invoke-test', (event, message) => { // message には 呼び出し元からのデータ ('ping') が入っている console.log(message) // renderer プロセスにデータを返す return 'pong' })console> ping > pongMain 側では、
ipcMain.handle()とメソッド名が変わっています。
- 投稿日:2020-01-10T02:56:05+09:00
Oculus Quest で日本語を打つ
VR 空間でも日本語入力
製作物
日本語メモ (Glitch プロジェクト)
Oculus Quest なら Alt + Space で半角 ⇔ 日本語入力の切り替え。
URL を開くと ID が URL に付与されますので、再度編集したい場合は ID が付けられた URL をブックマークしてください。
テキストが変更がされると自動でサーバーに保存されます。解説
Oculus Quest + Firefox Reality + Glitch + A-Frame で VR 内 VR 開発 を推進している gaegae です。
前回の記事でデメリットに上げませんでしたが、
2020/01/10現在、Oculus Quest では Bluetooth キーボードから日本語入力できません。
Firefox Reality ではソフトキーボードで日本語入力できますが、 Bluetooth は非対応です。
デフォルトブラウザはソフトキーボードも対応していません。コーディング時に必須ではないので特に問題ないだろうと思っておりましたが、
作業しているときにひらめきを即座にメモできないのがきつく感じてきました?英語で書くのはしんどい、メモのためにヘッドセット外したら本末転倒。
Firefox Reality のイシューに日本語入力をお願いしていますが、無理難題を Mozilla さんに押し付けるのも失礼。なのでプログラマなのだから自分でどうにかしたいと思います。
VR 開発の記事をどんどん上げていきたいところですが、その前に足固めです。方針
Oculus Quest の IME をどうにかするのは正直無理。 やる前からあきらめてました。
最低限、日本語のメモが取れればよかったので、
Javascript で日本語入力 を実装した Web ページを作成することにしました。詳細
フロントエンドとサーバーサイド、2つの Glitch プロジェクトを作りました。
フロントエンド:https://glitch.com/~oculusquest-jpn-ime
テキストエリアが一つだけの Web ページです。
日本語入力には IgoIME を使用させていただいております。
変更があればサーバーに送信し、再度画面が表示されたときに読み込みます。サーバーサイド:https://glitch.com/~dot-spruce
認証不要で使えるシンプルな Key Value Store です。
node.js 上でキーをファイル名、値を内容にしてファイルとして保存しています。
他のプロジェクトでも使い回せるように分けました。おわりに
これでまたヘッドセット着脱の手間が減り、VRへの没入感がさらに上がりました。
今回は Oculus Quest よりも Glitch の話がメインでした。
やはりボタン一発で瞬時に Linux・node.js・IDEと Web 開発に必要なもの一通りを提供してくれるのは素晴らしいですね。
Google や AWS 、Github ページなどを利用するよりも気軽に開発・配信ができると思われますので
Web コンテンツ作りたい方、ぜひどうぞ!
- 投稿日:2020-01-10T02:56:05+09:00
Oculus Quest + Bluetooth キーボードで日本語を打つ
VR 空間でも日本語入力
製作物
日本語メモ (Glitch プロジェクト)
Oculus Quest なら Alt + Space で半角 ⇔ 日本語入力の切り替え。
URL を開くと ID が URL に付与されますので、再度編集したい場合は ID が付けられた URL をブックマークしてください。
テキストが変更がされると自動でサーバーに保存されます。解説
Oculus Quest + Firefox Reality + Glitch + A-Frame で VR 内 VR 開発 を推進している gaegae です。
前回の記事でデメリットに上げませんでしたが、
2020/01/10現在、Oculus Quest では Bluetooth キーボードから日本語入力できません。
Firefox Reality ではソフトキーボードで日本語入力できますが、 Bluetooth は非対応です。
デフォルトブラウザはソフトキーボードも対応していません。コーディング時に必須ではないので特に問題ないだろうと思っておりましたが、
作業しているときにひらめきを即座にメモできないのがきつく感じてきました?英語で書くのはしんどい、メモのためにヘッドセット外したら本末転倒。
Firefox Reality のイシューに日本語入力をお願いしていますが、無理難題を Mozilla さんに押し付けるのも失礼。なのでプログラマなのだから自分でどうにかしたいと思います。
VR 開発の記事をどんどん上げていきたいところですが、その前に足固めです。方針
Oculus Quest の IME をどうにかするのは正直無理。 やる前からあきらめてました。
最低限、日本語のメモが取れればよかったので、
Javascript で日本語入力 を実装した Web ページを作成することにしました。詳細
フロントエンドとサーバーサイド、2つの Glitch プロジェクトを作りました。
フロントエンド:https://glitch.com/~oculusquest-jpn-ime
テキストエリアが一つだけの Web ページです。
日本語入力には IgoIME を使用させていただいております。
変更があればサーバーに送信し、再度画面が表示されたときに読み込みます。サーバーサイド:https://glitch.com/~dot-spruce
認証不要で使えるシンプルな Key Value Store です。
node.js 上でキーをファイル名、値を内容にしてファイルとして保存しています。
他のプロジェクトでも使い回せるように分けました。おわりに
これでまたヘッドセット着脱の手間が減り、VRへの没入感がさらに上がりました。
今回は Oculus Quest よりも Glitch の話がメインでした。
やはりボタン一発で瞬時に Linux・node.js・IDEと Web 開発に必要なもの一通りを提供してくれるのは素晴らしいですね。
Google や AWS 、Github ページなどを利用するよりも気軽に開発・配信ができると思われますので
Web コンテンツ作りたい方、ぜひどうぞ!
- 投稿日:2020-01-10T00:01:43+09:00
開発環境の1つであるVSCodeの開発環境についてチラ見してみる
リーマンサットについて
趣味で宇宙開発を行う団体「リーマンサット・プロジェクト」がお送りする新春アドベントカレンダーです。インデックスはこちら
リーマンサット・プロジェクトは「普通の人が集まって宇宙開発しよう」を合言葉に活動をしている民間団体です。
他では経験できない「宇宙開発プロジェクト」に誰もが携わることができます。
興味を持たれた方は https://www.rymansat.com/join からお気軽にどうぞ。概要
機械学習周りやWEBサービスを担当してますAkira Sugawaraです。
開発環境、、、エンジニアなら誰しも気になりますよね?
リーマンサットでは趣味開発なので、特に大きな制限を設けずに自由に開発しています。
開発エディタはVSCodeやIntelliJ、ソースコード・タスク管理はBacklog、といった感じです。VSCodeの開発環境
ふと、VSCodeってどう作られてるんだろうか、どんな開発環境なんだろうか、と考えてしまいました。
思いを馳せると夜も眠れなくなってしまいます。開発環境の一部であるエディタを開発している開発環境は、さぞこだわりがあるんだろう…。
ということで、本記事ではVSCodeの開発環境を調べてみます。
VSCodeのツールチェーン
2019/12/30時点でのmasterブランチをcloneして確認しています。。
type details Language typescript,javascript Application Framework Electron Linter ESLint, TSLint Formatter prettier TaskRunner NPM, gulp TestFramework mocha CI/CD Azure Pipeline CI/CDに関しては、./build/azure-pipelinesのフォルダの下にOS毎のビルド定義ファイルが格納されています。
さすがにMicrosoftのOSSということなので、Azureになってるんですね。使用してるVSCodeExtension
もちろんVSCodeの開発もVSCodeですよね!
ワークスペースのRecommendリストは下記です。
"ms-vscode.vscode-typescript-tslint-plugin"
eslintがtypescriptサポートを強化するという発表もありましたが、フロントエンドによくあるESLint/TSLint併用構成のようです
"dbaeumer.vscode-eslint"
言わずもしれたESLintのvscodeプラグインです。
"EditorConfig.EditorConfig"
恥ずかしながら使用経験がありませんでした。
複数人で作業するときのEditorのConfigurationToolで、言語非依存・エディター非依存で規約の準拠が可能になります。
Prettierと役割重なってるんじゃない?と思いましたが、この記事が違いがわかりやすかったです。"msjsdiag.debugger-for-chrome"
Chromeでjavascriptをデバックするための連携ツールです。
まとめ
さらーっと、VSCodeの開発環境を見ていきました。
何かしらのプロジェクトで新しく開発を始める場合、著名なOSSの環境を見てみるのは参考になるかもしれませんね。次の記事は、@KingBritainの「航空機の流体力学(2次元翼の流体解析)」になります。
参考




