- 投稿日:2019-04-25T23:16:44+09:00
Alexa Lambda関数を「一から作成」する方法
Alexa SkillのLambda関数の作成は、「設計図」のテンプレートから作成する方法が、Alexa道場では紹介されています。
でも、この場合、もともとの設計図のサンプルコードが入っており、それを編集していくのは面倒だったり、何より、関数名の一部は変更できず、関数名が長く気持ちが悪いです。
そこで、「一から作成」を使って、ローカル環境で作成したプロジェクトをアップロードする方法を紹介します。
どちらかというと備忘録です。Node.jsプロジェクトの作成とindex.jsの作成
まず、ローカルドライブで、プロジェクトを作成し、
package.jsonを作成します。$ mkdir SKILL_DIRECTORY $ cd SKILL_DIRECTORY $ npm init
npm initでは、package nameなどを聞かれますが、とりあえずそのまま[Enter]します。続いて、Alexaのモジュールを追加します。
$ npm install ask-sdkすると、npm_modulesというフォルダが作成され、ここにask-sdkのモジュールが以下のように追加されます。
フォルダ .bin ask-sdk ask-sdk-core ask-sdk-dynamodb-persistence-adapter ask-sdk-model ask-sdk-runtime aws-sdk base64-js buffer ... ここで、不要と思われるモジュールのフォルダは削除します。必要なモジュールのフォルダのみにします。
aws-sdkは、Lamdba上に存在するため削除します。
その他base64-jsなどaskで始まらないモジュールのフォルダを削除します。
askで始まるモジュールは、そのフォルダにpackage.jsonファイルが存在します。
このファイルを開いて_whererを探すとそこには、ローカルフォルダの位置が記載されています。リポジトリで使用するようですが、ローカルフォルダがわかるのが嫌なら削除してしまいましょう。続いて、基本となる
index.jsを作成します。このファイルが呼び出しファイルになります。自分でなんらか記載します。その後、この
index.jsとnode_modulesフォルダをzipで圧縮します。zipファイルのLamdbaへのアップロード
AWSのLambdaの関数から「関数の作成」の「一から作成」を選び、関数名を自由につけて、「関数の作成」ボタンを押下します。
続いて、関数コードのコードエントリタイプを「.zipファイルをアップロード」を選択し、zipファイルをアップロードします。
これであとは、エンドポイントなどを設定すれば、Alexa developer consoleから作成した関数を呼び出すことができます。
- 投稿日:2019-04-25T23:06:37+09:00
【Angularアプリ開発】Angularアプリの基本構造を説明します
モジュール
プロジェクトを構成するコンポーネントを束ねる要件はモジュールと呼びます。Angular自体にも複数のモジュールから構成されております。プロジェクトの要件に応じて必要なモジュールをインポートして利用することになります。
App.module
/src/app/に含まれているapp.module.tsファイルは、アプリを起動する際に最初に読み取りにして行くモジュールです。
下図で、app.module.tsファイルを例としてモジュールの役割を見てみましょう。
importコマンド
構文: import{ name1, …, nameN } from module
・name: インポートする要素名(複数指定可)
・module: モジュール
意味: Angularアプリを動作させるのに必要となるモジュール/コンポーネントをインポートします。
Angular標準モジュール
上図の「1.」の@angular/~はAngularが提供する標準モジュールです。最低限、モジュールを定義するためのNgModule、ブラウザー上でアプリを動作させるためのBrowserModuleが導入必要です。
本格的なアプリでは、フォームを扱うためのFormsModule、ルーティング機能を提供するRouterModuleなどを導入する必要があります。
AppRoutingModule
上図の[2.]のAppRoutingModule、 ルートのAppModuleからインポートされるルーティング専用のトップレベルモジュールで、 ルーターをロードして管理することです。
?実装は、下記の「AppRoutingModuleの実装」に行われます。
AppComponent
上図の[3.]のAppComponentは、アプリの本体を表すコンポーネントです。
?実装は、下記の「AppComponentの実装」に行われます。
モジュールクラス
上図の「4.」のAppModuleモジュールクラスは、他のモジュールから呼び出す際などには、ここで宣言した名前(AppModule)を利用します。
@NgModuleデコレーター
上図の「5.」の@NgModuleデコレータは、他者が本モジュールを見れるために、本モジュールとしての情報を宣言しておきましょう。
デコレーターは、モジュールやクラスなどの要素に対してメタ情報を付与するための仕組みです。Javaのアノテーションに相当する仕組みです。
デコレーターには「パラメーター名: 値」のハッシュ形式で、あらかじめ決められたパラメーター情報を指定できます。@NgModuleデコレーターには、主に以下ようなパラメーターが利用できます。
パラメーター 概要 declarations モジュール配下のコンポーネント imports 現在のモジュールで利用する他のモジュール/コンポーネント exports 現在のモジュールで外部に公開するコンポーネント providers サービス bootstrap 最初に起動すべき最上位のコンポーネント(=ルートコンポーネント) AppConponentの実装
上記の「App.module」の「3.」のAppConponentを実装します。
AppConponent(もしくはメインコンポーネント)とは、アプリで最初に呼び出される、いわゆるエントリーポイントです。
「1.」は、コンポーネントを定義するために必要となるオブジェクトをインポートしています。
「2.」は、コンポーネントの本体で、先ほどAppModuleモジュールで指定したAppComponentという名前でコンポーネントクラスを作成しています。モジュールから参照できます
?exportキーワードで外部に公開していることに注意してください。
「3.」の@Componentデコレーターでは、さまざまなパラメーターを指定できます。
パラメーター 概要 selector コンポーネントの適用先を表すセレクター式 template コンポーネントに適用するビュー(テンプレート) テンプレートの中の変数nameは、Interpolation(補間)と呼ばれる構文で、「4.」の場所に定義されております。
AppRoutingModuleの実装
上記の「App.module」の「3.」のルートモジュールを実装します。ルートモジュールは、ユーザーがリンクをクリックしたとき、またはURLをブラウザのアドレスバーに貼り付けた時に、 どのビューを表示したらよいかをルーターに伝えます。
「2.」のRoutesは、「パラメーター名: 値」のハッシュプロパティを持っています:
パラメーター 概要 path ブラウザのアドレスバーにある URL にマッチする文字列 component そのルートに遷移するときにルーターが作成すべきコンポーネント errorページ追加
VSCodeのターミナルを開き、以下ようにerrorページを追加してみましょう。
$ ng g component error # 以下表示 CREATE src/app/error/error.component.css (0 bytes) CREATE src/app/error/error.component.html (24 bytes) CREATE src/app/error/error.component.spec.ts (621 bytes) CREATE src/app/error/error.component.ts (265 bytes) UPDATE src/app/app.module.ts (734 bytes)下図のように、ルートモジュールを編集しErrorページをルーターに伝えます。
Errorページを試すために、サーバを起動して、URLに「localhost:4200/error」を打つでErrorComponentを表示しましょう。
$ ng serve
- 投稿日:2019-04-25T16:53:38+09:00
もう npm ls でイラッとしない
みなさんは
npm lsで依存モジュールがずらずらと表示されて、イラッとしたことはありませんか。私はあります。npm ls --depth=0とすれば、トップレベルのモジュールのみに制限できますが、いちいち
--depth=0をつけるのは面倒です。そこで、次のコマンドを実行してみましょう。
npm config set depth 0これ以降、
--depth=0をつけなくても、npm lsでトップレベルのモジュールのみが表示されるようになります。設定は~/.npmrcに保存されます。依存ツリーが見たい場合は、
npm ls --depth=9999のように、
depthを適当に大きな値で上書きすれば OK です。参考
- 投稿日:2019-04-25T16:29:38+09:00
slackにdynamoDBから情報を取得して、整形まで。[投稿は、ご自身で。]
ことの発端
- POSを開発しているチーム所属なので導入店舗が増えれば管理も増えてくる。
- クレジット決済端末を交換したい時とかに、いちいちCLIでDynamoDBをみていた。
- めんどくさい of the day。
どうでもいいこと
- Node: 知りません。
- TypeScript: 美味しいの?
- lambda: チョットワカル
- Qiita: 通勤してる時にちょっと見る。
- 某パズルゲーム: ランク994(2019/04/24)
- 昨年ランク1000行けなかったのが悔しい。
では、参る。
- slackのスラッシュコマンドで作りました。
- すでにあるものに付け加えたので、slackから値を受け取りたい等はお調べください。
今回slackから渡ってくるサブコマンドは、3つあります。
エラーハンドリングは社内でしか使いわないので、しません。
TypeScriptです。
男は黙ってconst
post to slack #1
sample.tsimport * as AWS from "aws-sdk" import * as url from "url" const docClient = new AWS.DynamoDB.DocumentClient();
import * as url from "url"は呼ばれたチャンネルに返却するためです。参考資料: AWS JavaScript SDK DynamoDB - 公式ドキュメント
post to slack #2
main functionの内部です。
sample.tsconst resURL = url.parse(query.response_url) const partitionKey = query.text.split(" ")[1]; let params if (query.text.split(" ")[2] && query.text.split(" ")[2] !== "") { const sortKey = query.text.split(" ")[2] params = { TableName: TABLE_NAME, ProjectionExpression: '#pk, row2, row3, row4, row5, row6', KeyConditionExpression: '#pk = :partKey AND row1 = :sortKey', ExpressionAttributeNames: { '#pk': PRIMARY_KEY }, ExpressionAttributeValues: { ':partKey': partitionKey, ':sortKey': sortKey }, } } else { params = { TableName: 'TABLE_NAME', ProjectionExpression: '#pk, row2, row3, row4, row5, row6', KeyConditionExpression: '#pk = :partKey', ExpressionAttributeNames: { '#pk': PRIMARY_KEY }, ExpressionAttributeValues: { ':partKey': partitionKey }, Limit: 10, } }
TableName: DynamoDBの使用するテーブル名ProjectionExpression: DynamoDBから取ってきたい列。 <- なくてもいい。KeyConditionExpression: クエリ部分ExpressionAttributeNames: クエリする際のprimaryKeyと思えばいいはず。ExpressionAttributeValues:ExpressionAttributeNamesの値Limit: DynamoDBから取得する最大数。if内はslackからくる引数が2つの場合。(1つだけ抽出)
else内は引数が1つの場合。(PRIMARY_KEYの列を抽出)post to slack #3
sample.tsdocClient.query(params, (err, data: any) => { if (err) { console.error("Unable to query. Error:", JSON.stringify(err, null, 2)); } else { const array = data.Items.map(i => { const output = { item1: i.row2 item2: i.row3, item3: i.row4, item4: i.row5, item5: i.row6, } return output }); let fields = [{ title: String, value: ``, short: true }]; fields.splice(0, 1) // 空の連想配列を取り除く for (const i of array) { const text = ` item1: ${i.item1}\n item2: ${i.item2}\n item3: ${i.item3}\n item4: ${i.item4}\n` fields.push({ title: i.item5, value: "```" + text + "```", short: true }) } post to slack #4に続く
TypeScriptなのにany使ってます。ごめんなさい。
- 必要な物だけを使いたかったので
ProjectionExpressionを記述しました。- Slack Attachments ドキュメント
仕上がりはこんな感じにしました。
- fieldsを使用することで、slackのスペースを有効に使えます。
- fields部分の処理をforですることで複数に対応しています。
- 1回の処理で枠1つのfieldsを作り、arrayの要素分作成します。
- 複数にする際はfor文でできます。
post to slack #4
sample.tsconst attachments = [ { fallback: "通知:tada:", color: "#439FE0", title: "タイトル + partitionKey", fields: fields, mrkdwn_in: ["text"], }]; postSlackBot(resURL, attachments) //自前の関数です。 } });
fallback: 通知。シュココのところです。color: 色- title: タイトル
fields: #3で作ったfields自前の関数はありますが、slackに表示する記事はたくさんあると思うので、検索してみてください。
おわり。
以上で、DynamoDBから取得し、整形までのフローです。
もっとよくできるとかあれば、コメントいただければと思います。
- 投稿日:2019-04-25T13:35:28+09:00
Node.js v12をyumでインストールしてみた。(CentOS 7)
Node.js v12がリリース
node.js v12 (LTS予定)がリリースされました。
v8エンジンがアップグレードされたり、TLS1.3がサポートされたりと、色々変わっているようです。
詳しくは、リリースノート(英語)をみましょう。
https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V12.md#12.0.0Node.js v12 をインストール
取り敢えず、リポジトリを追加。
# yum install https://rpm.nodesource.com/pub_12.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm念のため、yum でnodejsのどのバージョンが対象になっているか確認。
# yum info nodejs Installed Packages Name : nodejs Arch : x86_64 Epoch : 2 Version : 12.0.0 <-ココが重要 Release : 1nodesource Size : 58 M Repo : installed From repo : nodesource Summary : JavaScript runtime URL : http://nodejs.org License : MIT and ASL 2.0 and ISC and BSD Description : Node.js is a platform built on Chrome's JavaScript runtime : for easily building fast, scalable network applications. : Node.js uses an event-driven, non-blocking I/O model that : makes it lightweight and efficient, perfect for data-intensive : real-time applications that run across distributed devices.問題なさそうなので、インストールする。
# yum -y install nodejs最後に、バージョンを確認しておしまい。
# node --version v12.0.0enjoy!
- 投稿日:2019-04-25T13:24:59+09:00
Node.jsとPHP APIを使用して複合機が受信するFAXをアプリで見れるようにしてみた。
はじめに
・複合機でFAXを受信したときに、そのデータをスマホアプリに転送してほしいとお願いされた。Node.jsとPHP APIを使用して機能の実現を試みました。
開発環境
・サーバー構成
WindowsServr2012R2
Apache + SQLServer2012 + PHP
Node.js(シェルスクリプト)・複合機機種
Canon iR-ADV C5235F実装コード
・Node.jsからPHP APIの呼び出し
参考にしたページ:https://qiita.com/zaburo/items/0280807fe5e59026e41b
fax_tenso.jsvar kyotenHand001EmailAdress = "【手動転送用のメールアドレス】"; var kyotenAuto001EmailAdress = "【自動転送用のメールアドレス】"; var request = require('request'); // HTTP header var headers = { 'Content-Type': 'application/json', 'Content-type': 'application/x-www-form-urlencoded' }; //require var chokidar = require("chokidar"); funcWatcher( "【会社番号】/【拠点番号】/hand/", "【会社ごとの転送用メールアドレス】", kyotenHand001EmailAdress ); //----------------------------------- // 2018/05/26 // shinichi yamazaki // node.jsでファイルの変更を検出して何かする // ファイル監視のための処理を関数化しました // 引数1:監視するディレクトリパス // 引数2:会社を特定するためのメールアドレス(メールアドレスである必要はあまりない) // 引数3:拠点とFAXモードを特定するためのメールアドレス(全社共通) //----------------------------------- function funcWatcher( pass, companyEmailAdress, kyotenEmailAdress) { // chokidarの初期化 var watcher = chokidar.watch( "【サーバーの監視先フォルダパス】" + pass, { ignored:/[\/\\]\./, persistent:true }); // イベント定義 watcher.on('ready',function(){ // 準備完了 console.log("ready watching..."); // ファイルの追加 watcher.on('add',function(path){ var options = { url : '【FAX転送用のPHP API】', method: 'POST', headers: headers, form: { 'companyEmailAdress': companyEmailAdress, 'kyotenEmailAdress': kyotenEmailAdress, 'mailTitle': "hello" } }; // FAX転送用のPHP APIの呼び出し request.post(options, function (error, response, body) { if (body) { var options = { url : '【通知用のPHP API】', method: 'POST', headers: headers, form: { 'idm': "", 'registerID': "-1", 'companyID': "", 'staffID': "", 'msg': "新しいFAXを受信しました", 'mode': "mode=6", 'groupID': "", 'smartPhoneName': body } }; // 通知用のPHP APIの呼び出し request.post(options, function (error, response, body) { if (body) { } if (error) { } }); console.log(body); } if (error) { console.log(error); } }); console.log(path + " added."); }); }); }サーバー側
FAX転送用のPHP APIfax_tenso.php<?php date_default_timezone_set('Asia/Tokyo'); // 現在日時をUNIXタイムスタンプを秒単位で取得する $now = time(); // 現在日時を YYYY/MM/DD hh:mm:ss の書式の文字列で取得する $now = date('Y/m/d H:i:s'); $companyEmailAdress = $_POST["companyEmailAdress"]; $kyotenEmailAdress = $_POST["kyotenEmailAdress"]; $subject = $_POST["mailTitle"]; $bodystructure = $_POST["bodystructure"]; // 変数宣言 $companyID = ""; $faxKyoten = ""; $faxMode = ""; $sendFlag = ""; $maxFaxID = ""; // FAX受信者リスト $faxPushList = NULL; $pushJsonArray = array(); require('common.php'); //----------------------------------------- // マッピング // 会社番号の取得 // 2018/05/03 yamazaki //----------------------------------------- $companyData = databaseGet( "SELECT". " companyID". " FROM MK_company". " WHERE". " faxEmail=N'".$companyEmailAdress."'" ); // 存在していないときの処理 if ($companyData == NULL) { echo "会社番号の取得に失敗しました。"; die('MSSQL Serer Connect Error'); } else { $companyID = $companyData[0]["companyID"]; } //----------------------------------------- // マッピング // 拠点情報の取得 // 2018/05/03 yamazaki //----------------------------------------- $kyotenData = databaseGet( "SELECT". " faxKyoten,". " sendFlag". " FROM MK_kyoten". " WHERE". " kyotenEmail=N'".$kyotenEmailAdress."'" ); // 存在していないときの処理 if ($kyotenData == NULL) { echo "拠点情報の取得に失敗しました。"; die('MSSQL Serer Connect Error'); } else { $faxKyoten = $kyotenData[0]["faxKyoten"]; $sendFlag = $kyotenData[0]["sendFlag"]; } if ($sendFlag == "0") { $faxMode = "auto"; } else { $faxMode = "hand"; } //----------------------------------------- // マッピング // FaxID最大値の取得 // 2018/05/06 yamazaki //----------------------------------------- $faxIDData = databaseGet( "SELECT". " MAX(faxID)+1 AS maxFaxID". " FROM MK_faxSend". " WHERE". " companyID=N'".$companyID."'" ); // 存在していないときの処理 if ($faxIDData == NULL) { echo "FaxID最大値の取得に失敗しました。"; die('MSSQL Serer Connect Error'); } else { $maxFaxID = $faxIDData[0]["maxFaxID"]; } //----------------------------------------- // マッピング // FAX受信者リストの取得 // 2018/05/06 yamazaki //----------------------------------------- $faxPushDate = databaseGet( "SELECT". " staffID". " FROM MK_staff". " WHERE". " companyID = N'". $companyID. "' AND". " faxRec = N'000'" ); // 存在していないときの処理 if ($faxPushDate == NULL) { echo "FAX受信者リストの取得に失敗しました。"; die('MSSQL Serer Connect Error'); } else { $faxPushList = $faxPushDate; } // 保存先のFAX受信リストを取得する。 $files = glob("../../../fax_data/get/dev/".$companyID."/".$faxKyoten."/".$faxMode."/*"); $list = array(); foreach ($files as $file) { if (is_file($file)) { $fileNamePath = explode("/", $file); $fileName = $fileNamePath[9]; $fileExte = explode(".", $fileName); error_log("ファイルの拡張子:".$fileExte[1], 0); // 拡張子がTIFの時にJPEGに変換する処理 if ($fileExte[1] == "tif" || $fileExte[1] == "tiff") { $dest = "./dst/"; $type = "jpg"; $image = new Imagick(); $image->readImage("【サーバーのFAX受信フォルダ ← ここに複合機からFAXが転送されるようにしてください】".$companyID."/".$faxKyoten."/".$faxMode."/".$fileName); $image->setImageFormat('jpg'); $image->writeImage("【サーバーのFAX転送先フォルダ ← Webアプリはここに参照しに行く】".$companyID."/".$faxKyoten."/".$fileExte[0].".jpg"); // 後処理 $image->clear(); $image->destroy(); // 変換前のファイルを削除する unlink("【サーバーのFAX受信フォルダ】".$companyID."/".$faxKyoten."/".$faxMode."/".$fileName); } else { //----------------------------------------- // 該当ファイルの移動 // 1つずつ //----------------------------------------- if (FALSE == rename( "../../../fax_data/get/dev/".$companyID."/".$faxKyoten."/".$faxMode."/".$fileName, "../../../fax_data/send/dev/".$companyID."/".$faxKyoten."/".$fileName )) { die('File Move Error'); } } //----------------------------------------- // マッピング // FAX送信情報の登録 // 2018/05/06 yamazaki //----------------------------------------- databaseSet( "INSERT INTO". " MK_faxSend(". " faxDateTime,". " companyID,". " faxFlag,". " subject,". " imagePass,". " faxID,". " faxKyoten". " ) VALUES(". " '".$now."',". " N'".$companyID. "',". " '" .$sendFlag. "',". " N'".$subject. "',". " N'".$fileExte[0].".jpg". "',". " '" .$maxFaxID. "',". " N'".$faxKyoten. "'". ")" ); foreach ($faxPushList as $faxPush) { //----------------------------------------- // マッピング // FAX送信情報履歴の登録 // 2018/05/06 yamazaki //----------------------------------------- databaseSet( "INSERT INTO". " MK_historyOption(". " companyID,". " category,". " ymdTime,". " staffID,". " flag,". " externNo,". " okiniFlag". " )". " VALUES(". " N'".$companyID. "',". " '6',". " '".$now."',". " N'".$faxPush["staffID"]."',". " '0',". " '" .$maxFaxID. "',". " '" .$sendFlag. "'". " )" ); //----------------------------------------- // マッピング // スタッフIDから通知先の情報の取得 // 2018/05/07 yamazaki //----------------------------------------- $pushData = databaseGet( "SELECT". " registerID,". " name". " FROM MK_smartPhone". " WHERE". " staffID = N'".$faxPush["staffID"]."' AND". " companyID = N'".$companyID."' AND". " name <> N'card'" ); //----------------------------------------- // 2018/05/15 yamazaki // 通知先の情報が取得できないときは何もしない //----------------------------------------- foreach ($pushData as $pushInfo) { $pushJsonArray[] = array( 'registerID' =>$pushInfo["registerID"], 'name' =>$pushInfo["name"] ); } } $maxFaxID++; } } // commonPushFuncメソッドで、対象者全員に通知を送る。 //(※FAXデータが複数存在するときに複数回通知が飛ぶこともありえる) header('Content-type: application/json'); // 指定されたデータタイプに応じたヘッダーを出力する print(json_encode($pushJsonArray)); exit(); ?>クライアント側
アプリ(iPhone, Android ガワネイティブ)運用時の問題点
①機能自体は実装できている。ただ、運用面でサーバーを再起動するとそのたびにシェルスクリプトを実行する必要がある。
②Node.jsのソースバージョン管理が出来ていない。対策案
①ひとまずは、Windows Serverのタスクスケジューラにログオン時にShell Scriptを自動起動で実行出来るようになればいいかな。他にもっと良い方法がありそうだが...
②Gitを使ってバージョン管理ができるといいな。まとめ
・Node.jsでフォルダの更新を監視し、トリガーからPHP APIの呼び出しができた。
・現状、実行ファイルsをPowerShellから手動でしか呼び出せていないので、なんとか他のやり方でスマートにやりたい。
・将来的には他の会社、複数の拠点で運用出来る様にしたい。(今後拡張が出来るように設計段階で盛り込み済み)
- 投稿日:2019-04-25T04:56:40+09:00
Raspberryに特定バージョンのNode.jsをインストールする
Raspberryに普通にNode.jsをインストールすると、Ver8.xがインストールされます(2019年4月時点)
例えば、Ver10.15.3をインストールしたいってことありませんか?
今回は、そんなお話です。Node.jsのインストール
Node.jsをインストールします。
Raspberry Pi Zeroは、Armv6なので通常の手順でインストールすると8.xがインストールされます。
10.15.3をインストールするには、以下の手順になります。sudo apt remove nodejs sudo apt autoremove VERSION=v10.15.3 DISTRO=linux-armv6l cd /usr/src sudo wget https://nodejs.org/dist/$VERSION/node-$VERSION-$DISTRO.tar.xz sudo mkdir -p /usr/local/lib/nodejs sudo tar -xJvf node-$VERSION-$DISTRO.tar.xz -C /usr/local/lib/nodejsホームディレクトリの.profileを開いて以下の行を追加します。
.profile# Nodejs VERSION=v11.13.0 DISTRO=linux-armv6l export PATH=/usr/local/lib/nodejs/node-$VERSION-$DISTRO/bin:$PATH.profileを有効にし、リンクを張ります。
. ~/.profile sudo ln -s /usr/local/lib/nodejs/node-$VERSION-$DISTRO/bin/node /usr/bin/node sudo ln -s /usr/local/lib/nodejs/node-$VERSION-$DISTRO/bin/npm /usr/bin/npm sudo ln -s /usr/local/lib/nodejs/node-$VERSION-$DISTRO/bin/npx /usr/bin/npxインストールしたnode.jsのバージョンを確認します。
node -v v10.15.3 npm -v 6.4.1 npx -v 6.4.1
- 投稿日:2019-04-25T01:56:54+09:00
anyenv から入れた nodenv で Node.js を入れたときのメモ
本記事について
「りあクト!」1を読みはじめ、本のように「anyenv 経由で ndenv をインストールして、ndenv で Node.js をインストール」しようと思ったら、anyenv で ndenv をインストールできないなど、状況が変わっていてハマったため残したメモです。
環境
- OS:macOS Mojave
- シェル:zsh
- homebrew インストール済み
- これまで nvm を使用
概要
結局今回は以下でインストールが完了しました:
- anyenv をインストール
- anyenv 経由で nodenv をインストール
- nodenv で Node.js をインストール
- これまで使っていた nvm のアンインストール
anyenv のインストール方法
GitHub - anyenv/anyenv: All in one for **env
README にはまず homebrew でのインストールが紹介されているが、ブログや Qiita を見ると多くが git clone でインストールしている。homebrew 版はかなり最近なんだろうか。
こちらでは両方の方法が紹介されている。
https://qiita.com/rinpa/items/81766cd6a7b23dea9f3canyenv のインストール
今回は homebrew でインストールしてみる。
README に従う。$ brew install anyenv $ anyenv init # Load anyenv automatically by adding # the following to ~/.zshrc: eval "$(anyenv init -)"
$ anyenv initを打ったら指示が出てきた。指示の通りに~/.zshrcに追記。
そしてターミナル再起動。すると(README の通り)次の warning が出る。ANYENV_DEFINITION_ROOT(/Users/xxx/.config/anyenv/anyenv-install) doesn't exist. You can initialize it by: > anyenv install --initwarning の通り実行。
$ anyenv install --init Manifest directory doesn't exist: /Users/xxx/.config/anyenv/anyenv-install Do you want to checkout ? [y/N]: y Cloning https://github.com/anyenv/anyenv-install.git master to /Users/xxx/.config/anyenv/anyenv-install... Cloning into '/Users/xxx/.config/anyenv/anyenv-install'... remote: Enumerating objects: 44, done. remote: Counting objects: 100% (44/44), done. remote: Compressing objects: 100% (39/39), done. remote: Total 44 (delta 1), reused 43 (delta 1), pack-reused 0 Unpacking objects: 100% (44/44), done. Completed!ndenv のインストール(できない)
anyenv で ndenv が入れられない。
$ anyenv install ndenv anyenv-install: definition not found: ndenvnodenv のインストール
ndenv の代わりに nodenv が推奨になっていたため、こちらをインストール。
$ anyenv install nodenv $ exec $SHELL -lNode.js のインストール
$ nodenv install -l $ nodenv install 12.0.0$ node -v v7.6.0 $ npm -v 4.1.2 $ nodenv global 12.0.0 $ node -v v7.6.0 $ npm -v 4.1.2インストールしたはずの node v12.0.0 が呼び出せない。
(nvm など使ってない方はここで呼び出せるはず?)nvm のアンインストール(必要な人のみ)
ここで、これまで nvm を使っていたことを思い出し、nvm をアンインストールすることに。
アンインストール方法は GitHub の README を参照。➜ ~rm -rf "$NVM_DIR"(つまり
~/.nvmの削除)そして
~/.zshrcの下記を削除:export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm確認:
$ node -v v12.0.0 $ npm -v 6.9.0呼び出せた
![]()
やっと本の続きが読める







