20200112のNode.jsに関する記事は14件です。

Sonos で Lチカ してみた。

はじめに

電子工作のはじめの一歩と言えば「Lチカ」ですね。
ワイヤレススピーカーシステム Sonos でも「Lチカ」を試すことができます。
Sonos One にはステータスライトがついており、このステータスライトの色や点滅で状態を確認することができます。(白色点灯状態が正常です)

ただ、夜中暗い中でステータスライトが点灯していると眩しいことがあるので、Sonos アプリからステータスライトを OFF にすることができます。
Sonos_App.jpeg

プログラムから LED を操作する

Sonos は API が公開されていますので、プログラムから LED を操作することが可能です。

  • getLEDState() →現在の LED の状態を取得します
  • setLEDState(desiredState) → LED の状態を変更します

JavaScript (node.js) の node-sonos モジュールを使用してスクリプトで LED を操作してみました。

インストール

node のバージョンを確認します。(nodebrew で node のバージョン管理を行っています。)

$ nodebrew list
v6.14.1
v8.14.0
v9.11.2
v12.14.1

current: v12.14.1
$ node -v
v12.14.1

node-sonos をインストールします。

$ npm install sonos

スクリプトの実行

Sonos の LED のステータスを確認して、On なら Off へ、Off なら On へ変更するスクリプトです。

$ node setLEDState.js 
Got current LED state "Off"
Success LED: Off->On
$ node setLEDState.js 
Got current LED state "On"
Success LED: On->Off
setLEDState.js
const Sonos = require('sonos').Sonos
const sonos = new Sonos(process.env.SONOS_HOST || '192.168.13.4', process.env.SONOS_PORT || 1400)

sonos.getLEDState().then(state => {
  console.log('Got current LED state %j', state)
  if (state == "On") {
    sonos.setLEDState("Off").then(state => {
      console.log('Success LED: On->Off')
    }).catch(err => { console.log('Error occurred %j', err) })
  }
  if (state == "Off") {
    sonos.setLEDState("On").then(state => {
      console.log('Success LED: Off->On')
    }).catch(err => { console.log('Error occurred %j', err) })
  }
}).catch(err => { console.log('Error occurred %j', err) })
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laragonで簡単に開発環境を構築する

皆さん、学習するとき、開発をするとき、ローカルで確認を行うときの環境構築はどうされていますか?
恐らくMacを所有している方が多くDockerを使われている方が多いと思います。

自分が現在、所有しているはHPのSPECTRE X360 13、Windows 10 Homeです。Windows 10 Homeなのです。
ラップトップと言っても非力というほどではありませんがVagrantを立ち上げている間、かなりファンが回り気になります。
それに決して速いとは言えません。さらに現時点ではまだWSL2とDocker for WSLは正式リリースされていません。

ではどうするか?
コメント 2020-01-01 215211.png
https://laragon.org/

Laragonです。
Windows向けのAMP環境構築ソフトで
PHP、Node.js、Python、Java、Go、Rubyをサポートし、
ApacheとNginxのどちらを使用するかを切り替えることができます。
では早速、インストールを行っていきましょう。

1. インストール

コメント 2020-01-01 215427.png
https://github.com/leokhoa/laragon/releases

Githubから最新版を落としてきましょう。
環境構築の経験がない、初学者の方はlaragon-full.exeを選んでいきましょう。
以後はこれをベースに進めます。

インストール先は拘りがなければわかりやすいようデフォルトのC:\Laragonにしておきます。
Laragon 2020-01-12 164745.png

VSCode等を使用する際は"Sublime Text & Terminalを追加する"のチェックが外れた状態にしておきます。
Laragon 2020-01-12 164703.png
ちなみにNotepad++、WinSCP、Putty、HeidiSQL Portable等がインストールされるのでこの1回のインストールだけで開発が出来るようになります。

2. 起動

では起動してみましょう。
Laragon 2020-01-12 165644.png
このスクリーンショットでPHP7.4になっているのは自身で後から追加ができるためです。
"ウェブ"を押すとホスト名を"localhost"ポート番号を8080で設定しているので
"http://localhost:8080/"
の形でブラウザが開きます。
"データベース"でHeidiSQL
"ターミナル"でCmderを起動します。
"ルート"は設定されたルートフォルダを表示します。"ウェブ"で表示される場所も同じものになります。
設定は右上にの歯車マークから表示できる設定で行います。

3. バージョンの追加

今回はPHPを例に紹介します。
https://windows.php.net/download/
から使用するものをダウンロードしてきます。
フォルダを解凍後、
C:\laragon\bin\php\へ追加します。
PythonであればC:\laragon\bin\python\のようになります。
Laragon 2020-01-12 170749.png
追加後に使用するバージョンを左上のメニューから選択します。
Laragon 2020-01-12 171603.png
ここから起動時に使用する言語やバージョン等を切り替えることが出来ます。

4.ガンガン使いましょう!

Macには現時点で対応していませんし、万能とまではいかないまでも
軽く使いやすいので空いた時間でサクッと作業を行うのに役立ちます。
OSがWindows 10 Homeで開発環境で悩んでいる方に特にオススメです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

本当のimport Vue from 'vue'を研究して、分かってきたもの

import Vue from 'vue'はなぜ使えるか?

Vuejsの開発の際、よく最初に出てくるこれ

import Vue from 'vue';

下のような相対パスなどはまだわかりやすいけど、

import Example from './Example.vue';

vueはなずimportできるのか、みんな様こんな疑問はないのか。
もしかして俺一人の疑問かも?

少し研究してきたことをまとめてみた。

importとは

Javascriptのモジュールシステムです。他のファイルを使いたい時、require functionで他のファイルの内容を引用する。
es6を使っている時、importrequireにコンパイルする。
だから、実際に実行するコードは以下。

import Vue from 'vue';
⬇️
const Vue = require('vue')

nodejs引用ルール

実は、nodejsの中に、requireを使う時に、require.reslove functionを使ってファイルのパスを探している。このfunctionは優先順位は以下になる。
require(X) from module at path Y
1.もしXはコアのパッケージかどうか、普段のpathなどみたいは直接引用される。ではなければ、次へ。
2.もしX/から始めれば、YのパスはOSのrootと設定。ではなければ、次へ。
3.もしX./,/,../から始めれば、(Y + X)ファイルかディレクトリ引用。ではなければ、次へ。
4.node_modulesフォルダの中に、見つかる!

node_modulesにあるvue

node_modulesに確かにvueというフォルダは存在しているが、new Vue()などの操作の時は、JsのObjectとして使っている。では、なぜか!
真の犯人まではもう少し?❗️
npmのパッケージとして、内部の出力はまたルールがある!
まずは、node_modules/vueのディレクトリツリーを見てみる。

