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

Node.js, npm, nの整理とアンインストール

はじめに

Node.jsのバージョン管理方法は数多く存在し、さらに情報も散乱しているため非常に混乱します。

インタラクティブにNode.jsのバージョンを管理するnpmパッケージ「n」を使っていましたが、
プロジェクト(ディレクトリ)ごとにバージョンを切り替え可能な「Nodenv」へ移行する際、
nのアンインストールでちょっとハマったため調べました。

ついでに、aptで入れたNode.js, npmと、nの関係もよく分かっていなかったため、順序だてて整理していきます。

本記事で得られる知識

  • 「aptで入れたNode.js, npm」と、「npmで入れたn」と、「nで入れたNode.js, npm」の関係
  • パッケージnの正しいアンインストール方法

あると嬉しい知識

  • Docker (綺麗な環境での検証目的に使うため、Dockerを使わなくても本記事はローカルマシンで再現可能です)
  • Ubuntu(本記事はUbuntuを前提としています)

結論

以下のコマンドに従えば、nを完全にアンインストールできます。
(注意)Ubuntu 16.04での実行例です。

# nの削除の準備(「nで入れたnodeとnpm」へのシンボリックリンクが削除されます)
# n uninstall

# nodeの削除(「nで入れたnode」の実体が削除されます)
# rm -rf /usr/local/n

# 「aptで入れたnpm」によるnのアンインストール
# npm uninstall -g n

0. 関係性の整理

検証に入る前に、まずはNode.js, npm, nの関係を整理します。
nを使ってNode.jsのバージョンを管理する場合、以下のような手順になります。

  1. aptでNode.jsnpmをインストール
  2. npmでパッケージnをインストール
  3. パッケージnNode.jsnpmを複数インストールしバージョン管理

つまり、「aptで入れたNode.js, npm」と、「nで入れたNode.js,npm」が共存する形になります。
ただし、nによりNode.jsを入れた時点で、bashのコマンドは「nで入れた方のNode.js,npm」へ向くためnでのバージョンの管理が可能となります。
以下のような構造ですね。

  1. aptで入れたNode.jsnpm(<-使われない)
  2. aptで入れたnpmで入れたパッケージn
  3. パッケージnで入れたNode.jsnpm(<-bashではこれを使う)

これを前提として、nをアンインストールする際に以下の問題が発生します。

nのアンインストール時に発生する問題

nをアンインストールする際、「nでインストールしたNode.js, npm」が残ってしまいます。
構造を可視化すると、以下のようになります。

  1. aptで入れたNode.jsnpm(存在する)
  2. aptで入れたnpmで入れたパッケージn(削除済み)
  3. パッケージnで入れたNode.jsnpm(存在する。bashはこれを使う)

つまり、nを削除しても、3の「nで入れたNode.jsnpm」は依然存在するため、
1のNode.jsを使いたいときや、Nodenvなど他のパッケージマネージャを使いたい場合に、
3のnで入れたNode.jsを見に行ってしまうという不具合が起きてしまいます。

解決策

最近までは、「nで入れたNode.jsnpm」を手動で消す必要がありました。
https://stackoverflow.com/questions/49648514/how-to-uninstall-n-and-all-node-versions-installed-by-n

しかし、v4.1.0からn uninstallコマンドが追加されたようです(リリースは2019/5/10ですね)。
https://github.com/tj/n/releases/tag/v4.1.0
nのGithubのREADMEにも、このコマンドが記載されています。

さらにn uninstallコマンドは、シンボリックリンクのみを削除するため、nからインストールしたNode.jsのキャッシュは削除しません。
これは、nをアンインストールすること無く、一時的に「aptで入れたNode.js」を使い、しかる後に再び「nで入れたNode.js」を使うなどの運用が可能になります(需要があるかは分かりませんが)。

ただしその反面、nを完全にアンインストールするには、手動での削除が必ず必要になってしまうことを意味します。
以下で、それを見ていきます。

1. aptによるNode.js, npmのインストール

以下、再現性を担保するためにDockerを使います。
ですが、別にDockerを使わずにローカルでやっても構いません。

以下のように、ubuntu:16.04イメージを使ってコンテを起動します。
(基本的にDocker内ではrootユーザでコマンドを打ちますので、rootユーザでない方は必要に応じてsudo su -でrootユーザになるか、コマンドの頭にsudoをつけてください。)

まず、コンテナを起動します。イメージがない場合は勝手にpullしてくれます

$ docker run -it ubuntu:16.04 /bin/bash

ここからコンテナ内での操作です。
まず、念の為環境をチェック。

# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.6 LTS"

以下で、Node.jsとnpmをインストールします。
明示的にapt install nodejsしても良いですが、npmを入れると、nodejsも自動でインストールされます。そこはお好みで。

# apt update
# apt upgrade -y
# apt install curl npm -y

以下でインストールを確認できます。

# nodejs -v
v4.2.6

# npm -v
3.5.2

場所も確認しておきましょう。

# which nodejs
/usr/bin/nodejs

# which npm
/usr/bin/npm

# ls -lF /usr/bin/ | grep -e node -e npm
-rwxr-xr-x 1 root root        943 Aug  9  2018 dh_nodejs*
lrwxrwxrwx 1 root root         33 Dec  7  2015 node-gyp -> ../share/node-gyp/bin/node-gyp.js*
-rwxr-xr-x 1 root root   11187096 Aug  9  2018 nodejs*
lrwxrwxrwx 1 root root         27 Dec  8  2015 npm -> ../share/npm/bin/npm-cli.js*
lrwxrwxrwx 1 root root         27 Oct 25  2014 rimraf -> ../lib/nodejs/rimraf/bin.js*
lrwxrwxrwx 1 root root         31 Aug 25  2013 semver -> ../lib/nodejs/semver/bin/semver*

なるほど。
Node.jsの実行ファイルと、npmの実行ファイルへのシンボリックリンクは/usr/bin/にあることが確認できました。

2. npmによるパッケージnのインストール

次に、npmを使ってnをグローバルにインストールします。

