- 投稿日:2019-07-27T23:29:36+09:00
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 n0. 関係性の整理
検証に入る前に、まずは
Node.js
,npm
,n
の関係を整理します。
n
を使ってNode.js
のバージョンを管理する場合、以下のような手順になります。
- aptで
Node.js
とnpm
をインストールnpm
でパッケージn
をインストール- パッケージ
n
でNode.js
とnpm
を複数インストールしバージョン管理つまり、「aptで入れた
Node.js
,npm
」と、「n
で入れたNode.js
,npm
」が共存する形になります。
ただし、n
によりNode.js
を入れた時点で、bashのコマンドは「n
で入れた方のNode.js
,npm
」へ向くためn
でのバージョンの管理が可能となります。
以下のような構造ですね。
- aptで入れた
Node.js
とnpm
(<-使われない)- aptで入れた
npm
で入れたパッケージn
- パッケージ
n
で入れたNode.js
とnpm
(<-bashではこれを使う)これを前提として、
n
をアンインストールする際に以下の問題が発生します。nのアンインストール時に発生する問題
n
をアンインストールする際、「n
でインストールしたNode.js
,npm
」が残ってしまいます。
構造を可視化すると、以下のようになります。
- aptで入れた
Node.js
とnpm
(存在する)- aptで入れた
npm
で入れたパッケージn
(削除済み)- パッケージ
n
で入れたNode.js
とnpm
(存在する。bashはこれを使う)つまり、
n
を削除しても、3の「n
で入れたNode.js
とnpm
」は依然存在するため、
1のNode.js
を使いたいときや、Nodenv
など他のパッケージマネージャを使いたい場合に、
3のn
で入れたNode.js
を見に行ってしまうという不具合が起きてしまいます。解決策
最近までは、「
n
で入れたNode.js
とnpm
」を手動で消す必要がありました。
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.js
とnpm
は、# 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.js
とnpm
」をアンインストールする理由は、ここにあったんですね。現時点のインストール状況を整理します。
「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のアンインストール
n
はnpm
のパッケージの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.js
とnpm
」は以下でアンインストール可能です。# apt purge nodejs npm -y # grepできないので、アンインストールが確認できますね。 # ls -lF /usr/bin/ | grep -e node -e npmn uninstallを使わずnをアンインストールしてしまった場合
n uninstall
コマンドを使わず、いきなりnpm uninstall -g n
を実行した場合、「n
で入れたnode
とnpm
」が残ります。# 「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以上でおわりです。
- 投稿日:2019-07-27T22:40:37+09:00
私の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の機能を使えばとりあえず十分。
- 投稿日:2019-07-27T20:23:34+09:00
node-id3でid3タグを編集する
node.jsでmp3ファイルのid3タグ(曲名や収録アルバム名など)を編集する。
使用するAPI
楽天ブックスCD検索API
https://webservice.rakuten.co.jp/api/bookscdsearch/node-id3のインストール
npm install node-id3https://github.com/Zazama/node-id3
コード
id3.jsvar 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); });
- 投稿日:2019-07-27T19:40:46+09:00
Check! auth0-js の WebAuth.checkSession() でエラーが出てしまう場合の対処
こんにちは、 @dz_ こと大平かづみです。
Prologue
最近、 Auth0 をつかって認証機構を作ろうと試作しています。そこで躓いた点を共有します。
環境
フロントエンド(Vue.js)で Auth0 を使って認証をしようと試みています。基本的にはこのチュートリアル Auth0 Vue SDK Quickstarts: Login を参考にしています。
Vue.js に限らず、フロントエンドで Auth0 を使う場合は
auth0-js
を使うことが多いようです。今回は、この
auth0-js
を利用している際にみつけた事象について記載します。即タイムアウト?
タイムアウトするようなタイミングでもないのに下記のようなエラーが出た場合は、 Auth0 の管理画面から Applications の
Allowed 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.js の
checkSession()
の説明を見ると、ソーシャルアカウントでログインしていて、開発環境(インターネット上でアクセス可能なドメインでない)場合は常にLogin required
になるようです。![]()
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.
ですので、ソーシャルアカウントではなくメールアドレスとパスワードでログインするようにすれば、このエラーは解消できることを確認できました。
なお、インターネットからアクセスできるドメインで運用すればこのエラーは解消されると見受けられますが、まだ試しておりませんのでご了承くださいませ。
Epilogue
これで常にタイムアウトする事象は避けられました!(笑)
どんどん開発するぞ~!(๑•̀ㅂ•́)و✧
- 投稿日:2019-07-27T19:39:23+09:00
(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';参考情報
- 投稿日:2019-07-27T19:39:23+09:00
(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';参考情報
- 投稿日:2019-07-27T18:44:25+09:00
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
に書いてありました。
ホームディレクトリに新しいディレクトリを作成(元のディレクトリの代わりに使います)
mkdir ~/.npm-global
新しいディレクトリを設定
npm config set prefix '~/.npm-global'
文字エディターを開いて、ファイルを新規作成し、以下の行を追加
export PATH=~/.npm-global/bin:$PATH
保存する。名前は.profileで保存先はホームディレクトリ
(隠しファイルなので保存してもFinderでは見えません)再びcmdに戻って、sourceコマンドで作成したファイルを反映させる
source ~/.profile
これで
npm install -g
をそのまま使えるようになりました!おまけ
これで解決できましたが、cmdを開くたびに
source ~/.profile
を打たないと反映されませんでした。
毎回だとめんどくさいので、それについても調べました。
どうやら~/.bash_profileというログイン時実行される設定ファイルが存在しています。
なので、それを編集して無事~/.profileの内容が自動的に反映されるようになりました!
cmdで~/.bash_profileを呼び出す
vi ~/.bash_profile
iキーを押すとで編集モードになり、最後の行に追加
source ~/.profile
Escキーで編集モードを終了させ、
:wq
で保存して戻るさいごに
コマンドプロンプトを使い慣れた方には簡単なことかもしれませんが、
自分は結構苦戦したので、
こんな風にまとめて、一人でも苦戦している方の悩みを解決できたら幸いです。
- 投稿日:2019-07-27T18:44:25+09:00
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
に書いてありました。
ホームディレクトリに新しいディレクトリを作成(元のディレクトリの代わりに使います)
mkdir ~/.npm-global
新しいディレクトリを設定
npm config set prefix '~/.npm-global'
文字エディターを開いて、ファイルを新規作成し、以下の行を追加
export PATH=~/.npm-global/bin:$PATH
保存する。名前は.profileで保存先はホームディレクトリ
(隠しファイルなので保存してもFinderでは見えません)再びcmdに戻って、sourceコマンドで作成したファイルを反映させる
source ~/.profile
これで
npm install -g
をそのまま使えるようになりました!おまけ
これで解決できましたが、cmdを開くたびに
source ~/.profile
を打たないと反映されませんでした。
毎回だとめんどくさいので、それについても調べました。
どうやら~/.bash_profileというログイン時実行される設定ファイルが存在しています。
なので、それを編集して無事~/.profileの内容が自動的に反映されるようになりました!
cmdで~/.bash_profileを呼び出す
vi ~/.bash_profile
iキーを押すとで編集モードになり、最後の行に追加
source ~/.profile
Escキーで編集モードを終了させ、
:wq
で保存して戻るさいごに
コマンドプロンプトを使い慣れた方には簡単なことかもしれませんが、
自分は結構苦戦したので、
こんな風にまとめて、一人でも苦戦している方の悩みを解決できたら幸いです。
- 投稿日:2019-07-27T18:39:43+09:00
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 コンソールで作成したプロジェクトがあることを確認、選択。
・Functions Setup
※基本的には画像と同じように選択すれば良いが、ここはそれぞれで要確認。
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⑥デプロイした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
- 投稿日:2019-07-27T18:35:59+09:00
Node.jsをインストールする方法(Windows)
自身の備忘録としてNode.jsのインストール方法を記事にまとめてみました。
ちなみに、マシンはWindows10を使用しています。インストールまでの流れ
- Nodistをインストール
- 正常にインスールされたか確認
- 公式HPからインストールしない理由(おまけ)
Nodistをインストール
Nodistからインストールができます。
画面上部にあるバージョンでNodistSetup-v0.9.1.exe
をクリックします。
Next>
をクリックします。
表示内容を確認し、I Agree
をクリックします。
フォルダーを確認し、変更の必要がなければそのままInstall
をクリックします。
インストールが終了するとFinish
をクリックします。
これでNodistのインストール完了です。NodistからNode.jsをインストールしよう
- Nodistがインストールされてるか確認
- インストール可能なNode.js一覧を表示
- バージョンを選択
- Node.jsがインストールされているか確認
1.Nodistがインストールされてるか確認
nodist -vWindowsであれば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からインストールしない理由(おまけ)
Node.jsの公式HPからもインストールが可能です。
しかし、公式HPからインストールしてしまうと、バージョンが固定されてしまいます。Nodeを使用しているとバージョンを切り替えたいといったことが多々あるそうです。
そういったときに公式HPからインストールしてしまうとバージョン切り替えができません。そのため、今回は公式HPではなくNodeのインストールやバージョン管理が行えるNodistをあえてインストールしました。
まとめ
PCをセットアップする際にNode.jsをインストールするので、そういった場面で自身が見返すときに分かりやすいようにまとめました。
自身の備忘録としてまとめましたが、間違い等があればご指摘いただけると幸いです。
- 投稿日:2019-07-27T18:06:58+09:00
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にしたいだけなのに…条件で切り替えればいいだけじゃないか
思いついたら後は作るだけ。test.jsconst firebaseUtil = require('./firebase/util.js'); test('call private method', () => { firebaseUtil.privateMethod(); })firebaseのutilモジュールにあるprivateメソッドをコールするテストを想定します。
privateMethodはexportしていないので、このままでは実行エラーになります。firebase/util.jsconst { 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.jsconst getPrivateMethodsInTest = (methods) => process.env.NODE_ENV === 'test' ? methods : {}; module.exports = { getPrivateMethodsInTest };jestの場合、テスト実行時にprocess.env.NODE_ENVに'test'が入るため、それによって渡されたメソッドをそのまま返すか、空のオブジェクトを返すか切り替えているだけのシンプルなものです。
この戻り値を呼び出し元で展開することで、テスト時にはprivateメソッドがexportされ、それ以外の場合にはpublicメソッドのみが展開されるようになります。
この案のメリットはテスト時は通常のpublicメソッドなので、トラブルの心配がないというところです。シンプルにまとまっていると思いますが、対象となるソースが多くなってくると煩わしく思えるかもしれません。
その場合はrewireの採用を検討したほうがいいかもしれません。
- 投稿日:2019-07-27T16:47:18+09:00
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 -Dcsvファイルと変換先の空のファイルを用意
csv
title
:ページのタイトルold
:リダイレクト元のドメインより後のURLnew
:リダイレクト先のドメインより後のURLCSVのデータ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;
の後に改行が入りますが動作に影響は無いので無視で・・・
- 投稿日:2019-07-27T16:17:29+09:00
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-stablePuppeteerをインストール
$ 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/puppeteerChrome headless doesn't launch on UNIX
https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#chrome-headless-doesnt-launch-on-unixSandboxを設定
$ 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/lighthouseLighthouseを実行
# 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
を追加する。
- 投稿日:2019-07-27T14:03:10+09:00
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を使うとさらに使いやすくなります。
インストール方法
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ファイル
実行ログ
書き換え後のExcel
ExcelデータをJSONデータとして扱えるのでjQueryやunderscoreを組み合わせるとwhere検索や絞り込みが行えるのでかなり使えるノウハウと思います☺