├── LICENSE
├── README.md
├── dist
├── package.json
├── src
└── types

ルールは以下になる。
1.package.jsonmainが定義されたら、mainに入り口を探す。
2.package.jsonがなければ、index.jsindex.nodeを読む。
3.どちらもなければ、Error: Cannot find module 'some-library'を投げる。

では、node_modules/vue/packeage.jsonこう書いてある❗️

  ...
  "main": "dist/vue.runtime.common.js",
  ...

ではでは、だんだん明らかになってきた❗️

本当にいつもimportしたものは...

import vue from 'vue';

// 実は、これに変換する
const vue = require('./node_modules/vue/dist/vue.runtime.common.js');

その内容は

if (process.env.NODE_ENV === 'production') {
  module.exports = require('./vue.runtime.common.prod.js')
} else {
  module.exports = require('./vue.runtime.common.dev.js')
}

これは普段npmのスクリプトにあるNODE_ENV=developmentを読んで、実行環境に応じて違うvueインスタンスのexportができるようになった?

今回のimportルールや他にも今回出てなかったルールの詳細はnodejsのドキュメントに?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

import Vue from 'vue'の意味を研究して、分かってきたもの

import Vue from 'vue'はなぜ使えるか?

Vuejsの開発の際、よく最初に出てくるこれ

import Vue from 'vue';

下のような相対パスなどはまだわかりやすいけど、

import Example from './Example.vue';

vueはなずimportできるのか、みんな様こんな疑問はないのか。
もしかして俺一人の疑問かも?

少し研究してきたことをまとめてみた。

importとは

Javascriptのモジュールシステムです。他のファイルを使いたい時、require functionで他のファイルの内容を引用する。
es6を使っている時、importrequireにコンパイルする。
だから、実際に実行するコードは以下。

import Vue from 'vue';
⬇️
const Vue = require('vue')

nodejs引用ルール

実は、nodejsの中に、requireを使う時に、require.reslove functionを使ってファイルのパスを探している。このfunctionは優先順位は以下になる。
require(X) from module at path Y
1.もしXはコアのパッケージかどうか、普段のpathなどみたいは直接引用される。ではなければ、次へ。
2.もしX/から始めれば、YのパスはOSのrootと設定。ではなければ、次へ。
3.もしX./,/,../から始めれば、(Y + X)ファイルかディレクトリ引用。ではなければ、次へ。
4.node_modulesフォルダの中に、見つかる!

node_modulesにあるvue

node_modulesに確かにvueというフォルダは存在しているが、new Vue()などの操作の時は、JsのObjectとして使っている。では、なぜか!
真の犯人まではもう少し?❗️
npmのパッケージとして、内部の出力はまたルールがある!
まずは、node_modules/vueのディレクトリツリーを見てみる。

├── LICENSE
├── README.md
├── dist
├── package.json
├── src
└── types

ルールは以下になる。
1.package.jsonmainが定義されたら、mainに入り口を探す。
2.package.jsonがなければ、index.jsindex.nodeを読む。
3.どちらもなければ、Error: Cannot find module 'some-library'を投げる。

では、node_modules/vue/packeage.jsonこう書いてある❗️

  ...
  "main": "dist/vue.runtime.common.js",
  ...

ではでは、だんだん明らかになってきた❗️

本当にいつもimportしたものは...

import vue from 'vue';

// 実は、これに変換する
const vue = require('./node_modules/vue/dist/vue.runtime.common.js');

その内容は

if (process.env.NODE_ENV === 'production') {
  module.exports = require('./vue.runtime.common.prod.js')
} else {
  module.exports = require('./vue.runtime.common.dev.js')
}

これは普段npmのスクリプトにあるNODE_ENV=developmentを読んで、実行環境に応じて違うvueインスタンスのexportができるようになった?

今回のimportルールや他にも今回出てなかったルールの詳細はnodejsのドキュメントに?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【ECMAScript】importでSyntaxError

ECMAScriptの記法を学習していたところ、外部モジュールのimportで詰まったので解決策を残しておきます。

実行環境

  • Node.js : v12.12.0
  • IDE: WebStorm(2019.3.1)

ディレクトリ / ファイル

index.jsからadd.jsで定義した関数を使うだけの簡単なものです。

.
├── add.js
└── index.js
index.js
import { add } from "./add.js";

console.log(add(10, 15));
add.js
export function add(a, b){
    return a + b;
}

なぜかimportの箇所SyntaxErrorとなる

実行時、エラーが出力されたので調べてみたところ、以下の対応が必要とのこと。

  • 実行時オプションに --experimental-modules を指定する
  • ファイル拡張子を変更する(js -> mjs) or package.json を作成する

今回は拡張子は変えず package.json ファイルを作成して対応。

(node:13761) ExperimentalWarning: The ESM module loader is experimental.
(node:13761) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
import { add } from "./add";
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Module._compile (internal/modules/cjs/loader.js:892:18)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)
    at Module.load (internal/modules/cjs/loader.js:812:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1025:10)
    at internal/main/run_main_module.js:17:11

エラー対応後

.
├── add.js
├── index.js
└── package.json
package.json
{
  "type": "module"
}

Node parameters--experimental-modules を追加
webstorm.png

実行してみる

正常に実行できたようです。

/Users/xxxxx/.nodebrew/current/bin/node --experimental-modules /Users/xxxxx/WebstormProjects/untitled/index.js
(node:13854) ExperimentalWarning: The ESM module loader is experimental.
25

Process finished with exit code 0

参考

[Node.js の ESModules]
http://var.blog.jp/archives/80335431.html

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ネット環境なしで手持ちの端末をサーバーに接続させる。

発端

筆者はよく行きつけのカフェでイキりながらWEB開発をしております。

ところが困ったことに、カフェなどで設置されている公共Wifiでは、ルーターの設定で他機の存在が秘匿にされている場合が多いです。(当然pingも打てない)

セキュリティの観点から妥当な処置ではあるのですが、開発しているWEBサイトをスマホで確認する・・・といったことはできません。

対処法として、パソコン自体をルーターにして独自のLANを構築し、端末と通信することがあげられます。

パッと見では難しそうですが、Windowsでは7からSoftAPという機能が標準で用意されており、Microsoftが提供している仮想ネットワークアダプタを利用して、パソコンをルーターとして扱うことができるようになります。

そこで今回は、SoftAPを利用してパソコン単体でLANを構築し、Nodeでサーバーを起動、手持ちの端末でLANに接続して、サーバーからレスポンスを受け取ることを目標にします。