# npm install n -g
/usr/local/bin/n -> /usr/local/lib/node_modules/n/bin/n
/usr/local/lib
`-- n@5.0.1

出力を見れば、nのバージョンと場所はわかるのですが、一応確認をしましょう。

# n --version
5.0.1

# which n
/usr/local/bin/n

# ls -lF /usr/local/bin/
total 0
lrwxrwxrwx 1 root root 27 Jul 27 08:06 n -> ../lib/node_modules/n/bin/n*

n/usr/local/bin/にインストールされたことを確認できました。
ちなみに、この時点でのNode.jsnpmは、

# which nodejs
/usr/bin/nodejs

# which npm
/usr/bin/npm

まだ手順1と同じ場所を指しています。

3. パッケージnによるNode.jsとnpmのインストール

パッケージnを使って、Node.jsを入れてみましょう。
バージョンは何でもいいのですが、とりあえず安定版を入れます。

# n stable

  installing : node-v10.16.0
       mkdir : /usr/local/n/versions/node/10.16.0
       fetch : https://nodejs.org/dist/v10.16.0/node-v10.16.0-linux-x64.tar.gz
   installed : v10.16.0

これも同じく出力で分かるのですが、確認をします。

# which nodejs
/usr/bin/nodejs

# which npm 
/usr/local/bin/npm

# which node
/usr/local/bin/node

ここで、整理をします。
上記nodejsコマンドと、nodeコマンドの間には、以下の関係があります。

  • apt install nodejsでインストールしたNode.jsは、nodejsコマンド
  • nでインストールしたNode.jsは、nodeコマンド

もうワケが分かりません。
私がNode.js関連が理解できていなかった理由は、このあたりの複雑さにあります。

つまり、現時点では、「aptでインストールしたNode.js(=nodejs)」と、「nで入れたNode.js(=node)」が混在している状況です。
(参考)https://stackoverflow.com/questions/48513484/what-is-the-difference-between-node-and-nodejs

nを使ったバージョン管理のブログ記事などで、nをインストールした後にapt purge nodejs npm -yコマンドを使って、「aptで入れたNode.jsnpm」をアンインストールする理由は、ここにあったんですね。

現時点のインストール状況を整理します。
「aptで入れたNode.js (nodejs)npm」は/usr/bin/に配置。

# ls -lF /usr/bin/ | grep -e node -e npm
...
-rwxr-xr-x 1 root root   11187096 Aug  9  2018 nodejs*
lrwxrwxrwx 1 root root         27 Dec  8  2015 npm -> ../share/npm/bin/npm-cli.js*
...
# 

nで入れたNode.js (node)npm」、およびn自身は、/usr/local/bin/に配置。

# ls -lF /usr/local/bin/
total 40152
lrwxrwxrwx 1 root root       27 Jul 27 08:06 n -> ../lib/node_modules/n/bin/n*
-rwxr-xr-x 1 root root 41115408 Jul 27 08:14 node*
lrwxrwxrwx 1 root root       38 Jul 27 08:14 npm -> ../lib/node_modules/npm/bin/npm-cli.js*
lrwxrwxrwx 1 root root       38 Jul 27 08:14 npx -> ../lib/node_modules/npm/bin/npx-cli.js*

ですね。
ここで、Ubuntuにおいてこれら2つのディレクトリの優先度は/usr/local/bin/ > /usr/bin/です。
(参考)https://qiita.com/valzer0/items/67a4c8bf2b1be0fc825a
したがって、両方に存在するnpmは、/usr/local/bin/npm、すなわち「nで入れた方のnpm」が実行されます。

本記事では、あえて「aptで入れた方のNode.js, npm」はアンインストールせず、このまま進みます。

4. パッケージnのアンインストール

nnpmのパッケージの1つであるため、インストール時と同様、npmを用いてアンインストールします。

しかし、上記のように、bashで実行されるnpmは「nで入れた」方です。
上記のnのアンインストール時に発生する問題は、「nで入れた方のnpm」でnをアンインストールしようとするために起こります(と予想しています)。

したがって、これを回避するため、nをアンインストールする際は、以下のコマンドを使って「nで入れたNode.js, npm」を削除します。
とその前に、確認をします。

# バージョンを増やします
# n latest
# n
    node/10.16.0
  ο node/12.7.0

# node -v
v12.7.0

# node自体はここにインストールされています
# ls /usr/local/n/versions/node/
10.16.0  12.7.0

# n, node, npmはここにあります
# ls -lF /usr/local/bin
total 43516
lrwxrwxrwx 1 root root       27 Jul 27 08:06 n -> ../lib/node_modules/n/bin/n*
-rwxr-xr-x 1 root root 44552896 Jul 27 13:09 node*
lrwxrwxrwx 1 root root       38 Jul 27 13:09 npm -> ../lib/node_modules/npm/bin/npm-cli.js*
lrwxrwxrwx 1 root root       38 Jul 27 13:09 npx -> ../lib/node_modules/npm/bin/npx-cli.js*

1つバージョンを増やしています。
各バージョンのnodeの実行ファイルは/usr/local/n/versions/node/にあることを確認できました。

では、nのアンインストールの準備です。

# n uninstall
Do you wish to delete node and npm from /usr/local? yes

Uninstalling node and npm
/usr/local/bin/node
/usr/local/bin/npm
/usr/local/bin/npx
/usr/local/include/node
/usr/local/lib/node_modules/npm
/usr/local/share/doc/node
/usr/local/share/man/man1/node.1
/usr/local/share/systemtap/tapset/node.stp

質問されるので、yやらyesを入れて削除です。
出力の通り、nで管理しているファイルたちが削除されました。

# node -v
bash: /usr/local/bin/node: No such file or directory

# which npm
/usr/bin/npm

nodeコマンドが無効になり、npmコマンドは「aptで入れた方」へ戻っています。
ただし、シンボリックリンクが削除されただけで、node自体は削除されていないことに注意です。

# nodeのシンボリックリンクが削除され、nだけになっている
# ls -lF /usr/local/bin
total 0
lrwxrwxrwx 1 root root 27 Jul 27 08:06 n -> ../lib/node_modules/n/bin/n*

# node自体は残っている
# ls /usr/local/n/versions/node/
10.16.0  12.7.0

ついにnのアンインストールです。今なら「aptで入れた方のnpm」で実行可能です。

# npm uninstall -g n
- n@5.0.1 node_modules/n

削除ができたことを確認しましょう。

# n
bash: /usr/local/bin/n: No such file or directory

# nのシンボリックリンクは削除済み
# ls -lF /usr/local/bin
total 0

# nの実体も削除済み
# ls -lF /usr/local/lib/node_modules/
total 0

# node自体は依然存在
# ls /usr/local/n/versions/node/
10.16.0  12.7.0

以上で、nのアンインストールは完了です。

nを再インストールする場合

ちなみに、node自体はローカルに残っているため、もう一度nを入れると、同じように使うことができます。

# npm install n -g
/usr/local/bin/n -> /usr/local/lib/node_modules/n/bin/n
/usr/local/lib
`-- n@5.0.1

# n
    node/10.16.0
  ο node/12.7.0

   installed : v12.7.0

# node -v
v12.7.0

# 「nで入れた方のnpm」に戻っていますね
# which npm
/usr/local/bin/npm

# アンインストール前と同じであることを確認できました
# ls /usr/local/bin
n  node  npm  npx