LANの構築

1 . コマンドプロンプトを管理者権限で起動

2 . 以下のコマンドを実行

C: > netsh
netsh > wlan
netsh wlan > set hostednetwork mode=allow ssid=your_ssid key=your_password

3 . hostednetworkを起動

netsh wlan> start hostednetwork

これでうまくいった人はついてます。
筆者の場合は下記のログが出てLANが構築できませんでした。

netsh wlan> start hostednetwork
ホストされたネットワークを開始できませんでした。
グループまたはリソースは要求した操作の実行に適切な状態ではありません。

主にMicrosoft Hosted Network Virtual Adapterが有効になっていない場合が想定されます。対処法は後ろに載せます。参考に他の記事も載せておくのでそちらもどうぞ。

起動に成功した場合は、LAN内のipアドレスを確認します。

> ipconfing
~~
IPv4 アドレス . . . . . . . . . . . .: 192.168.0.1
~~

サーバーの起動

Nodeでサーバーを起動します。

server.js
const express=require("express");
const app=express()
app.get('/',(req,res)=>{
    res.send(`Hello World!`);
});
app.listen(3000);

実機で接続

1 . 端末から、上で設定したSSIDにWifiで接続

2 . ブラウザで IPアドレス + ポート にアクセス
(上の例だと192.168.0.1:3000)

うまくHello Worldできてれば成功 !!

これでパソコンで起動したサーバーと端末を、ネット環境に依存せずに接続させることができました。

LANを構築しているパソコンがネットに接続できている場合は、端末がネット上のリソースを要求してもきちっと返してくれます。(というかまんまプロキシなので)

当然ネット環境がないとインターネット上のリソースが必要になるような処理は無理です。

しかし序盤で言ったように、他機の存在が秘匿されているようなLANでは、パソコンがプロキシとなって端末と接続できるようになる、という意味で有用な場面もあるのではないでしょうか。

(追記)Microsoft Hosted Network Virtual Adapterのインストール

SoftAPではMicrosoftが提供しているMicrosoft Hosted Network Virtual Adapterというネットワークアダプタを利用しています。こちらを用意してあげる必要があります。

1 . 下のコマンドを実行し、ドライバー名を確認する。

netsh wlan> show drivers

2 . デバイスマネージャーを起動し、ネットワークアダプターの欄の中にある、1で確認したドライバー名を右クリック

3 . ドライバーの更新を選択し、コンピューターを参照してドライバーソフトウェアを検索を選択。

4 . コンピューター上の利用可能なドライバーの一覧から選択しますを選択。

5 . ※Microsoftのモデルを選択して、次へ、ドライバーをインストールする。

※筆者の場合は同名のモデルがいくつもでて、順に更新していったら成功しました。

6 . デバイスマネージャーのメニューバーにある表示タブで、非表示のデバイスの表示を選択。ネットワークアダプターの欄にあるであろうMicrosoft Hosted Network Virtual Adapterを有効にする。

これでhostednetworkが起動できるはずです。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

NodeJSで、opencvを触るまで

Node jsは偉大ですよね!

一つのプログラムでhttpサーバーもwebscketサーバーも、ラズパイを使えばSPIやシリアル通信まで行えてしまいます!

しかも速度だってc++とそこまで変わらないし(ほんまか)

もうJavaScriptはクソだって言わせない!

さて、Nodejsを布教するのはこれくらいにして本題に入ります。

本題

Nodejsから、webカメラの画像を読み込みたい!!

調べていてよくあるのが、nodejsで建てたサーバーにクライアントから画像データを送るという記事。

しかし、私はnodejsをうごかしているパソコンにつながったカメラの映像を取得したいのです。

しかし、なかなか最適な答えにたどり着けなかったので、記事にまとめておきます。

手法

プログラムからカメラの画像を取得するといえば、やはりopenCVでしょう。

opencv3をサポートしているopencv4nodejsを使用します。

早速npmからインストール

npm install --save opencv4nodejs

これだけで導入完了です。
ただし、インストールにかなり時間がかかるので注意が必要です。

あとは他のモジュール同様、

const cv = require('opencv4nodejs');

すれば使用できます。

最後に

カメラ画像の取得の仕方と題しておきながら、本質情報がコード2行という記事になってしまいましたが、お許しください。

それでは、楽しいNodejsライフを!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

fetchの呼び出し @Javascript & Node.js 実験室

fetchは、HTTP呼び出しで標準的に使っていますが、Content-Typeに従った呼び出し方をいつも忘れてしまうので、備忘録として残しておきます。

実動作の確認のためのソースコードを以下のGitHubに上げておきました。
 https://github.com/poruruba/fetch_laboratory

Javascriptからの呼び出しを中心に示しますが、同じコードがそのままNode.jsでも動作します。
ちょっとだけ、Lambdaでの動作も示しておきます。

呼び出し方法の種類

今回扱う呼び出し方法は以下の通りです。

・Get呼び出し
 HTMLのページ取得でおなじみです。パラメータをQueryStringに指定します。例えば、以下のような呼び出しです。
 http://localhost:10080/api?param1=abcd

・Post(Content-Type: application/json)呼び出し
 パラメータをBody部にJSONで指定するWebAPI呼び出しでは一番一般的ですね。

・Post(Content-Type: application/x-www-form-urlencoded)呼び出し
 フォームでSumitするときの方法です。例えば、以下のような呼び出しです。
 <form action="http://localhost:10080/post-urlencoded" method="post">

・Post(Content-Type: multipart/form-data)呼び出し
 フォームでmultipart指定でSumitするときの方法です。例えば、以下のような呼び出しです。
 <form action="http://localhost:10080/post-formdata" method="post" enctype="multipart/form-data">

Javascriptの場合

まずは、Javascriptから。

Post(Content-Type: application/json)呼び出し

function do_post(url, body) {
  const headers = new Headers({ "Content-Type": "application/json; charset=utf-8" });

  return fetch(new URL(url).toString(), {
      method: 'POST',
      body: JSON.stringify(body),
      headers: headers
    })
    .then((response) => {
      if (!response.ok)
        throw 'status is not 200';
      return response.json();
    });
}

Javascriptから送信
image.png

Post(Content-Type: application/x-www-form-urlencoded)呼び出し

function do_post_urlencoded(url, params) {
  const headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
  var body = new URLSearchParams(params);

  return fetch(new URL(url).toString(), {
      method: 'POST',
      body: body,
      headers: headers
    })
    .then((response) => {
      if (!response.ok)
        throw 'status is not 200';
      return response.json();
    })
}