「nで入れたnode」を完全にアンインストールする場合

もし、nと「nで入れたnode」を完全に削除する場合は、nodeの実体も削除が必要です。
以下の流れですね。

# nの削除の準備
# n uninstall

# nodeの削除
# rm -rf /usr/local/n

# nodeの削除の確認
# n
find: '/usr/local/n/versions': No such file or directory

  Error: no installed version
...

# npmによるnの削除
# npm uninstall -g n

# 「aptで入れたnpm」でnをアンインストール
# npm uninstall -g n

「aptで入れたnodejsとnpm」のアンインストール

ちなみに、「aptで入れた方のNode.jsnpm」は以下でアンインストール可能です。

# apt purge nodejs npm -y

# grepできないので、アンインストールが確認できますね。
# ls -lF /usr/bin/ | grep -e node -e npm

n uninstallを使わずnをアンインストールしてしまった場合

n uninstallコマンドを使わず、いきなりnpm uninstall -g nを実行した場合、「nで入れたnodenpm」が残ります。

# 「aptで入れたnpm」でnのアンインストール
# npm uninstall -g n

# npmは依然、「aptで入れた」方を指す
# which npm
/usr/local/bin/npm

# nodeも存在する
# which node
/usr/local/bin/node

# nは削除されるが、nodeとnpmは残る
# ls -lF /usr/local/bin
total 40152
-rwxr-xr-x 1 root root 41115408 Jul 27 14:04 node*
lrwxrwxrwx 1 root root       38 Jul 27 14:04 npm -> ../lib/node_modules/npm/bin/npm-cli.js*
lrwxrwxrwx 1 root root       38 Jul 27 14:04 npx -> ../lib/node_modules/npm/bin/npx-cli.js*

こうなると、もう一度nを入れて、n uninstallからやりなおすか、手動で削除。

# npmの実体の削除
# rm -rf /usr/local/lib/node_modules/npm/

# nodeの削除
# rm -rf /usr/local/n

# シンボリックリンクの削除
# # rm /usr/local/bin/node /usr/local/bin/npm /usr/local/bin/npx

以上でおわりです。

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

私のnode開発スタイル

Git for Windows, Vim環境でNode.jsプログラムの開発環境を確認してみたが、まずはここに記述するスタイルで開発してみる。

プログラム開発環境

はい、vim。以下のプラグインを利用する。

  • プラグイン管理:dein
  • タブ設定にキーマップのカスタマイズ版
  • JsDocの自動生成プラグイン:heavenshell/vim-jsdoc
  • 自動的に対応する括弧を挿入する:Townk/vim-autoclose
  • js用インデックスとシンタックスカラー:pangloss/vim-javascript

これだけ。
あまり最初から色々使うと本当に必要だと感じて利用したときのありがたみに欠けるし、使わないプラグインによって重くなる可能性やキーマップのバッティングにより動作に異常をきたすかもしれない。
後は、タブスペース=4、タブを空白に変換、インデント幅とタブキーで挿入される空白の量は4。
ちなみに、NERDTreeは私にとっては少し使いづらいし、わざわざツリー表示したい場面も今のところないためvim標準の:editコマンドで十分と判断。
正直、タブ表示機能も、画面分割機能があれば不要かもと思ったが、1画面フルでソースが見れる状態が簡単に切り替えられるのは少し魅力があるため使ってみる。

JsDocの利用

関数を記入したらJsDocプラグインでドキュメントを作成する。

  • 関数にカーソルを合わせて:JsDocを実行

編集中のnode.jsの実行

はい、shellの機能を利用する。
具体的にはCtrl-zによりvimプロセスを一旦停止して、shellプロンプトに戻ってからnodeコマンドを使いたいように使う。この時、サーバープログラムを動かす場合はバックグランドでnodeを動かす。

  • 編集中のnode実行のためのshellへの切り替え:Ctrl-z
  • nodeをバックグランドで実行:node jsプログラム &
  • nodeプログラムを停止:fgしてからctrl-c、もしくはkill プロセスID
  • 編集へ戻る:fg

これぐらいかなぁ。
あとはvimの標準コマンドとshellの機能を使えばとりあえず十分。

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

node-id3でid3タグを編集する

node.jsでmp3ファイルのid3タグ(曲名や収録アルバム名など)を編集する。

使用するAPI

楽天ブックスCD検索API
https://webservice.rakuten.co.jp/api/bookscdsearch/

node-id3のインストール

npm install node-id3

https://github.com/Zazama/node-id3

コード

id3.js
var req = require("request");
var artistname = "アーティストの名前";
//空白は-(p.s red i => p.s.-red-i)
var cdtitle = "アルバム名";
var url = "https://app.rakuten.co.jp/services/api/BooksCD/Search/20170404?applicationId=1036033389143023148&title=" + encodeURI(cdtitle) + "&artistName=" +  encodeURI(artistname);
var fs = require("fs");
var id3 = require("node-id3");


function writetag(array) {

/*
arrayの中身
[ 
  [ 'P.S. RED I (初回限定盤 CD+DVD)',
    'TK from 凛として時雨',
    [ 'P.S. RED I',
      'moving on',
      'P.S. RED I (Instrumental)',
      'Fantastic Magic',
      'Signal',
      'film A moment',
      'katharsis' ] ],
  [ 'P.S. RED I',
    'TK from 凛として時雨',
    [ 'P.S. RED I', 'moving on', 'P.S. RED I 
    (Instrumental)' ] 
  ] 
]
*/

  var path = "mp3があるフォルダのパス";
  var dir = fs.readdirSync(path);
  var tags;

  for (var i = 0; i <= array.length - 1; i++) {
    if (array[i][2].length == dir.length) {
      for (var j = 0; j <= dir.length - 1; j++) {
        tags = {
          title: array[i][2][j],
          artist: array[i][1],
          album: array[i][0],
          //APIC: "./hogehoge.jpg", CDジャケット?
        }
        id3.write(tags, path + "/" + dir[j]);
      }
    }
  }
}


req.get(url, function(res, body, error) {

    var array;
    var info = [];
    var item_list = ["title", "artistName", "playList"];
    var content = JSON.parse(body.body).Items;

    for (var i = 0; i <= content.length - 1; i++) {
      array = [];
      for (var j = 0; j <= item_list.length - 1; j++) {
          if (j == item_list.length - 1) {
              content[i] = content[i].Item[item_list[j]].split("#");
              //falseと判定された要素を削除(Boolean => 空白文字やnull等がfalseになる型)
              content[i] = content[i].filter(Boolean);
              array.push(content[i]);
          } else {
              array.push(content[i].Item[item_list[j]]);
          }
       }
      info.push(array);
    }

    writetag(info);

});


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

Check! auth0-js の WebAuth.checkSession() でエラーが出てしまう場合の対処

こんにちは、 @dz_ こと大平かづみです。

Prologue

最近、 Auth0 をつかって認証機構を作ろうと試作しています。そこで躓いた点を共有します。

環境

フロントエンド(Vue.js)で Auth0 を使って認証をしようと試みています。基本的にはこのチュートリアル Auth0 Vue SDK Quickstarts: Login を参考にしています。

Vue.js に限らず、フロントエンドで Auth0 を使う場合は auth0-js を使うことが多いようです。

今回は、この auth0-js を利用している際にみつけた事象について記載します。

即タイムアウト?

タイムアウトするようなタイミングでもないのに下記のようなエラーが出た場合は、 Auth0 の管理画面から ApplicationsAllowed Web Origins の設定を確認してみてください。こちらのドキュメント Error response - Silent Authentication | Auth0 にも記載があるように、 Allowed Web Origins を正しく設定するとエラーが解消するかと思います。

Timeout during executing web_message communication

常に Login required エラー

上記エラーをクリアしたのに、今度は常に Login required

調査してみたところ、 auth0.js/README.md at master · auth0/auth0.jscheckSession() の説明を見ると、ソーシャルアカウントでログインしていて、開発環境(インターネット上でアクセス可能なドメインでない)場合は常に Login required になるようです。 :eyes:

Important: If you're not using the hosted login page to do social logins, you have to use your own social connection keys. If you use Auth0's dev keys, you'll always get login_required as an error when calling checkSession.

ですので、ソーシャルアカウントではなくメールアドレスとパスワードでログインするようにすれば、このエラーは解消できることを確認できました。 :raised_hands:

なお、インターネットからアクセスできるドメインで運用すればこのエラーは解消されると見受けられますが、まだ試しておりませんのでご了承くださいませ。

Epilogue

これで常にタイムアウトする事象は避けられました!(笑)
どんどん開発するぞ~!(๑•̀ㅂ•́)و✧

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

(Node.js) require の path 先に指定する方法

問題: requrire を path を指定せず moduleを呼び出したい。

import PrefectureOptions from './../../models/options/PrefectureOptions.js'

moduleを呼び出す時 requrire(import)で指定するpath を指定しないで呼び出したい、と思い解決法を調べました。

解決法: package.json の paths に記述する。

package.json
{
    "paths" : {
        "PrefectureOptions" : "dir/to/models/options/PrefectureOptions.js"
    }
}
import PrefectureOptions from 'PrefectureOptions';

参考情報

https://gist.github.com/branneman/8048520

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

(Node.js) require の path を先に指定する方法

問題: requrire を path で指定せず名前で moduleを呼び出したい。

import PrefectureOptions from './../../models/options/PrefectureOptions.js'

moduleを呼び出す時 requrire(import)で指定するpath を指定しないで呼び出したい、と思い解決法を調べました。

解決法: package.json の paths に記述する。

package.json
{
    "paths" : {
        "PrefectureOptions" : "dir/to/models/options/PrefectureOptions.js"
    }
}
import PrefectureOptions from 'PrefectureOptions';

参考情報

https://gist.github.com/branneman/8048520

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

macでnpm sudoなのにpermission deniedのエラーが出現することについて

はじめに

気づけば初仕事に入ってもはや2ヶ月。
当初に遭った問題を覚えているうちに書きたいと思います。
Windows民がiMacを配られた初日まずは環境構築でした…
Macの使い方やキーボードの配置すらあやふやの中進んでいて、
とりあえず壁をぶつかりまくりました…
まずsudoって管理者権限なのに権限がないってどういうことだよ!!(怒)

試したこと(失敗)

時間のない人はここを飛ばして解決策を見てください。

sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}

色々調べてたどり着いたのはこれ。
ざっくりいうとディレクトリの管理者を自分のアカウントに変更してくれます。
これでsudoがなくても普通にインストールできちゃいます。(むしろsudoを使ったらエラーが出ます)
しかし後ほどいろんな問題が浮かび上がりました…
一番大きかったのはiTunesのリソースを割り当てることができませんでしたエラー。
個人の推測ですが権限が変わった影響でディレクトリを見つからない、
もしくは書き込みできなくなったのではないかと。
このエラーのなにがいけないっていうと、
iPhoneから信頼できないため、実機テストができないのです!!
こうなったらインストールできても意味がないじゃん(涙)

これからは自分のアホ体験談です。
つまらない話なので時間のない方飛ばしてくださいね(二回目)
「sudo chownはだめだったので、元に戻したい!」と思ってとった行動は…
sudo chown -R root $(npm config get prefix)/{lib/node_modules,bin,share}
(実際のコマンドを忘れたがこんな感じ)
「再び権限をrootユーザーに戻せば大丈夫なはず!」という安易な思考から、
自らすべての権限を奪い、キーボードやブラウザの使用権限さえなくなりました。
初期化せざるを得ない状況を作り出したのだ…あれもはやホラーです…
これは、絶対、やっちゃいけません。

解決策

https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally
に書いてありました。

  1. ホームディレクトリに新しいディレクトリを作成(元のディレクトリの代わりに使います)
    mkdir ~/.npm-global

  2. 新しいディレクトリを設定
    npm config set prefix '~/.npm-global'

  3. 文字エディターを開いて、ファイルを新規作成し、以下の行を追加
    export PATH=~/.npm-global/bin:$PATH

  4. 保存する。名前は.profileで保存先はホームディレクトリ
    (隠しファイルなので保存してもFinderでは見えません)

  5. 再びcmdに戻って、sourceコマンドで作成したファイルを反映させる
    source ~/.profile

これでnpm install -gをそのまま使えるようになりました!

おまけ

これで解決できましたが、cmdを開くたびにsource ~/.profileを打たないと反映されませんでした。
毎回だとめんどくさいので、それについても調べました。
どうやら~/.bash_profileというログイン時実行される設定ファイルが存在しています。
なので、それを編集して無事~/.profileの内容が自動的に反映されるようになりました!

  1. cmdで~/.bash_profileを呼び出す
    vi ~/.bash_profile

  2. iキーを押すとで編集モードになり、最後の行に追加
    source ~/.profile

  3. Escキーで編集モードを終了させ、:wqで保存して戻る

さいごに

コマンドプロンプトを使い慣れた方には簡単なことかもしれませんが、
自分は結構苦戦したので、
こんな風にまとめて、一人でも苦戦している方の悩みを解決できたら幸いです。

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

Macでnpm sudoなのにpermission deniedのエラーが出現した

はじめに