フォームから送信した場合
image.png

Javascriptから送信した場合
image.png

Post(Content-Type: multipart/form-data)呼び出し

function do_post_formdata(url, params){
    var body = Object.entries(params).reduce( (l, [k,v])=> { l.append(k, v); return l; }, new FormData());

  return fetch(new URL(url).toString(), {
      method : 'POST',
      body: body,
  })
  .then((response) => {
    if( !response.ok )
      throw 'status is not 200';
    return response.json();
  });
}

フォームから送信した場合
image.png

Javascriptから送信した場合
image.png

GET呼び出し

function do_get(url, qs) {
  var params = new URLSearchParams(qs);
  var url2 = new URL(url);
  url2.search = params;

  return fetch(url2.toString(), {
      method: 'GET',
    })
    .then((response) => {
      if (!response.ok)
        throw 'status is not 200';
      return response.json();
    });
}

フォームから送信した場合
image.png

Javascriptから送信した場合
image.png

Node.jsの場合

Node.jsでも呼び出し方は同じです。
ポイントは、以下のnpmモジュールを利用するところです。

・node-fetch
 https://github.com/node-fetch/node-fetch
・form-data
 https://github.com/form-data/form-data

以下を先頭に記述することで、ほぼJavascriptと同じ記述で同じ動作となります。

const FormData = require('form-data');
const { URL, URLSearchParams } = require('url');
const fetch = require('node-fetch');
const Headers = fetch.Headers;

実験のためのサンプルページ

以下のようなページから、各呼び出し方法を確認します。
F11を押して、DevToolsを開くと、通信内容を詳しく見ることができます。

image.png

先ほど示した関数群を呼び出しているだけでして、詳細はGitHubのソースコードを参照ください。
参考までに、リクエストを受け付けるサーバ側のソースも示しておきます。

index.js
'use strict';

const HELPER_BASE = process.env.HELPER_BASE || '../../helpers/';
const Response = require(HELPER_BASE + 'response');
const Redirect = require(HELPER_BASE + 'redirect');

// Lambda+API Gatewayの場合に必要
//const { URLSearchParams } = require('url');
//const multipart = require('aws-lambda-multipart-parser');

exports.handler = async (event, context, callback) => {
  if( event.path == '/post-json'){
    console.log(event.body);

    var body = JSON.parse(event.body);
    var response = {
      path : event.path,
      param: {
        param1: body.param1,
        param2: body.param2,
      }
    };
    return new Response(response);
  }else
  if( event.path == '/post-urlencoded'){
    // Lambda+API Gatewayの場合はこちら
    //var body = {};
    //for( var pair of new URLSearchParams(event.body).entries() ) body[pair[0]] = pair[1];
    // swagger_nodeの場合はこちら
    var body = JSON.parse(event.body);

    var response = {
      path : event.path,
      param: {
        param1: body.param1,
        param2: body.param2,
      }
    };
    return new Response(response);
  }else
  if( event.path == '/post-formdata' ){
    // Lambda+API Gatewayの場合はこちら
    //var body = multipart.parse(event);
    // swagger_nodeの場合はこちら
    var body = JSON.parse(event.body);

    console.log(body);
    var response = {
      path : event.path,
      param: {
        param1: body.param1,
        param2: body.param2,
      }
    };
    return new Response(response);
  }else
  if( event.path == '/get-qs'){
    console.log(event.queryStringParameters);

    var response = {
      path : event.path,
      param: {
        param1: event.queryStringParameters.param1,
        param2: event.queryStringParameters.param2,
      }
    };
    return new Response(response);
  }
};

一方で、Node.jsでの呼び出しも確認したかったので、Node.js側の確認のためのソースも示しておきます。
動作としては、いったん、サーバ側でリクエストを受け付けたのち、パラメータで指定されたbody.typeの値によって、各呼び出し方法に従った呼び出しをNode.jsで行っています。
コードを見ていただくと、Javascriptでの呼び出しと同じであることがわかります。

'use strict';

const HELPER_BASE = process.env.HELPER_BASE || '../../helpers/';
const Response = require(HELPER_BASE + 'response');
const Redirect = require(HELPER_BASE + 'redirect');

const FormData = require('form-data');
const fetch = require('node-fetch');
const { URL, URLSearchParams } = require('url');
const Headers = fetch.Headers;

const baseurl = 'http://localhost:10080';

exports.handler = async (event, context, callback) => {
  if( event.path == '/node'){
    console.log(event.body);

    var body = JSON.parse(event.body);
    if( body.type == "post-json"){
      var params = {
        param1: body.param1,
        param2: body.param2,
      };
      return do_post(baseurl + '/post-json', params)
        .then(json => {
          console.log(json);
          return new Response({ type: body.type, resposne: json });
        })
        .catch(error => {
          console.log(error);
          return new Response(error);
        });
    }else
    if( body.type == "post-urlencoded"){
      var params = {
        param1: body.param1,
        param2: body.param2,
      };
      return do_post_urlencoded(baseurl + '/post-urlencoded', params)
        .then(json => {
          console.log(json);
          return new Response({ type: body.type, resposne: json });
        })
        .catch(error => {
          console.log(error);
          return new Response(error);
        });
    }else
    if( body.type == "post-formdata"){
      var params = {
        param1: body.param1,
        param2: body.param2,
      };
      return do_post_formdata(baseurl + '/post-formdata', params)
        .then(json => {
          console.log(json);
          return new Response({ type: body.type, resposne: json });
        })
        .catch(error => {
          console.log(error);
          return new Response(error);
        });
    }else
    if( body.type == 'get-qs'){
      var qs = {
        param1: body.param1,
        param2: body.param2,
      }
      return do_get(baseurl + '/get-qs', qs)
        .then(json => {
          console.log(json);
          return new Response({ type: body.type, resposne: json });
        })
        .catch(error => {
          console.log(error);
          return new Response(error);
        });
    }

    var response = {
      type : body.type,
      param: {
        param1: body.param1,
        param2: body.param2,
      }
    };
    return new Response(response);
  }
};


function do_post(url, body) {
  const headers = new Headers({ "Content-Type": "application/json; charset=utf-8" });

  return fetch(new URL(url).toString(), {
      method: 'POST',
      body: JSON.stringify(body),
      headers: headers
    })
    .then((response) => {
      if (!response.ok)
        throw 'status is not 200';
      return response.json();
    });
}

function do_get(url, qs) {
  var params = new URLSearchParams(qs);
  var url2 = new URL(url);
  url2.search = params;

  return fetch(url2.toString(), {
      method: 'GET',
    })
    .then((response) => {
      if (!response.ok)
        throw 'status is not 200';
      return response.json();
    });
}