気づけば初仕事に入ってもはや2ヶ月。
当初に遭った問題を覚えているうちに書きたいと思います。
Windows民がiMacを配られた初日まずは環境構築でした…
Macの使い方やキーボードの配置すらあやふやの中進んでいて、
とりあえず壁をぶつかりまくりました…
まずsudoって管理者権限なのに権限がないってどういうことだよ!!(怒)

試したこと(失敗)

時間のない人はここを飛ばして解決策を見てください。

sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}

色々調べてたどり着いたのはこれ。
ざっくりいうとディレクトリの管理者を自分のアカウントに変更してくれます。
これでsudoがなくても普通にインストールできちゃいます。(むしろsudoを使ったらエラーが出ます)
しかし後ほどいろんな問題が浮かび上がりました…
一番大きかったのはiTunesのリソースを割り当てることができませんでしたエラー。
個人の推測ですが権限が変わった影響でディレクトリを見つからない、
もしくは書き込みできなくなったのではないかと。
このエラーのなにがいけないっていうと、
iPhoneから信頼できないため、実機テストができないのです!!
こうなったらインストールできても意味がないじゃん(涙)

これからは自分のアホ体験談です。
つまらない話なので時間のない方飛ばしてくださいね(二回目)
「sudo chownはだめだったので、元に戻したい!」と思ってとった行動は…
sudo chown -R root $(npm config get prefix)/{lib/node_modules,bin,share}
(実際のコマンドを忘れたがこんな感じ)
「再び権限をrootユーザーに戻せば大丈夫なはず!」という安易な思考から、
自らすべての権限を奪い、キーボードやブラウザの使用権限さえなくなりました。
初期化せざるを得ない状況を作り出したのだ…あれもはやホラーです…
これは、絶対、やっちゃいけません。

解決策

https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally
に書いてありました。

  1. ホームディレクトリに新しいディレクトリを作成(元のディレクトリの代わりに使います)
    mkdir ~/.npm-global

  2. 新しいディレクトリを設定
    npm config set prefix '~/.npm-global'

  3. 文字エディターを開いて、ファイルを新規作成し、以下の行を追加
    export PATH=~/.npm-global/bin:$PATH

  4. 保存する。名前は.profileで保存先はホームディレクトリ
    (隠しファイルなので保存してもFinderでは見えません)

  5. 再びcmdに戻って、sourceコマンドで作成したファイルを反映させる
    source ~/.profile

これでnpm install -gをそのまま使えるようになりました!

おまけ

これで解決できましたが、cmdを開くたびにsource ~/.profileを打たないと反映されませんでした。
毎回だとめんどくさいので、それについても調べました。
どうやら~/.bash_profileというログイン時実行される設定ファイルが存在しています。
なので、それを編集して無事~/.profileの内容が自動的に反映されるようになりました!

  1. cmdで~/.bash_profileを呼び出す
    vi ~/.bash_profile

  2. iキーを押すとで編集モードになり、最後の行に追加
    source ~/.profile

  3. Escキーで編集モードを終了させ、:wqで保存して戻る

さいごに

コマンドプロンプトを使い慣れた方には簡単なことかもしれませんが、
自分は結構苦戦したので、
こんな風にまとめて、一人でも苦戦している方の悩みを解決できたら幸いです。

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

Firebase Cloud Functionsを使ってGmail送信機能を作る

Firebaseについて

FirebaseはGoogleが提供しているモバイルアプリ、Webアプリのプラットフォームのことで、バックエンド機能を体系的に提供している。Firebseを使うことによって、開発者はクライアントサイドの開発に専念することができる。
できることの例
◇Hosting
本番環境へのホスティング

◇Authentication
ユーザ認証/ログイン機能の実装

◇Databases
データベース

◇Functions
クライアントサイドで実行するには重すぎる処理をHTTPリクエストなどをトリガーに実行できるようにする機能

<以下参考>
Firebase公式:
https://firebase.google.com/?hl=ja
Firebaseの概要についてまとまっいたサイト:
https://www.topgate.co.jp/firebase01-what-is-firebase
Firebaseでできることについてまとまっていたサイト:
https://qiita.com/dogwood008/items/fa95b62ad151f823af70

そして、今回は Firebase Cloud Functions+node.js(nodemailer)でメール送信機能を実装してみる。
調べてみると、Vue.jsで実装している人は多いが、拡張性を高めるためにフレームワークは使用しないパターンで取り組む。

Firebase Cloud Functionsの初期設定

※Googleアカウントを持っていることは前提
※事前にnpmが使用できる環境を作ってあることは前提

①Firebaseでプロジェクトを作成する
・FirebaseコンソールにGoogleアカウントでログイン
 Firebaseコンソール: https://console.firebase.google.com/u/0/?hl=ja
・「プロジェクトを追加」からプロジェクトを追加する

<以下参考>
https://docs.kii.com/ja/samples/push-notifications/push-notifications-android-fcm/create-project/

②Firebase CLIをインストール

npm install -g firebase-tools

③Firebase CLIにログインする

firebase login

・ブラウザが立ち上がり、Googleアカウントを設定する画面が出てくるので、①のFirebase コンソールでプロジェクトを作成した Googleアカウントを選択、ログインする。
※Firebase CLIでログインするアカウントを変更したい場合は、

firebase logout

でログアウトすると別アカウントでログインできるようになる。

④Firebase Cloud Functionsのプロジェクトを作成する
A.プロジェクト用のディレクトリを作成し移動、下記コマンドを打つ

firebase init functions

下記のように表示される。

B.ここでセットアップするのは主に2つで
・ Project Setup
Firebase コンソールで作成したプロジェクトがあることを確認、選択。
firebase1.png

・Functions Setup
※基本的には画像と同じように選択すれば良いが、ここはそれぞれで要確認。
firebase2.png

C.ディレクトリの中にプロジェクトが作成されていることを確認
・functions/ の中にindex.jsというファイルが作成されている

$ls
firebase.json   functions

$cd functions/
index.js    package.json

⑤nodemailerとcorsをインストールする
※作業は functions/ で行う

npm install nodemailer cors

index.jsにメール送信のプログラムを書いていく

今回はクエリパラメータに送信先とメッセージ内容を含める仕様で実装。
これで、実際にアプリケーションで使う際も、送信先とメッセージ内容をその都度変更できる。

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const nodemailer = require('nodemailer');
const cors = require('cors')({origin: true});
const gmailEmail = functions.config().gmail.email;
const gmailPassword = functions.config().gmail.password;

admin.initializeApp();

// Using Gmail
let transporter = nodemailer.createTransport({
    service: 'gmail',
    auth: {
        user: gmailEmail,
        pass: gmailPassword
    }
});

// Sending the request
exports.sendMail = functions.https.onRequest((req, res) => {
    cors(req, res, () => {

        // Getting query parameter from http request
        const to = req.query.to;
        const msg = req.query.msg;

        const mailOptions = {
            from: gmailEmail,
            to: to,
            subject: 'This is a sample of email function',
            html: `${msg}`
        };

        // Getting results
        return transporter.sendMail(mailOptions, (erro, info) => {
            if(erro){
                return res.send(erro.toString());
            }
            return res.send('Sended');
        });
    });
});

いくつか解説
A.Gmailを使う際の、送信元のメールアドレスとパスワードについて
Firebaseでは、プロジェクト内で使える環境変数の設定が提供されている。

const gmailEmail = functions.config().gmail.email;
const gmailPassword = functions.config().gmail.password;

で事前に環境変数として設定したGmailアドレスとパスワードを取得する。

◇Firebaseでの環境変数の設定の仕方はこちらを参考
https://qiita.com/nerdyboy_cool/items/695c8af7ca8d22761927

(こんな感じ)

firebase functions:config:set gmail.email="hoge@gmail.com" gmail.password="fugafuga"

B.クエリパラメータから送信先メールアドレスとメッセージ内容を取得する仕組みについて

ここで取得している

const to = req.query.to;
const msg = req.query.msg;

⑥メール送信機能をデプロイする
プロジェクトの直下ディレクトリに戻る(functions/ の1つ上)

firebase deploy

そして以下のように表示されたら成功
firebase3.png

⑥デプロイしたfunctiosのURLを確認して、メールを送ってみる
A.Firebase コンソールに行き、該当プロジェクトの画面まで移動
左のメニュー欄のFunctionsのダッシュボードにHTTPリクセスト用のURLが表示さレているので取得

https://us-central1-****************/FUNCTIONAME

のようになっているので、クエリパラメータを指定して、ブラウザでURLを叩けばメールが送信される。

https://us-central1-****************/FUNCTIONAME?to=RECEIVER_EMAIL&msg=hogehoge"

このURLをHTMLのaタグとかで叩けば、アプリ内でサーバーを立ち上げなくてもGmail送信機能を使用することができる。

その他参考記事

Firebase Cloud Functionsについて:
https://qiita.com/HALU5071/items/e43729ac5b06b0506fbe
https://qiita.com/tdkn/items/2ed2b01f2656fc50da8c
今回の全体的な参考:
https://medium.com/@edigleyssonsilva/cloud-functions-for-firebase-sending-e-mail-1f2631d1022e
Vue.jsでやっている記事:
https://qiita.com/Hiroyuki1993/items/1ab9266ca6fc422113e3
https://qiita.com/ryo2132/items/7cdd6c86dd418095f74a#_reference-7ee779146fd0b678f3f9

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

Node.jsをインストールする方法(Windows)

自身の備忘録としてNode.jsのインストール方法を記事にまとめてみました。
ちなみに、マシンはWindows10を使用しています。

インストールまでの流れ

  1. Nodistをインストール
  2. 正常にインスールされたか確認
  3. 公式HPからインストールしない理由(おまけ)

Nodistをインストール

Nodistからインストールができます。
コメント 2019-07-23 100508.png
画面上部にあるバージョンで NodistSetup-v0.9.1.exe をクリックします。
コメント 2019-07-23 100659.png
Next> をクリックします。
コメント 2019-07-23 100734.png
表示内容を確認し、 I Agree をクリックします。
コメント 2019-07-23 100813.png
フォルダーを確認し、変更の必要がなければそのまま Install をクリックします。
コメント 2019-07-23 100856.png
インストールが終了すると Finish をクリックします。
これでNodistのインストール完了です。

NodistからNode.jsをインストールしよう

  1. Nodistがインストールされてるか確認
  2. インストール可能なNode.js一覧を表示
  3. バージョンを選択
  4. Node.jsがインストールされているか確認

1.Nodistがインストールされてるか確認

nodist -v

WindowsであればWindows Power Shellまたはコマンドプロンプトで nodist -v コマンドを入力します。

2.インストール可能なNode.js一覧を表示

nodist dist

nodist dist コマンドを入力するとインストール可能なNode.jsのバージョン一覧が表示されます。

  10.10.0
  10.11.0
  10.12.0
  10.13.0
  10.14.0
  10.14.1
  10.14.2
  10.15.0
  10.15.1
  10.15.2
  10.15.3
  10.16.0

偶数から始まるバージョンが一般的に安定版といわれています。
必要に応じてバージョンを選びましょう。

3.バージョンを選択

今回はNode.js公式が推奨している 10.16.0 をインストールします。
(2019/07/27時点)

nodist 10.16.0

上記コマンドを入力すると、該当のバージョンがインストールされ使用できる状態になります。
バージョンを変更したい場合は、先ほどと同様に nodist (バージョン) を入力すればOKです。

4.Node.jsがインストールされているか確認

node -v

指定したバージョンが表示されれば、インストールが正常に完了していると判断してください。

公式HPからインストールしない理由(おまけ)

image.png
Node.jsの公式HPからもインストールが可能です。
しかし、公式HPからインストールしてしまうと、バージョンが固定されてしまいます。

Nodeを使用しているとバージョンを切り替えたいといったことが多々あるそうです。
そういったときに公式HPからインストールしてしまうとバージョン切り替えができません。

そのため、今回は公式HPではなくNodeのインストールやバージョン管理が行えるNodistをあえてインストールしました。

まとめ

PCをセットアップする際にNode.jsをインストールするので、そういった場面で自身が見返すときに分かりやすいようにまとめました。

自身の備忘録としてまとめましたが、間違い等があればご指摘いただけると幸いです。

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

Node.jsでprivateメソッドをテスト方法を検討

概要

Node.jsに限らず各言語でpriateメソッドをテストする際、程度の差はありますが工夫が必要にあります。
今回はNode.jsでpriateメソッドをテストするまでに時間を要したので、メモとして残しておきます。

読者対象

  • priateメソッドをテストしたいけど、面倒なので放置した方

不採用になった案

結論は自前でやることになったのですが、パッケージやコードがないかなと思ってググりました。
その中で採用候補になったものをあげておきます。

requireで細工をする

Nodeでプライベートな(exportsされてない)メソッドのテスト
http://nazomikan.hateblo.jp/entry/2013/04/10/032410
vm.runInThisContext()にする場合の補足
https://stackoverflow.com/questions/20899863/the-module-property-is-undefined-when-using-vm-runinthiscontext

これはrequireを通すとexportされてないものがロードできないため、自前でrequireを用意するやり方です。
似たような感じにして作ってみましたが、私はうまく行きませんでした。
やり方が悪かったのか、記事が古くvm.runInNewContext()の仕様が変わったのかは不明です。
テストコードが比較的スマートなので採用する予定でした。
しかし、一部キャッシュされたモジュールを使いまわす前提の箇所があり、contextが別になるとそこの動作への懸念が出たので不採用になりました。