function do_post_urlencoded(url, params) {
  const headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
  var body = new URLSearchParams(params);

  return fetch(new URL(url).toString(), {
      method: 'POST',
      body: body,
      headers: headers
    })
    .then((response) => {
      if (!response.ok)
        throw 'status is not 200';
      return response.json();
    })
}

function do_post_formdata(url, params) {
  var body = Object.entries(params).reduce((l, [k, v]) => {
    l.append(k, v);
    return l;
  }, new FormData());

  return fetch(new URL(url).toString(), {
      method: 'POST',
      body: body,
    })
    .then((response) => {
      if (!response.ok)
        throw 'status is not 200';
      return response.json();
    });
}

補足

※レスポンスの型
最近レスポンスはJSONで返されることが多くなっていますので、すべてJSONで返ってくることを想定しています。もし、単なるテキストで返ってくる場合には以下の部分を変更します。


(変更前) return response.json();

(変更後) return response.text();

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初学者向け】Herokuデプロイ時 code=H10 エラー解消

構築時に以下事象にて20分程はまってしまったので、備忘含め投稿します。

デプロイ時のエラー内容

#gitにコミットしたソースをHerokuへデプロイ
git push heroku master
#####アプリケーションエラー発生#####

#Herokuのエラーログを確認
heroku logs --tail

エラーログ

at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=XXXXX.herokuapp.com request_id=11089354-f9b9-4f65-a85f-c4969a772d76 fwd="XXX.XXX.XXX.XXX" dyno= connect= service= status=503 bytes= protocol=https
2020-01-11T17:36:56.788077+00:00 herok

結論

Package.jsonの記載誤り。