rewireを導入

https://www.npmjs.com/package/rewire

rewireパッケージを使うことも検討しました。
普段の書き方と変わるのが少しマイナス。
あまり好まないので、さらに検討を進めて自前になりました。

後で以下を見て、これでも悪くないかなと思ったのは内緒です。
const test123 = require('./index').__get__('test123');
https://www.grzegorowski.com/jest-tests-with-rewire-plugin/

実践

通常と同じ動作をしてほしいし、複雑なことはやりたくない。
とにかくシンプルがいい。ただ、テストの時だけpublicにしたいだけなのに…条件で切り替えればいいだけじゃないか:hugging:
思いついたら後は作るだけ。

test.js
const firebaseUtil = require('./firebase/util.js');

test('call private method', () => {
    firebaseUtil.privateMethod();
})

firebaseのutilモジュールにあるprivateメソッドをコールするテストを想定します。
privateMethodはexportしていないので、このままでは実行エラーになります。

firebase/util.js
const { getPrivateMethodsInTest } = require('../utils/testHelper'); // add code

const publicMethod = () => console.log('this is public');
const privateMethod = () => console.log('this is private');

module.exports = {
    publicMethod,
    ...getPrivateMethodsInTest({ privateMethod }) // add code
};

util.jsではpublicMethod()とprivateMethod()があり、publicMethodは通常通りexportしており、privateの方はgetPrivateMethodsInTest()というメソッドを挟んでいます。
getPrivateMethodsInTest()がカギになります。

utils/testHelper.js
const getPrivateMethodsInTest = 
    (methods) => process.env.NODE_ENV === 'test' ? methods : {};

module.exports = { getPrivateMethodsInTest };

jestの場合、テスト実行時にprocess.env.NODE_ENVに'test'が入るため、それによって渡されたメソッドをそのまま返すか、空のオブジェクトを返すか切り替えているだけのシンプルなものです。
この戻り値を呼び出し元で展開することで、テスト時にはprivateメソッドがexportされ、それ以外の場合にはpublicメソッドのみが展開されるようになります。
この案のメリットはテスト時は通常のpublicメソッドなので、トラブルの心配がないというところです。

シンプルにまとまっていると思いますが、対象となるソースが多くなってくると煩わしく思えるかもしれません。
その場合はrewireの採用を検討したほうがいいかもしれません。

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

Node.jsでCSVからPHPに雑に変換してみる

WordPressのリプレイスもどき案件で大量(1,000件以上)のリダイレクトをすることになりそうなので、後の自分のダメージを減らすべく、準備がてらなるべく楽にリダイレクト出来る方法を考えました。

表題の通り 雑に 書いています。取り敢えず目的を果たす為だけにつくりました。

達成したいこと

  • 大量のリダイレクトの処理の手間を減らしたい。
    • 目視で1件ずつは勘弁…
  • 本番・開発・ローカルでファイルを共有出来る状態にしておきたい。
    • サーバーの仕様に影響される .htaccess は本番・開発・ローカルで共有したくない。(共有出来ない可能性がある。)
  • 自分以外の人もリダイレクト元とリダイレクト先の情報が一度に確認出来る状態にしておきたい。
    • プラグインを利用した場合、管理画面から1件ずつ確認するのが面倒臭そう。間違いに気付きにくい。
    • GoogleDriveなどで表にしておいて、必要な情報のみ抜き出して編集・閲覧出来る状態にしておけば、間違いに気付きやすくなる。

考えた方法

リダイレクト元とリダイレクト先のURLを記載したCSVファイルを作り、リダイレクト用のPHPに変換し、header('Location:...') を利用してリダイレクト。

今回はリダイレクトの条件の部分の変換を行いました。( header('Location... を書いてある別ファイルにincludeする前提)

プラグインを使用しなかった理由

  • プラグインによっては更新が止まっているものがある(アップデート後に不具合を起こす可能性がある)。
  • リダイレクトの設定が .htaccess に吐き出されるプラグインは避けたい。
    • 本番・開発・ローカルで .htaccess を使い回すことは避けたい。

前提条件

  • Node.js をインストール済みであること

使うもの

準備

パッケージをインストール

yarn add csv -D

若しくは

npm i csv -D

csvファイルと変換先の空のファイルを用意

csv

  • title:ページのタイトル
  • old:リダイレクト元のドメインより後のURL
  • new:リダイレクト先のドメインより後のURL
CSVのデータ
title,old,new
Contact,contact,sample-page
りだいれくとのてすと。さんぷるページに移動,19,sample-page
りだいれくとてすと2。プライバシーポリシーにいどう,21,privacy-policy

空のファイル

中身は書かずに hoge.php で保存

スクリプトを書く

convert-csv.js で保存

変換用スクリプト
/**
 * csvからリダイレクト用のPHPに変換するスクリプト
 */
const fs = require('fs');
const csv = require('csv');


/**
 * データをパースする
 */
const parser = csv.parse( { columns: true }, ( error, data ) => {

  if ( error ) {
    console.error(error);
    return;
  }

  /**
   * データからリダイレクト元とリダイレクト先のURLのみ取り出した配列を作成
   */
  const redirectUrlArray = data.map((obj) => {
    const oldUrl = obj['old'];
    const newUrl = obj['new'];
    return { oldUrl, newUrl };
  });

  /**
   * リダイレクト元とリダイレクト先の配列を元にPHPのswitch文の中身を作成
   */
  const arrayText = redirectUrlArray.map((obj) => {
    return `    case home_url('/').'${obj['oldUrl']}/':\n      $redirectUrl = home_url('/').'${obj['newUrl']}/';\n      break;\n`;
  });


  /**
   * テキストに変換
   */
  const outText = arrayText.join(',').replace(/,/g, '');

  /**
   * PHPファイルの中身
   */
  const outputData = `<?php\n  switch ($url) {\n${outText}\n  }\n?>`;

  /**
   * ファイルに書き出し
   */
  fs.writeFile(__dirname + 'hoge.phpのファイルパス', outputData, (error) => {

    if ( error ) {
      console.error(error);
      return;
    }
    console.log(outputData);
    console.log('変換完了');

  });

});


/**
 * ファイルの読み込み
 */
fs.createReadStream(__dirname + 'CSVデータのファイルパス').pipe(parser);

実行

convert-csv.js を保存したディレクトリで以下を実行

node convert-csv.js

実行結果

<?php
  switch ($url) {
    case home_url('/').'contact/':
      $redirectUrl = home_url('/').'sample-page/';
      break;
    case home_url('/').'19/':
      $redirectUrl = home_url('/').'sample-page/';
      break;
    case home_url('/').'21/':
      $redirectUrl = home_url('/').'privacy-policy/';
      break;

  }
?>

最後の break; の後に改行が入りますが動作に影響は無いので無視で・・・

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

CentOS7 CLIでLighthouseを実行する

検証環境

Docker Toolbox version 18.09.3
Oracle VM VirtualBox 5.2.20

※コンテナをPrivileged modeで起動する

$ cat /etc/redhat-release 
CentOS Linux release 7.6.1810 (Core)

検証日時

2019/07/28

Node.jsをインストール

$ curl -sL https://rpm.nodesource.com/setup_12.x | bash -
$ yum install -y nodejs
$ node --version
v12.7.0

$ npm --version
6.10.0

参考

パッケージマネージャを利用した Node.js のインストール
https://nodejs.org/ja/download/package-manager/

Node.js 公式のバイナリディストリビューションが NodeSource によって提供されています。

Yarnをインストール

$ curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo
$ yum install -y yarn
$ yarn --version
1.17.3

参考

Installation
https://yarnpkg.com/en/docs/install#centos-stable

Puppeteerをインストール

$ yarn global add puppeteer
$ cat /usr/local/share/.config/yarn/global/node_modules/puppeteer/package.json | grep -e version -e chromium
  "version": "1.19.0",
    "chromium_revision": "674921"
:

不足しているモジュールをインストール

$ yum install -y pango.x86_64 \
libXcomposite.x86_64 \
libXcursor.x86_64 \
libXdamage.x86_64 \
libXext.x86_64 \
libXi.x86_64 \
libXtst.x86_64 \
cups-libs.x86_64 \
libXScrnSaver.x86_64 \
libXrandr.x86_64 \
GConf2.x86_64 \
alsa-lib.x86_64 \
atk.x86_64 \
gtk3.x86_64 \
ipa-gothic-fonts \
xorg-x11-fonts-100dpi \
xorg-x11-fonts-75dpi \
xorg-x11-utils \
xorg-x11-fonts-cyrillic \
xorg-x11-fonts-Type1 \
xorg-x11-fonts-misc
$ yum update nss -y

参考

GoogleChrome/puppeteer
https://github.com/GoogleChrome/puppeteer

Chrome headless doesn't launch on UNIX
https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#chrome-headless-doesnt-launch-on-unix

Sandboxを設定

$ cd /usr/local/share/.config/yarn/global/node_modules/puppeteer/.local-chromium/linux-674921/chrome-linux/
$ chown root:root chrome_sandbox
$ chmod 4755 chrome_sandbox
$ cp -p chrome_sandbox /usr/local/sbin/chrome-devel-sandbox

参考

Setting Up Chrome Linux Sandbox
https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#setting-up-chrome-linux-sandbox

[alternative] Setup setuid sandbox

Lighthouseをインストール

$ yarn global add lighthouse
$ yarn global list | grep lighthouse
info "lighthouse@5.2.0" has binaries:
   - lighthouse

参考

GoogleChrome/lighthouse
https://github.com/GoogleChrome/lighthouse

Lighthouseを実行

# rootで実行するとエラーになるためユーザーを作成
$ useradd test
$ su - test
# 必要な環境変数を設定
$ export CHROME_PATH=/usr/local/share/.config/yarn/global/node_modules/puppeteer/.local-chromium/linux-674921/chrome-linux/chrome
$ export CROME_DEVEL_SANDBOX=/usr/local/sbin/chrome-devel-sandbox
# ChromeをHeadlessモードで実行
$ lighthouse --output html --output-path ./report.html --throttling-method=provided --chrome-flags="--headless" https://qiita.com

補足

このコマンドを実行するとスマホ表示のスコアを計測する。
PC表示のスコアを計測する場合はオプション--emulated-form-factor=noneを追加する。

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

node.jsで簡易データベースとしてExcelファイルを使う

node.jsで簡易データベースとしてExcelファイルを使う

MySQLを使うほど大袈裟にせず手軽にデータベースを使いたい場合、簡易データベースとしてExcelを導入するのも良い手だと思います。
ExcelならSQLを使わずに抽出やデータ更新ができるので手軽に扱えるというメリットがあります。
そこでnode.jsでExcelファイルを読み書きできるライブラリを探しました。
できればヘッダなどは色付けしておきたいので書式情報は維持したまま保存したいです。

SheetJS

高機能だがPro版でないと書式情報が保存されないので却下。
公式ページ

xlsx-populate

xlsx-populateなら書式情報を維持しながらExcelファイルを読み書きできます。
Github

インストール方法

npm install xlsx-populate

使い方

const XlsxPopulate = require('xlsx-populate')

XlsxPopulate.fromFileAsync("./Input.xlsx")
    .then(book => {
        const sheet1 = book.sheet("Sheet1")
        sheet1.cell("A2").value(10)
        sheet1.cell("B2").value(20)
        sheet1.cell("C2").value(30)
        book.toFileAsync("./Output.xlsx")
    })

xlsx-populate-wrapper

xlsx-populateをラッピングしたxlsx-populate-wrapperを使うとさらに使いやすくなります。

Github

インストール方法

npm install xlsx-populate-wrapper

使い方

const xPopWrapper = require("xlsx-populate-wrapper")
const path = require("path")

const filePath = path.resolve('./sample_data.xlsx')
const workbook = new xPopWrapper(filePath)

workbook.init()
  .then(wb => {
    // シート名の一覧を取得
    console.log(wb.getSheetNames())
    // => ['Sheet1', 'Sheet2', 'Sheet3']

    // シート名を指定してヘッダ一覧の取得
    console.log(workbook.getHeadings('Sheet1'))
    // => ['Title1', 'Title2', 'Title3']

    // シート名を指定してJSONデータとして取得
    const jsonData = workbook.getData('Sheet1')
    console.log(jsonData)
    /*
      [
        {
          'Title1': '1',
          'Title2': '2',
          'Title3': '3',
        },
        {
          'Title1': '5',
          'Title2': '6',
          'Title3': '7',
        },
        {
          'Title1': '11',
          'Title2': '12',
          'Title3': '13',
        }
      ]
    */

    // データを書き換える
    jsonData[0].Title3 ='a'
    jsonData[1].Title3 ='b'
    jsonData[2].Title3 ='c'

    workbook.update('Sheet1', jsonData) // 更新

    return workbook.commit() // ファイルに書き込み
  })
  .catch(error => {
    throw error
  })

書き換え前のExcelファイル

image.png

実行ログ

image.png

書き換え後のExcel

image.png

ExcelデータをJSONデータとして扱えるのでjQueryやunderscoreを組み合わせるとwhere検索や絞り込みが行えるのでかなり使えるノウハウと思います☺

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