Package.json
{
  "name": "testheroku",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "start": "node index.js", ←ここに書かない
  "scripts": {
    "start": "node index.js", ←ここに書く
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "engines": {
    "node": "13.5.0",
    "npm": "6.13.6"
  }
}

お作法を色々と覚えていきたいものです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ネットのない環境でWEBの実機テストをする

発端

筆者はよく行きつけのカフェでイキりながらWEB開発をしております。

ところが困ったことに、カフェなどで設置されている公共Wifiでは、ルーターの設定で他機の存在が秘匿にされている場合があります。(当然pingも打てない)

セキュリティの観点から妥当な処置ではあるのですが、開発しているWEBサイトをスマホで確認したい・・・といった場合には困ったことになります。

一つの解決策として、パソコン自体をルーターにして独自のLANを構築する、というものがあります。

Windowsでは7から標準でSoftAPという機能が用意されており、Microsoftが提供している仮想ネットワークアダプタを利用してパソコン単体でLANを構築できます。

今回は、パソコン単体でLANを構築 & Nodeでサーバーを起動、手持ちの端末でLANに接続してサーバーからレスポンスを受け取ることを目標にします。

LANの構築

1 . コマンドプロンプトを管理者権限で起動

2 . 以下のコマンドを実行

C: > netsh
netsh > wlan
netsh wlan > set hostednetwork mode=allow ssid=your_ssid key=your_password

3 . hostednetworkを起動

netsh wlan> start hostednetwork

これでうまくいった人はついてます。
筆者の場合は下記のログが出てLANが構築できませんでした。

netsh wlan> start hostednetwork
ホストされたネットワークを開始できませんでした。
グループまたはリソースは要求した操作の実行に適切な状態ではありません。

主にMicrosoft Hosted Network Virtual Adapterが有効になっていない場合が想定されます。対処法は後ろに載せます。参考に他の記事も載せておくのでそちらもどうぞ。

起動に成功した場合は、LAN内のipアドレスを確認します。

> ipconfing
~~
IPv4 アドレス . . . . . . . . . . . .: 192.168.0.1
~~

サーバーの起動

Nodeでサーバーを起動します。

server.js
const express=require("express");
const app=express()
app.get('/',(req,res)=>{
res.send(`Hello World!`);
});
app.listen(3000);

実機で接続

1 . 端末から、上で設定したSSIDにWifiで接続

2 . ブラウザで IPアドレス + ポート にアクセス
(上の例だと192.168.0.1:3000)

うまくHello Worldできてれば成功 !!

これでパソコンで起動したサーバーと端末を、ネット環境に依存せずに接続させることができました。

LANを構築しているパソコンがネットに接続できている場合は、端末がネット上のリソースを要求してもきちっと返してくれます。(というかまんまプロキシなので)

当然ネット環境がないとインターネット上のリソースが必要になるような処理は無理です。

しかし序盤で言ったように、他機の存在が秘匿されているようなLANでは、パソコンがプロキシとなって端末と接続できるようになる、という意味で有用な場面もあるのではないでしょうか。

(追記)Microsoft Hosted Network Virtual Adapterのインストール

SoftAPではMicrosoftが提供しているMicrosoft Hosted Network Virtual Adapterというネットワークアダプタを利用しています。こちらを用意してあげる必要があります。

1 . 下のコマンドを実行し、ドライバー名を確認する。

netsh wlan> show drivers

2 . デバイスマネージャーを起動し、ネットワークアダプターの欄の中にある、1で確認したドライバー名を右クリック

3 . ドライバーの更新を選択し、コンピューターを参照してドライバーソフトウェアを検索を選択。

4 . コンピューター上の利用可能なドライバーの一覧から選択しますを選択。

5 . Microsoftのモデルを選択して※次へ、ドライバーをインストールする。
※筆者の場合は同名のモデルがいくつもでて、順に更新していったら成功しました。

6 . デバイスマネージャーのメニューバーにある表示タブで、非表示のデバイスの表示を選択。ネットワークアダプターの欄にあるであろうMicrosoft Hosted Network Virtual Adapterを有効にする。

これでhostednetworkが起動できるはずです。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.js module管理の仕組み

Node.jsデザインパターンを読んで勉強中なので
そちらの備忘録として投稿していきます。

まず初めにNode.jsがどうやって異なるバージョンの同一モジュールを管理し、
「依存地獄(dependency hell)」を回避しているかを整理します。

Node.jsの依存解決アルゴリズム

Node.jsがモジュールを読み込む時に
指定されたモジュール名をもとにモジュールをコアモジュール、もしくはローカルファイル
から探すために使用されるアルゴリズムは
以下の三段階に分かれている。

  1. コアモジュール
    まずは指定されたモジュール名がNodeのコアモジュールかどうか調べる

  2. ファイルモジュール
    コアモジュールに見つからなかった場合、ローカルファイルシステムを探す。
    モジュール名が「/」で始まる場合は絶対パスとして、「./」、「../」で始まる場合は
    requireを呼び出しているファイ ルからの相対パスとして解釈される。

  3. パッケージモジュール
    モジュール名の開始文字列が「/」、「./」、「../」のいずれでもない場合は、
    requireを呼び出しているファイルと同じディレクトリの下にあるnode_modulesディレクトリの中を探す。

それでも見つからない、もしくはnode_modulesディレクトリがなかった場合
さらに親のディレクトリを探しにいき、上へ上へ探索していき
ローカルファイルシステムのルートに到達するまで探す。

ファイルモジュールとパッケージモジュールのロード時のルール

ファイルモジュールとパッケージモジュールのロード時には
上記のアルゴリズム以外にルールがある。

  • 指定されたモジュール名と同じ名前のファイルがあれば (なければ拡張子.jsもしくは.jsonを補完して確認) そのファイルをロードする。
  • 指定されたモジュール名と同じ名前のディレクトリがあれば、その配下にpackage.jsonファイルがないか調べる。 存在すれば、ファイル中のmainプロパティで指定されたファイルをロードする。
  • 指定されたモジュール名ディレクトリ配下にindex.jsというファイルがあればロードする。

整理

myApp/
├── foo.js
└─┬ node_modules
├── depA
|└── index.js
├── depB
├── bar.js
└── node_modules
└── depA
└── index.js
└── depC
├── foobar.js
└── node_modules
└── depA
└── index.js
上記のようなディレクトリ構成として
各ファイルからモジュールdepAをロードしてみる。

  • /myApp/foo.jsからrequire('depA')を呼び出した場合
    /myApp/node_modules/depA/index.jsをロードする

  • /myApp/node_modules/depB/bar.jsからrequire('depA')を呼び出した場合
    /myApp/node_modules/depB/node_modules/depA/index.jsをロードする

  • /myApp/node_modules/depC/foobar.jsからrequire('depA')を呼び出した場合
    /myApp/node_modules/depC/node_modules/depA/index.jsをロードする

まとめ

依存解決アルゴリズムにより、Nodeは複雑な依存関係も解決でき、
ひいては大規模なアプリケーションにおいて、
バージョン間の衝突なく何百、何千といった依存パッケージをもつことが可能になる

参考書籍
Node.jsデザインパターン 第2版

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

nodebrewからnodenv(on anyenv)に切り替える(2019年1月版)+ありがちなトラブル

動機

nodebrew にて手動でプロジェクト毎にnodeのバージョンを切り替えるのが面倒になったので、.node-version ファイルで自動切り替えできるnodenvで管理しようと思いました。
ひと悶着あり、同じことが起こってる人の役にたつかもしれないので、全体の流れも記録しておくことにしました。その都度、遭遇するかもしれないトラブルシューティングも下のほうに記載しておきましたので、躓いたら見てみてください。

最初の状態

環境

  • Mac
  • ターミナル
  • zsh

nodeのバージョンなど

10系と12系のプロジェクトがあるので、都度切り替えている感じです。

$ node -v

v10.16.3
$ which node

/usr/local/bin/nodebrew

その他にインストールされていたnodeのバージョン

$ nodebrew ls  

v9.11.2
v10.16.3
v12.10.0
v12.12.0

npmのバージョンなど

$ npm -v

6.13.0
$ which npm

/Users/user-name/.nodebrew/current/bin/npm

nodebrewを消す

nodebrewがインストールされている状態だとバッティングの可能性があるようなので、思い切って削除します。
-rf つけてる rm は慎重に。

$ rm -rf ~/.nodebrew

ばっさり

.bash_profile で通しているパスを削除しておく必要があるらしい。

$ vi ~/.bash_profile

↓のようなのを消しておきましょう

export PATH=/Users/user-name/.nodebrew/current/bin:$PATH

確認する。これでエラーが返ってきたらばっちりのはず…

$ node -v

/usr/local/bin/node

おっと…?

とりあえずanyenv -> nodenvをインストールしてみる

Homebrewで可能でした

$ brew install anyenv

からの。
初期化?

$ anyenv init

# Load anyenv automatically by adding
# the following to ~/.zshrc:

eval "$(anyenv init -)"

.zshrc ファイルに記述が必要らしいので。

$ vi ~/.zshrc

まだファイルがなかった場合は下記の1行だけを置いておく形に。

eval "$(anyenv init -)"

viじゃなくても大丈夫だし、環境によっては .bashrc とかに記述の必要があるかも。

どこかに書かれていたけど、以下も必要なのかな?

$ anyenv install --init

とりあえず都度シェルをきれいに。

$ exec $SHELL -l 

本題の nodenv のインストール。 anyenv 経由でできるらしい。

$ anyenv install nodenv

(前略)
Install nodenv succeeded!
Please reload your profile (exec $SHELL -l) or open a new session.

おけ。指示通りターミナルを初期化して、今の状態を確認してみる。

$ exec $SHELL -l
$ nodenv versions

* system => v12.12.0 (set by /Users/user-name/.anyenv/envs/nodenv/version)

おぉ?まだ nodenv でnodeをインストールしてないけど…まぁええんか?

以前の状態に合わせるために古いnodeもインストール

$ nodenv install 10.16.3

nodenv versions        
* system => v12.12.0 (set by /Users/user-name/.anyenv/envs/nodenv/version)
  10.16.3

ちゃんと入ったっぽい。

マシンを3年も使っていると色々と溜め込んだものがありまして

手動で切り替えてみよう

$ nodenv global 10.16.3

(略)

$ node -v     

v12.12.0

あかん。なんでや?

どこのnodeを使っているか場所を確認。

$ which node

/Users/user-name/.nodebrew/current/bin/node

ゾンビnode発見。
もういないはずの、 nodebrew の文字が…

確認。

$ nodebrew

zsh: command not found: nodebrew

やはりゾンビ。
さよならだ。(正直謎…)

$ rm -rf /Users/user-name/.nodebrew

気を取り直して

$ node -v

v13.2.0

HAHAHA、冗談はやめてくれYO

$ which node

/usr/local/bin/node

地縛霊発見。

sudo rm -rf /usr/local/bin/node

お祓い完了。

node -v

zsh: command not found: node

ほぅ…

(少しやけくそ目に)

$ anyenv install nodenv

$ nodenv versions

* 10.16.3 (set by /Users/user-name/.anyenv/envs/nodenv/version)

$ node -v

zsh: command not found: node

おこ。




あ。もしや。

$ exec $SHELL -l
$ node -v

v10.16.3

いえーす。

いつから(ry

$ npm -v

6.13.1

$ which npm

/usr/local/bin/npm

お前もか

$ brew uninstall --ignore-dependencies npm

Uninstalling /usr/local/Cellar/node/13.2.0... (4,654 files, 58.8MB)
node 12.12.0 is still installed.
Run `brew uninstall --force node` to remove all versions.

$ node -v
v12.12.0

$ npm -v
6.13.1

$ which npm
/usr/local/bin/npm

お祓いがきかないぃ(まぁアンインストールされるバージョンも変なの出てるんですけどね…)
おこ。そろそろ慣れてきたけど。

$ which npm

/usr/local/bin/npm

$ rm -rf /usr/local/bin/npm
$ npm -v                   
6.11.3

$ which npm

/Users/user-name/.anyenv/envs/nodenv/shims/npm

(ファンファーレが頭の中で鳴り響く)

特定のバージョンのnpmが欲しかったので。

$ npm install -g npm@6.13.0

こうしておいて、手動でのnodeバージョンを切り替えてnpmもついてくるかテスト

$ nodenv global 12.12.0
$ node -v
v12.12.0

$ npm -v
6.13.0

$ nodenv global 10.16.3
$ node -v
v10.16.3

$ npm -v
6.9.0

できた

やっと本題の、 .node-versionでのローカルの管理

npmにしろnodeを用いる際にnode自体のバージョンによってエラーなどの原因になることがしばしばあります。nodebrewでの管理でプロジェクトごとにこの辺りの事情が異なる場合、プロジェクトをはしごする際に手動でのnodeの切り替えが必要になったりします。
nodenvはコマンドを実行するディレクトリに .node-version ファイルがあるとそのファイル内で指定されているバージョンのnodeを用いて各種コマンドを実行してくれるので、切り替えを意識することがなくなります。

といってもファイルを自分で書く必要はない

$ cd /path/to/project/root
$ nodenv local 12.12.0

これでそのディレクトリに .node-version ファイルを生成してくれ、次回以降このディレクトリ内での作業時には自動的にnodeのバージョンが切り替わります。

.gitignore_global でignoreしておく

プロジェクトで固定、かつ、チームメンバーが nodenv を使っている前提であれば、プロジェクトのルートに .node-version ファイルをコミットしておいて、共有しておくのはとてもいいソリューションだと思いますが、諸々の事情でコミットできない場合もあると思います。そういう場合には、そのマシン全体でgitignoreできる .gitignore_global を使うのもひとつの手です。

$ cd ~
$ vi .gitignore_global

ただし、その後、他のプロジェクトで .node-version を使うとなった際にgitに入ってこなくなるので注意が必要です。

おかしい時のチェック

とりあえずバージョンは逐一確認してみる

node -v

インストールされている場所も確認しておく

which node

例えば、↓こういうのが表示されるのはMacのデフォルトのnodeを使っている状態なので、 nodebrew にしろ nodenv にしろが動作している前提だとしたら、間違っている可能性が高いです。

/usr/local/bin/node

こういう場合、nodenvなどのセットアップが適切にできればそちらが使われますし、最悪この元の場所にインストールすることもできますから、消しちゃって大丈夫です。

コマンドがみつからない系

* : command no found

とりあえず、下記でターミナルを再読み込みしてみたり、なんなら再起動してみましょう。割とそれで解決することが多いはず。

exec $SHELL -l

それでもダメな場合は所謂「パスが通っていない」可能性もあるので、インストール時に表示されていた内容を見直してみたり、再インストールする必要があるかもしれません。
install complete的なメッセージが出ていても、もうひと手順あることが意外とあります。

まとめ

やはり先にnodeを全部消すのがよいです。変に保険をかけずnode -vでなにも出なくなるようにするのを優先した方が早かったと思います。(もしかするとnpm -vも。)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

nodebrewからnodenv(on anyenv)に切り替える(2020年1月版)+ありがちなトラブル

動機

nodebrew にて手動でプロジェクト毎にnodeのバージョンを切り替えるのが面倒になったので、.node-version ファイルで自動切り替えできるnodenvで管理しようと思いました。
ひと悶着あり、同じことが起こってる人の役にたつかもしれないので、全体の流れも記録しておくことにしました。その都度、遭遇するかもしれないトラブルシューティングも下のほうに記載しておきましたので、躓いたら見てみてください。

最初の状態

環境

  • Mac
  • ターミナル
  • zsh

nodeのバージョンなど

10系と12系のプロジェクトがあるので、都度切り替えている感じです。

$ node -v

v10.16.3
$ which node

/usr/local/bin/nodebrew

その他にインストールされていたnodeのバージョン

$ nodebrew ls  

v9.11.2
v10.16.3
v12.10.0
v12.12.0

npmのバージョンなど

$ npm -v

6.13.0
$ which npm

/Users/user-name/.nodebrew/current/bin/npm

nodebrewを消す

nodebrewがインストールされている状態だとバッティングの可能性があるようなので、思い切って削除します。
-rf つけてる rm は慎重に。

$ rm -rf ~/.nodebrew

ばっさり

.bash_profile で通しているパスを削除しておく必要があるらしい。

$ vi ~/.bash_profile

↓のようなのを消しておきましょう

export PATH=/Users/user-name/.nodebrew/current/bin:$PATH

確認する。これでエラーが返ってきたらばっちりのはず…

$ node -v

/usr/local/bin/node

おっと…?

とりあえずanyenv -> nodenvをインストールしてみる

Homebrewで可能でした

$ brew install anyenv

からの。
初期化?

$ anyenv init

# Load anyenv automatically by adding
# the following to ~/.zshrc:

eval "$(anyenv init -)"

.zshrc ファイルに記述が必要らしいので。

$ vi ~/.zshrc

まだファイルがなかった場合は下記の1行だけを置いておく形に。

eval "$(anyenv init -)"

viじゃなくても大丈夫だし、環境によっては .bashrc とかに記述の必要があるかも。

どこかに書かれていたけど、以下も必要なのかな?

$ anyenv install --init

とりあえず都度シェルをきれいに。

$ exec $SHELL -l 

本題の nodenv のインストール。 anyenv 経由でできるらしい。

$ anyenv install nodenv

(前略)
Install nodenv succeeded!
Please reload your profile (exec $SHELL -l) or open a new session.

おけ。指示通りターミナルを初期化して、今の状態を確認してみる。

$ exec $SHELL -l
$ nodenv versions

* system => v12.12.0 (set by /Users/user-name/.anyenv/envs/nodenv/version)

おぉ?まだ nodenv でnodeをインストールしてないけど…まぁええんか?

以前の状態に合わせるために古いnodeもインストール

$ nodenv install 10.16.3

nodenv versions        
* system => v12.12.0 (set by /Users/user-name/.anyenv/envs/nodenv/version)
  10.16.3

ちゃんと入ったっぽい。

マシンを3年も使っていると色々と溜め込んだものがありまして

手動で切り替えてみよう

$ nodenv global 10.16.3

(略)

$ node -v     

v12.12.0

あかん。なんでや?

どこのnodeを使っているか場所を確認。

$ which node

/Users/user-name/.nodebrew/current/bin/node

ゾンビnode発見。
もういないはずの、 nodebrew の文字が…

確認。

$ nodebrew

zsh: command not found: nodebrew

やはりゾンビ。
さよならだ。(正直謎…)

$ rm -rf /Users/user-name/.nodebrew

気を取り直して

$ node -v

v13.2.0

HAHAHA、冗談はやめてくれYO

$ which node

/usr/local/bin/node

地縛霊発見。

sudo rm -rf /usr/local/bin/node

お祓い完了。

node -v

zsh: command not found: node

ほぅ…

(少しやけくそ目に)

$ anyenv install nodenv

$ nodenv versions

* 10.16.3 (set by /Users/user-name/.anyenv/envs/nodenv/version)

$ node -v

zsh: command not found: node

おこ。




あ。もしや。

$ exec $SHELL -l
$ node -v

v10.16.3

いえーす。

いつから(ry

$ npm -v

6.13.1

$ which npm

/usr/local/bin/npm

お前もか

$ brew uninstall --ignore-dependencies npm

Uninstalling /usr/local/Cellar/node/13.2.0... (4,654 files, 58.8MB)
node 12.12.0 is still installed.
Run `brew uninstall --force node` to remove all versions.

$ node -v
v12.12.0

$ npm -v
6.13.1

$ which npm
/usr/local/bin/npm

お祓いがきかないぃ(まぁアンインストールされるバージョンも変なの出てるんですけどね…)
おこ。そろそろ慣れてきたけど。

$ which npm

/usr/local/bin/npm

$ rm -rf /usr/local/bin/npm
$ npm -v                   
6.11.3

$ which npm

/Users/user-name/.anyenv/envs/nodenv/shims/npm

(ファンファーレが頭の中で鳴り響く)

特定のバージョンのnpmが欲しかったので。

$ npm install -g npm@6.13.0

こうしておいて、手動でのnodeバージョンを切り替えてnpmもついてくるかテスト

$ nodenv global 12.12.0
$ node -v
v12.12.0

$ npm -v
6.13.0

$ nodenv global 10.16.3
$ node -v
v10.16.3

$ npm -v
6.9.0

できた

やっと本題の、 .node-versionでのローカルの管理

npmにしろnodeを用いる際にnode自体のバージョンによってエラーなどの原因になることがしばしばあります。nodebrewでの管理でプロジェクトごとにこの辺りの事情が異なる場合、プロジェクトをはしごする際に手動でのnodeの切り替えが必要になったりします。
nodenvはコマンドを実行するディレクトリに .node-version ファイルがあるとそのファイル内で指定されているバージョンのnodeを用いて各種コマンドを実行してくれるので、切り替えを意識することがなくなります。

といってもファイルを自分で書く必要はない

$ cd /path/to/project/root
$ nodenv local 12.12.0

これでそのディレクトリに .node-version ファイルを生成してくれ、次回以降このディレクトリ内での作業時には自動的にnodeのバージョンが切り替わります。

.gitignore_global でignoreしておく

プロジェクトで固定、かつ、チームメンバーが nodenv を使っている前提であれば、プロジェクトのルートに .node-version ファイルをコミットしておいて、共有しておくのはとてもいいソリューションだと思いますが、諸々の事情でコミットできない場合もあると思います。そういう場合には、そのマシン全体でgitignoreできる .gitignore_global を使うのもひとつの手です。

$ cd ~
$ vi .gitignore_global

ただし、その後、他のプロジェクトで .node-version を使うとなった際にgitに入ってこなくなるので注意が必要です。

おかしい時のチェック

とりあえずバージョンは逐一確認してみる

node -v

インストールされている場所も確認しておく

which node

例えば、↓こういうのが表示されるのはMacのデフォルトのnodeを使っている状態なので、 nodebrew にしろ nodenv にしろが動作している前提だとしたら、間違っている可能性が高いです。

/usr/local/bin/node

こういう場合、nodenvなどのセットアップが適切にできればそちらが使われますし、最悪この元の場所にインストールすることもできますから、消しちゃって大丈夫です。

コマンドがみつからない系

* : command no found

とりあえず、下記でターミナルを再読み込みしてみたり、なんなら再起動してみましょう。割とそれで解決することが多いはず。

exec $SHELL -l

それでもダメな場合は所謂「パスが通っていない」可能性もあるので、インストール時に表示されていた内容を見直してみたり、再インストールする必要があるかもしれません。
install complete的なメッセージが出ていても、もうひと手順あることが意外とあります。

まとめ

やはり先にnodeを全部消すのがよいです。変に保険をかけずnode -vでなにも出なくなるようにするのを優先した方が早かったと思います。(もしかするとnpm -vも。)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

node 10 -> 12 バージョンアップしたら、npm installでnode-sass@4.11.0はエラーになる

Unsupported for node-sass@4.11.0

2019年10月に、node v12はついLTSになりました:clap::clap::clap:

それで、既存のシステムのnodeをバージョンアップしたら、↓のようなエラーになりました!

    Cannot download "https://github.com/sass/node-sass/releases/download/v4.11.0/linux_musl-x64-72_binding.node":

    HTTP error 404 Not Found

    Hint: If github.com is not accessible in your location
          try setting a proxy via HTTP_PROXY, e.g.

          export HTTP_PROXY=http://example.com:1234

    or configure npm proxy via

          npm config set proxy http://example.com:8080

v12はサポートしなくなったらしいので、node-sass@4.12.0にアップデートする必要があります。

npm install node-sass@4.12.0

これでエラーが消えます。

node v12 はどこが新しくなったのか

  • JavaScriptエンジンであるV8はNode.js v10のv6.8からv12のv7.4にバージョンアップした、そのためパフォーマンスは大きく変わりました

    • Asyncスタックトレース
    • JavaScriptパース高速化
    • Await高速化
    • 引数ミスマッチ高速化
  • ClassにPrivateFields定義できる
    #でプライベートフィールドを定義する。(例:#name
    この#nameはClass内にしか使えない。

  • HTTP parserはllhttpに変わりました

  • TLS1.3もサポートするようになった

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む