20211016のNode.jsに関する記事は12件です。

C#とNode.jsを連携する

C#とNode.jsを連携する EdgeJsを利用する EdgeJsを利用しNode.jsからC#通信ができます。その逆もできます。.net4.6のみ。まだ.netCoreには未対応のようです。 Node.js側 const edge = require('edge-js'); const helloWorld = edge.func('cs', function () {/* async (input) => { return ".NET Welcomes " + input.ToString(); } */}); helloWorld('Node.js', function (error, result) { if (error) throw error; console.log(result); }); C#側 NodeJsからC#のメソッドを実行しデーターを渡します edgeJsライブラリ 現在は更新されていません。メンテナンスを引き継いだプロジェクトが別にあります。 npm install edge edgeで読み込む const edge = require('edge'); フォークされたもの 現在も保守されている npm install edge-js edgeの後ろに-jsを付ける const edge = require('edge-js'); 説明 Node.jsにインストールされたモジュールを表示する npm list npm -v 環境構築 DockerFileの内容をみて必要なライブラリをインストールします。 Monoは必要ないです。 RiderのエディタからedgeJSモージュールをインストールする npm install後にエディタ上で 波線をクリックするとnode_moduleフォルダが生成され、edgeモジュールがインストールされる 動作に必要な設定 コマンド 有無 値 備考 EDGE_USE_CORECLR 必須 1 .NetCore用のedgeモジュールを利用する EDGE_NATIVE 必須 edge-js/build/Release/edge_coreclr.node 相対パスで設定する 絶対パスだとエラーが出る EDGE_DEBUG オプション 1 デバッグ表示 EDGE_APP_ROOT オプション Publishフォルダへのパス 外部Dll Nugetライブラリを利用する時に使う 相対パスで設定する 環境変数の設定の仕方 ターミナルから設定し実行する EDGE_NATIVE=edge-js/build/Release/edge_coreclr.node EDGE_USE_CORECLR=1 EDGE_DEBUG=1 node test.js RiderのNode.js設定画面から設定する EnviromentValueで設定します。 JSプログラムの中に書く var path = require('path'); const baseNetAppPath = path.join(__dirname, '/bin/Release/netstandard2.0/publish/'); process.env.EDGE_USE_CORECLR = 1; process.env.EDGE_DEBUG=1; process.env.EDGE_NATIVE='edge-js/build/Release/edge_coreclr.node'; //process.env.EDGE_APP_ROOT = baseNetAppPath; var edge = require('edge-js'); サンプルを実行 node_modules/edge-jsフォルダの中にSampleファイルがあり、いろいろ試せます。 デバッグ 3種類 C#側のデバッグ 実行ボタンでデバッグ エラーが緑文字で出る。C#側のCSファイルビルド状態、Dllファイルが読み込まれたかどうか Dllファイルがあるかアセンブリが読み込まれたかどうかなどいろいろ確認できます。 Node.js側のデバッグ 虫のアイコンでNode.js側がデバッグできます。Js側でブレイクポイントなどをしてデバッグします。 edge.jsを追加するとブレイクポイントでデバッグできるようになる ブレイクポイント追加する Debugger ConsoleとProcess Consoleでエラーログを見ることができます。 よく出るエラー Uncaught TypeError: edge.initializeClrFunc is not a function 一見JavaScript側のエラーのように見えるがC#側のエラーであることが多いです。C#側を確認するとよいです。 Error occurred during CoreCLR initialization node:internal/modules/cjs/loader:1168 return process.dlopen(module, path.toNamespacedPath(filename)); パスのどれかに絶対パスが含まれていると出るエラーになります。相対パスに直すと通ります。 環境変数の設定などで起きる ダイナミックライブラリの中に外部DllやNugetライブラリを利用する設定 プロジェクトフォルダに以下の値を追加する。 <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netcoreapp2.0</TargetFramework> <PreserveCompilationContext>true</PreserveCompilationContext> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> </PropertyGroup> <ItemGroup> <Reference Include="EdgeJs"> <HintPath>..\..\node_modules\edge-js\lib\bootstrap\bin\Release\netcoreapp1.1\EdgeJs.dll</HintPath> <Private>true</Private> </Reference> </ItemGroup> </Project> .NET5のところをクリックしAdd FromからもDllを追加できます Publishを設定する Publishを実行すると依存ファイル(dllなど)、Nugetから入れたDLLをすべて同じフォルダに書き出せます。 Publishフォルダへパスを通す。相対がよいです。 process.env.EDGE_APP_ROOT = ''; Nugetから必要ライブラリをインストール Microsoft.NETCore.DotNetHost Microsoft.NETCore.DotNetHostPolicy このライブラリには既に依存ファイルが設定されています 現在の状態 Dllファイルへのアクセス サンプルファイルのDllへはアクセスができましたが、DLLプログラムのの中にNugetのライブラリを入れると読み込まれない状態です。 DapperやMicoroSoftのSqliteライブラリなどが読み込まれない。NewtonSoftのJesonのライブラリは読み込め使えました。 EDGE_APP_ROOTにPublishまでの相対パスを通すとエラーが起きます。 読み込み方法がわかる方ご教授ください。 参考 続く
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Angular CLIインストール時のWARN解消

はじめに Angular CLIインストール時にWARNが出たので調べてみました。 2021年10月時点 環境 $ node -v v14.18.1 $ npm -v 8.1.0 Node.js(安定最新版) + npm(最新版) Angular CLIのインストール $npm i @angular/cli npm WARN EBADENGINE Unsupported engine { npm WARN EBADENGINE package: '@angular/cli@12.2.10', npm WARN EBADENGINE required: { npm WARN EBADENGINE node: '^12.14.1 || >=14.0.0', npm WARN EBADENGINE npm: '^6.11.0 || ^7.5.6', npm WARN EBADENGINE yarn: '>= 1.13.0' npm WARN EBADENGINE }, npm WARN EBADENGINE current: { node: 'v14.18.1', npm: '8.1.0' } npm WARN EBADENGINE } npm WARN EBADENGINE Unsupported engine { npm WARN EBADENGINE package: '@angular-devkit/architect@0.1202.10', npm WARN EBADENGINE required: { npm WARN EBADENGINE node: '^12.14.1 || >=14.0.0', npm WARN EBADENGINE npm: '^6.11.0 || ^7.5.6', npm WARN EBADENGINE yarn: '>= 1.13.0' npm WARN EBADENGINE }, npm WARN EBADENGINE current: { node: 'v14.18.1', npm: '8.1.0' } npm WARN EBADENGINE } npm WARN EBADENGINE Unsupported engine { npm WARN EBADENGINE package: '@angular-devkit/core@12.2.10', npm WARN EBADENGINE required: { npm WARN EBADENGINE node: '^12.14.1 || >=14.0.0', npm WARN EBADENGINE npm: '^6.11.0 || ^7.5.6', npm WARN EBADENGINE yarn: '>= 1.13.0' npm WARN EBADENGINE }, npm WARN EBADENGINE current: { node: 'v14.18.1', npm: '8.1.0' } npm WARN EBADENGINE } npm WARN EBADENGINE Unsupported engine { npm WARN EBADENGINE package: '@angular-devkit/schematics@12.2.10', npm WARN EBADENGINE required: { npm WARN EBADENGINE node: '^12.14.1 || >=14.0.0', npm WARN EBADENGINE npm: '^6.11.0 || ^7.5.6', npm WARN EBADENGINE yarn: '>= 1.13.0' npm WARN EBADENGINE }, npm WARN EBADENGINE current: { node: 'v14.18.1', npm: '8.1.0' } npm WARN EBADENGINE } npm WARN EBADENGINE Unsupported engine { npm WARN EBADENGINE package: '@schematics/angular@12.2.10', npm WARN EBADENGINE required: { npm WARN EBADENGINE node: '^12.14.1 || >=14.0.0', npm WARN EBADENGINE npm: '^6.11.0 || ^7.5.6', npm WARN EBADENGINE yarn: '>= 1.13.0' npm WARN EBADENGINE }, npm WARN EBADENGINE current: { node: 'v14.18.1', npm: '8.1.0' } npm WARN EBADENGINE } npm WARN deprecated har-validator@5.1.5: this library is no longer supported npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 WARNが発生 要求バージョンが合っていなかった。 npmのバージョン7.5.6に変更し、Angular CLIの再インストールを行う。 $npm i -g npm@7.5.6 $npm rm @angular/cli $npm i @angular/cli npm WARN deprecated har-validator@5.1.5: this library is no longer supported npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 har-validator@5.1.5 と request@2.88.2は廃止予定でAngular CLI側での対処待ち uuid@3.4.0Angular CLI側での対処待ち https://github.com/angular/angular-cli/issues/20994 Angular CLIのバージョン確認 $npm list @angular/cli@12.2.10 終わりに 開発が進むと対処が大変になる可能性があるので、WARNであっても押さえておきたい。 開発環境構築を急かされて後回しにされるような気もする。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React + Express + Docker の環境構築

Reactで作成した画面からExpressで作成したAPIを呼び、取得したデータを画面表示するところまでを構築していきます。 React/Expressはそれぞれ別のDockerコンテナで動作させます。 ディレクトリ app/  ├── docker/  │ ├── docker-compose.yml  │ └── Dockerfile  ├── backend/  └── frontend/ docker/ の2ファイルはホスト側で作成しますが、その他の backend/ と frontend/ 内のファイルは全てコンテナ側で作成していきます。 Docker Dockerfile と docker-compose.yml を作成し、コンテナを起動します。 ファイル作成 React、Express で共通で使う Dockerfile を1つ作成します。 Dockerfile FROM node:14 今回はひとまずnodeが動けば良いので何も設定していません。 次に docker-compose.yml を作成します。 docker-compose.yml version: '3' networks: react_express: driver: bridge services: frontend: # React用のコンテナ build: . container_name: front tty: true volumes: - ../frontend:/frontend working_dir: "/frontend" ports: - 3001:3000 networks: - react_express backend: # Express用のコンテナ build: . container_name: back tty: true volumes: - ../backend:/backend working_dir: "/backend" ports: - 3002:3000 networks: - react_express network : 2つのコンテナを同じネットワーク内に配置します。 volumes : 開発の便宜上、ホストとコンテナでファイル共有しています。 ports : frontend、backendの各サーバ用のポート 3000 を、それぞれホストのポート 3001、3002 に転送しています。 コンテナの起動 コンテナを起動します。 $ cd docker/ $ docker-compose up -d ... $ docker-compose ps back docker-entrypoint.sh node Up 0.0.0.0:3002->3000/tcp,:::3002->3000/tcp front docker-entrypoint.sh node Up 0.0.0.0:3001->3000/tcp,:::3001->3000/tcp UpとなっていればOKです。 Express (Backend) プロジェクト作成 docker exec を使って、Express用のコンテナ (back) に入ります。 $ docker exec -u node -it back /bin/bash package.json を作成します。 $ npm init -y Expressをインストールします。 $ npm install express APIの作成 index.js を作成します。 index.js const express = require('express'); const app = express(); const port = 3000; app.get('/user', (req, res) => { res.json([{ id: 1, name: "Taro" }, { id: 2, name: "Jiro" }]); }); app.listen(port, () => console.log(`Server running on port ${port}`)); /user にリクエストが来たときに、jsonデータを返すようにしています。 Expressサーバの起動 準備ができたので、Expressサーバを起動します。 $ node index.js Server running on port 3000 React (Frontend) プロジェクト作成 別のターミナルを立ち上げ、docker exec を使って、React用のコンテナ (front) に入ります。 $ docker exec -u node -it front /bin/bash create-react-app コマンドを使って、プロジェクトを作成します。 (ドットを付けることで、ディレクトリ直下に作成できます) $ npx create-react-app . Proxyの設定 Dockerのネットワーク環境における Front/Backend の各オリジン ( http://xxx:yy )は、 Frontend : http://frontend:3000 Backend : http://backend:3000 のように異なるため、CORS (Cross-Origin Resource Sharing) の設定をする必要があります。 ここでは、Front側に Proxy を使う方法で回避します。以下2パターンのどちらかを使います。 方法1: package.json に proxy を設定する package.json に以下を追記します。 pacage.json "proxy": "http://backend:3000", この設定があると、text/html 以外のヘッダのリクエストを proxy のアドレスを origin としてリクエストするようになるため、Same-Origin として認識されます。 方法2: http-proxy-middleware を使う 複数の proxy を設定したい場合にはこちらの方法を使います。 src/setupProxy.js を作成します。 src/setupProxy.js const proxy = require('http-proxy-middleware') module.exports = function(app) { app.use(proxy('/user', { target: 'http://backend:3000' })) } この設定により、Reactアプリに対して /user にリクエストが来たときに http://backend:3000 にリクエストが飛ぶことになり、方法1と同様に Same-Origin として通信できます。 app.use(proxy()) は複数記述できるため、リクエストのパスにより別の proxy に分けて設定することもできます。 ちなみに create-react-app は、npm start の実行時に setupProxy.js を自動で読み込んで処理をするようになっているため、他のファイルにimportをする必要はありません。(ただし、npm run buildでは機能しません。) 画面の作成 src/App.js を以下に編集します。 src/App.js import { useEffect, useState } from 'react'; const App = () => { const [users, setUsers] = useState([]); useEffect(() => { fetch('/user') .then(res => res.json()) .then(data => { setUsers(data); }).catch(err => { console.log(err) }); }, []); return ( <div> {users.map((user, index) => <p key={index}>{ user.name }</p> )} </div> ); } export default App; 画面読み込み時に fetch('/user') が実行され、Proxyの設定によりExpressサーバ ( http://backend:3000/user ) にリクエストが送られます。 このAPIから取得したデータを users ステートに格納し、画面に表示します。 Reactサーバの起動 Reactサーバを起動します。 $ yarn start ホスト側のブラウザで http://localhost:3001/ にアクセスすると、 Taro Jiro が画面に表示されることが確認できました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Azure Web PubSub と Node.js を組み合わせた軽いお試し

この記事は、以下の続きにあたる内容です。 ●Azure Web PubSub を試してみるための下調べ(JavaScript を利用する方向で) - Qiita  https://qiita.com/youtoy/items/c1c9c2893e0e0fe29703 記事執筆時点でプレビュー版の「Azure Web PubSub」を使ってみる話で、Node.js のプログラムと組み合わせてみたという内容になっています。 サンプルプログラムを使ったお試し 前の記事でも引用していた以下の記事の手順を見つつ、サンプルアプリを使った動作確認を行っていきます。 ●Azure Web PubSub でリアルタイムメッセージングアプリを作ろう #Azure リレー | cloud.config Tech Blog  https://tech-blog.cloud-config.jp/2021-05-11-azure-web-pubsub-azure/ 少し UI の見た目が違う部分などはありましたが、上記の手順通りに進めていき、以下のサンプルアプリを使うところまで進めていきます。 ●A Simple Client-Side WebSocket Chat  https://azure.github.io/azure-webpubsub/demos/clientpubsub.html 1つだけ最初に軽くハマった点があり、「クライアント URL ジェネレーター」の「ハブ」の部分にデフォルトの日本語の文字列が入っていた状態で、「クライアント アクセス URL」を生成すると、その後の「Simple Client-Side WebSocket Chat」を使うところの接続周りで失敗しました。 そのハブの名前の部分を英語の文字列に変えて試したところ、以下のようにうまく動作させられました。 こちらのサンプルを使って、PubSub のお試しができた!●A Simple Client-Side WebSocket Chat https://t.co/guE4kW368s pic.twitter.com/zxkeu64TLB— you (@youtoy) October 16, 2021 Node.js のプログラムと組み合わせる 上記の手順で Azure側の動作確認ができたので、今度は Node.js のプログラムと Azure との間のメッセージングを試していきます。 前回の記事にも掲載していた、以下の公式サンプルを使っていきます。 ●azure-webpubsub/samples/javascript/pubsub at main · Azure/azure-webpubsub  https://github.com/Azure/azure-webpubsub/tree/main/samples/javascript/pubsub サンプルプログラムで「ws と @azure/web-pubsub」または「@azure/web-pubsub」が使われています。 とりあえず、これらをインストールしておきます。 $ npm i @azure/web-pubsub ws そして、サンプルに少し変更を加えたものを動かしてみます。 とりあえずのお試しなので接続文字列等をソースコード中に直書きをしてしまってますが、もちろん、このあたりは別で読み込むようにしたほうが良いです。 const WebSocket = require('ws'); const { WebPubSubServiceClient } = require('@azure/web-pubsub'); const connectionString = '【Endpointで始まる「接続文字列」】'; const hubName = '【ハブの名前】'; async function main() { let serviceClient = new WebPubSubServiceClient(connectionString, hubName); let token = await serviceClient.getAuthenticationToken(); let ws = new WebSocket(token.url); ws.on('open', () => console.log('connected')); ws.on('message', data => console.log(data));; } main(); const { WebPubSubServiceClient } = require('@azure/web-pubsub'); const connectionString = '【Endpointで始まる「接続文字列」】'; const hubName = '【ハブの名前】'; const message = 'Hello!!'; let serviceClient = new WebPubSubServiceClient(connectionString, hubName); serviceClient.sendToAll(message, { contentType: "text/plain" }); ちなみに、接続文字列は Azureポータル上で、以下に表示されているものになります。 上記のプログラムを動作させた結果がこちらです。 Node.js のプログラムでの PubSub も成功!先ほどのサンプルアプリ上にもメッセージが表示された!(Node.js のプログラムのほうはテキストになってないけどw) pic.twitter.com/tSqi8X2cy9— you (@youtoy) October 16, 2021 Node.js のプログラムでの出力が「Buffer ...」となってしまっているので、元のソースコードの出力部分を以下のように書きかえました。 ws.on('message', data => console.log(data.toString())); Node.js の Subscribe のプログラム出力を、toString で文字列にして、こちらも想定通りの出力に。 pic.twitter.com/q5IoLbBhOC— you (@youtoy) October 16, 2021 おわりに 今回、Azure Web PubSub と Node.js を組み合わせて PubSub を軽く試してみて、無事に動かすことができました。 この後は、Node.js のプログラムに手を加えてサービス間・デバイス間連携を何か試すか、以下のサンプルの「functions」で気になった「/client/nodeclient/」あたりを試せればと思っています。 ●azure-webpubsub/samples at main · Azure/azure-webpubsub  https://github.com/Azure/azure-webpubsub/tree/main/samples
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Sequelizeを使う際のurl設定について

Node.jsのORマッパーを実現するライブラリである、sequelizeを使って、RDBMSに接続する際のurlの設定方式についてのメモ。 前提 postgreSQLはDockerにてローカルに起動 docker run --name postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=sample_db -p 5432:5432 postgres:12 Version "sequelize": "^6.6.5" 確認結果 OK const url = process.env.DATABASE_URL || "postgres://postgres:postgres@localhost:5432/sample_db"; OK (port番号を省略) const url = process.env.DATABASE_URL || "postgres://postgres:postgres@localhost/sample_db"; NG (シングルクォートで記載) const url = process.env.DATABASE_URL || 'postgres://postgres:postgres:@localhost:5432/sample_db'; NG (改行を含む) const url = process.env.DATABASE_URL || "postgres://postgres:postgres:@localhost:5432/sample_db"; NGの場合は、以下のように、認証エラーとなる。 postgreSQL側のpeer認証の設定の問題では無いので、注意。 ConnectionError [SequelizeConnectionError]: password authentication failed for user "postgres"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ES2022のArray.prototype.atは今の所遅い (2021/10/16時点)

Array.prototype.atは何ができるの Pythonのように, 負数を指定すると配列の後ろから取得できます. 特に最後尾の数個や, 文字列での末尾からの指定など, 待ち望まれていた機能です. (String.prototype.atもあります) const arr = [1, 2, 3] console.log(arr.at(-1)); // 3 速度 普通の添字で指定と速度を比べてみます. バージョンは > node -v v16.9.0 ソース const arr = [...Array(1000*1000)].map((_, i) => i); // for内の余分な計算は取っ払いたいので先に const len = arr.length; const len2 = len - 1; const nlen = -len; // [] 昇順 { const startTime = (new Date()).getTime(); for (let n = 0; n < 100; ++n) { for (let i = 0; i < len; ++i) { arr[i]; } } const endTime = (new Date()).getTime(); console.log(`インデックス昇順: ${endTime - startTime}ms`); } // [] 降順 { const startTime = (new Date()).getTime(); for (let n = 0; n < 100; ++n) { for (let i = len2; i >= 0; --i) { arr[i]; } } const endTime = (new Date()).getTime(); console.log(`インデックス降順 ${endTime - startTime}ms`); } // at 昇順 { const startTime = (new Date()).getTime(); for (let n = 0; n < 100; ++n) { for (let i = 0; i < len; ++i) { arr.at(i); } } const endTime = (new Date()).getTime(); console.log(`at昇順 ${endTime - startTime}ms`); } // at 降順 { const startTime = (new Date()).getTime(); for (let n = 0; n < 100; ++n) { for (let i = -1; i >= nlen; --i) { arr.at(i); } } const endTime = (new Date()).getTime(); console.log(`at降順 ${endTime - startTime}ms`); } 結果 インデックス昇順: 47ms インデックス降順 82ms at昇順 4189ms at降順 4462ms びっくりするほど遅いです. Chromeでも大体同じ傾向だったため, Nodejsの実装が特別悪いというわけでもなさそうです. polyfillのほうが大幅に速い? からコードを持ってきて, 簡易的に試してみます. Array.prototype.myat = function (n) { // ToInteger() abstract op n = Math.trunc(n) || 0; // Allow negative indexing from the end if (n < 0) n += this.length; // OOB access is guaranteed to return undefined if (n < 0 || n >= this.length) return undefined; // Otherwise, this is just normal property access return this[n]; } // myat 昇順 { const startTime = (new Date()).getTime(); for (let n = 0; n < 100; ++n) { for (let i = 0; i < len; ++i) { arr.myat(i); } } const endTime = (new Date()).getTime(); console.log(`myat昇順 ${endTime - startTime}ms`); } // myat 降順 { const startTime = (new Date()).getTime(); for (let n = 0; n < 100; ++n) { for (let i = -1; i >= mlen; --i) { arr.myat(i); } } const endTime = (new Date()).getTime(); console.log(`myat降順 ${endTime - startTime}ms`); } myat昇順 139ms myat降順 101ms 速いです. 一瞬バグではないかと思いましたが, 添字にNaNや文字列を入れたりしても挙動は合っていたので間違いではないようです. ループ数も100で合っています. 最初は遅い理由を関数のオーバーヘッドガーや単純に処理が多いからーなどと考えていましたが, そう簡単ではないようです. この先は実装を解明してもらえる方に… チラッ 現状組み込みのArray.prototype.atがびっくりするくらい遅いだけで, 本来は添字に近い性能が出るのではないかと思います. Webアプリ開発における普段使いでは大きな影響はないと思いますが, 将来的によく使う機能になると思うので今後の性能改善に期待です. 全体ソース const arr = [...Array(1000*1000)].map((_, i) => i); const len = arr.length; const len2 = len - 1; const nlen = -len; Array.prototype.myat = function (n) { // ToInteger() abstract op n = Math.trunc(n) || 0; // Allow negative indexing from the end if (n < 0) n += this.length; // OOB access is guaranteed to return undefined if (n < 0 || n >= this.length) return undefined; // Otherwise, this is just normal property access return this[n]; } // [] 昇順 { const startTime = (new Date()).getTime(); for (let n = 0; n < 100; ++n) { for (let i = 0; i < len; ++i) { arr[i]; } } const endTime = (new Date()).getTime(); console.log(`インデックス昇順: ${endTime - startTime}ms`); } // [] 降順 { const startTime = (new Date()).getTime(); for (let n = 0; n < 100; ++n) { for (let i = len2; i > 0; --i) { arr[i]; } } const endTime = (new Date()).getTime(); console.log(`インデックス降順 ${endTime - startTime}ms`); } // at 昇順 { const startTime = (new Date()).getTime(); for (let n = 0; n < 100; ++n) { for (let i = 0; i < len; ++i) { arr.at(i); } } const endTime = (new Date()).getTime(); console.log(`at昇順 ${endTime - startTime}ms`); } // at 降順 { const startTime = (new Date()).getTime(); for (let n = 0; n < 100; ++n) { for (let i = -1; i >= nlen; --i) { arr.at(i); } } const endTime = (new Date()).getTime(); console.log(`at降順 ${endTime - startTime}ms`); } // myat 昇順 { const startTime = (new Date()).getTime(); for (let n = 0; n < 100; ++n) { for (let i = 0; i < len; ++i) { arr.myat(i); } } const endTime = (new Date()).getTime(); console.log(`myat昇順 ${endTime - startTime}ms`); } // myat 降順 { const startTime = (new Date()).getTime(); for (let n = 0; n < 100; ++n) { for (let i = -1; i >= nlen; --i) { arr.myat(i); } } const endTime = (new Date()).getTime(); console.log(`myat降順 ${endTime - startTime}ms`); } ```  </div></details>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Node.js】Qiita デイリー LGTM 数ランキング【自動更新】

他のタグ AWS Android Docker Git Go iOS Java JavaScript Linux Node.js PHP Python Rails React Ruby Swift TypeScript Vim Vue.js 初心者 集計について 期間: 2021-10-17 ~ 2021-10-18 GitHub スターをもらえるととっても励みになります LGTM 数ランキング 1 位: [メモ] Node.jsで開発するにあたっての基礎知識まとめ JavaScript Node.js 14 LGTM 20 ストック @from_Unknown さん ( 2021-10-17 19:56 に投稿 ) 2 位: LINE Bot のカルーセルテンプレートを Firebase Functions で実装する方法について Node.js Firebase linebot cloudfunctions Firestore 5 LGTM 0 ストック @gremito さん ( 2021-10-17 14:48 に投稿 )
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

webpack入門(Node.jsの導入からjsファイルのバンドルまで)

はじめに 業務でwebpackを使用する機会があるので、学習したことをまとめていきます。 今回は、Node.jsのインストール・jsファイルのバンドル・Loaderを使ってcssのバンドルを実際に行います。 ※一度にいろいろやると分からなくなるので、今回はjsファイルのバンドルまで行います。次回Loaderを用いてcssやscssファイルをバンドルする手順についてまとめます。 以前の学習まとめはこちらpackage.jsonとpackage-lock.jsonのバージョン指定や必要性について 今回使用するツールなどのバージョン Node.js:12.16.3 npm:6.14.4 webpack: 5.58.1 webpack-cli: 4.9.0 webpack導入の前に 図が多くわかりやすかったので、こちらの記事を見ておくとイメージが少しつくかと思います。 webpack学習の基本のき 前準備 1.Node.js/npmの導入 webpackを使用するには、Node.jsが必要になるためまずはインストールをしていきます。Node.jsをインストールする際に、npmもインストールされます。 Node.jsダウンロードサイト インストールが完了したら、以下のコマンドで確認しバージョンが表示されればOK。 node -v v12.16.3 npm -v 6.14.4 2.プロジェクトディレクトリの作成とpackage.jsonの作成 Node.jsがインストールできたら、次はプロジェクト用のディレクトリを用意します。 作成したディレクトリに移動したら、以下のコマンドでpackage.jsonを作成します。 色々設定について聞かれますが、特に気にせずEnterでOK。 npm init 上記のようにすべてEnterで問題ない場合は、以下のようにオプションを付けることで何も聞かれることなくpackage.jsonが作成できます。 npm init -y 3.webpack/webpack-cliのインストール 今回はwebpackを使いたいということで、webpackとwebpack-cliの2つをとりあえずインストールします。webpackとwebpack-cliについての細かいところはこちらを →webpack/webpack-cli 以下のコマンドを実行。 npm install --save-dev webpack npm install --save-dev webpack-cli インストールを行うと、ディレクトリ内にnode_modulesが作成されます。 4.webpack.config.jsとバンドルするためのjsファイルを準備 webpack.config.jsとは、webpackの設定ファイルです。 このファイルで、エントリポイントやバンドルしたファイルの出力場所などなどを記載していきます。 まずは、エントリポイント用のjsファイルを作成します。 今回はindex.jsとします。中身に関しては後ほど。 次に、webpack.config.jsを作成します。 内容は以下のように。 webpack.config.js const path = require('path') module.exports = { entry: path.resolve(__dirname, "index.js"), //エントリポイントであるファイルのパスを指定 output: { path: path.resolve(__dirname, 'dist'), //バンドルしたファイルの出力先のパスを指定 filename: 'bundle.js' //出力時のファイル名の指定 } } const path = require('path') pathは、Node.jsにデフォルトであるモジュール。 path.resolve()は、引数のパスをもとに絶対パスを返します。 公式ドキュメントを読んだのですがよくわからなかったので以下のサイトも参考にしました。 絶対パスを返す。 引数の後ろから順に評価、結合していく。 途中で絶対パスが完成したら結合途中でも処理を抜ける。 path.resolve('/a', '/b', '/c'); => /c path.resolve('/a', '/b', 'c'); => /b/c path.resolve('/a', 'b', 'c'); => /a/b/c path.resolve('a', 'b', 'c'); => current_path/a/b/c path.resolve(__dirname, 'a', 'b', 'c'); => current_path/a/b/c 引数の右から順位処理をしていき、”/”に当たった時点で絶対パスが作成されるため、そこで処理が終了する。つまり引数の文字列の先頭に”/”がある場合、そこまでで処理が終わる。 最後まで絶対パスができなかった場合は実行時のcurrent_pathを付けて返す。 引用元:path.resolve()の使い方 そのため、今回であれば entryは、current_path/index.js output(出力する際に作成される)は、current_path/dist/bundle.js というようになります。 参考 Node.js v12.22.7 Documentation 現在のディレクトリ構成はこんな感じ practice ├─ node_modules ├─ index.js ├─ package.json ├─ package-lock.json └─ webpack.config.js 先ほどの、webpack.config.jsの出力設定だとpracticeディレクトリの直下にdistというディレクトリが作成され、そこにbundle.jsというバンドルファイルが作成されます。 5.html、jsファイルを用意する 前準備は大体できたので、あとはバンドルする用のファイルを用意する。 js用ディレクトリを用意し、jsディレクトリには、sum.jsとdevide.jsを作成します。 現在のディレクトリ構成は以下の通りです。 practice ├─ node_modules ├─ src | └─ js  | ├─ devide.js | └─ sum.js ├─ index.html ├─ index.js ├─ package-lock.json ├─ package.json └─ webpack.config.js 各ファイルに処理を記載します。 index.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>webpack学習</title> <!-- バンドルしたファイルを読み込む --> <script src="dist/bundle.js"></script> </head> <body> <p class="message">webpack学習中!!</p> </body> </html> devide.js export default function hello(a, b) { return a / b; } sum.js export default function sum(a, b) { return a + b; } index.js import sum from './src/js/sum.js'; import devide from './src/js/devide.js'; var a = 10; var b = 2; var result = 'sum()の結果は' + sum(a, b) + ' devide()の結果は' + devide(a, b); alert(result); これでファイルの準備はOK。 今回は、足し算結果を出力する処理が記載されたsum.jsと割り算結果を出力する処理が記載されたdevide.jsをバンドルする。 webpack.config.jsで設定したエントリーポイントがindex.jsであるため、このファイル内でバンドルしたいjsファイルを読み込む。 6.scriptsにコマンドを追加 package.jsonのscriptsでコマンドを追加することで、簡単にコマンド実行が出来るようになります。以下のようにコマンドを追加します。 package.json { "name": "practice", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "version": "webpack -v", "dev": "webpack --mode development", "build": "webpack --mode production", "watch": "webpack --mode development --watch", "test": "echo \"Error: no test specified\" && exit 1", }, "author": "", "license": "ISC", "devDependencies": { "webpack": "^5.58.1", "webpack-cli": "^4.9.0" } } scriptsでは「コマンド名:実際に実行したいコマンド」のように記載します。 基本的に実行するにはnpm run コマンド名で実行します。 試しに、npm run versionと実行すると、以下のようにwebpackなどのバージョンが確認できます。 webpack: 5.58.1 webpack-cli: 4.9.0 webpack-dev-server not installed 他の設定したコマンドのざっくりした説明は以下の通り。 webpack --mode developmentは、開発用のビルド webpack --mode productionは、本番環境用のビルド webpack --mode development --watchは開発用のビルドで、ファイルの変更を検知して自動でビルドしてくれる。 7.いざバンドル! 以下のコマンドでバンドルします。 npm run dev バンドルが完了したら、index.htmlをブラウザで確認します。 以下のように、アラートで処理結果が表示されればバンドル成功です。 まとめ 今回はNode.jsの導入からwebpackを用いたjsファイルのバンドルまでをやってみました。以前まではwebpackは難しいものというイメージがありましたがわかってくると便利そうだなと思いました。 いきなり実務で使われている、webpack.config.jsを見てしまうと設定が色々あってくじけてしまうのでぜひ今回のように少ない設定項目から始めるといいのではないかと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

これからWeb開発を始める人に知ってほしいGithubプロジェクト

はじめに この記事ではProgrammingを始める方や学生でこれからエンジニアを目指されている方々に私がよく紹介しているGithubのプロジェクトを紹介しています。どのプロジェクトも英語ですが、どのプロジェクトもきっと皆さんのキャリアにとって役に立つはずです。ぜひお役立ていただければと思います。 1. Web Developer Roadmap このプロジェクトではWeb Developerになるまでにどのような知識が必要なのかを体型的にまとめてくれています。 これはFrontendのRoadmapの例ですが、以下のようにTopicにつき質問がいくつかあるのでそれに答えられるようになっていけば必然とFrontend開発を学ぶことができます。 HPもあり、こちらの方だとより詳しく言語ごとのロードマップなども紹介されています。 2. AI Expert Roadmap こちらはWeb開発ではないけど似たようなプロジェクトがあったので参考までに。 AIを学びたい方向けのロードマップ。 3. First Contributions エンジニアだろうとデータサイエンティストだろうとGithubを使った共同開発はもはや避けては通れません。 First ContributionsではどのようにしてPull Requestを作りコミュニティやチームに貢献しするのかを実際に体験することができます。GitHubでPull Requestを作ったことがない人は1度こちらで練習しておきましょう。 ちなみにこちらのプロジェクトは日本語に翻訳されています。 4. RealWorld RealWorldはMedium.comのクローンアプリをデモアプリとして提供しています。 100を超える言語やフレームワークごとにそれぞれ実装されており、自分が学びたい言語、フレームワークの実務レベルの使い方をデモアプリを再現することで学ぶことができます。 難易度は少し高いですが、お勧めです。私は今でも新しいフレームワークについて学ぶ機会があると一度こちらでフレームワーク独特の書き方や作法などを確認したりしています。 5. Web Development for Beginner Microsoftが提供しているウェブ開発のために学習教材。Microsoftが提供しているだけあって教材の質はかなり高い印象です。HTML,CSS, JSがメインのコースです。 6. Awesome Programmingの世界では分野ごとの便利なライブラリや情報を集めたAwesomeというレポジトリがGithub上に存在します。基本的にどの分野でもAwesomeが作られており、自分がこれから勉強する言語、フレームワークの情報を集めたりするのにお勧めです。 7. Coding Interview University こちらはコーディングインタビューのための情報をまとめたもの。 就職が近い方は目を通しておくといいでしょう。 終わりに どのプロジェクトも有益ですので自分に合ったものをぜひ使ってみてください。 これらのプロジェクトは知っているだけで違うとおもいますので、これから学習を始める方の一助になれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GR-ROSE と Node.js のプログラムの間でシリアル通信(一方向)

表題の件を試した際のメモです。 GR-ROSE と Node.js のプログラムとの間で、一方向のシリアル通信を軽く試してみます。 GR-ROSE側 以下の公式のプログラムを動かしてみます。 ●GR-ROSE チュートリアル:IDE for GRでスケッチ | Renesas  https://www.renesas.com/jp/ja/products/gadget-renesas/boards/gr-rose/project-arduino-sketch-ide-gr 開発には IDE for GR を使う形で、手順は上記のページ内のとおりです。 書き込みをする際、GR-ROSE のリセットボタンを押して USBドライブとして認識させてから行う、というのがあったりします。 プログラムは以下で、サンプルほぼそのままです。 遅延の設定だけ、100ミリ秒から 1秒に変えています。 void setup() { // put your setup code here, to run once: Serial.begin(9600); pinMode(PIN_LED1, OUTPUT); } void loop() { // put your main code here, to run repeatedly: digitalWrite(PIN_LED1, LOW); delay(1000); digitalWrite(PIN_LED1, HIGH); delay(1000); Serial.println("hello"); } こちらの動作確認を、IDE for GR のシリアルモニタで行っておきましょう。 以下のように、一定時間ごとに「hello」という文字列が出てくれば OK です。 Node.js側 Node.js側は、以下を使ったりするとシリアル通信を扱えるようになります。 ●serialport - npm  https://www.npmjs.com/package/serialport かなり前ですが、以下の記事に出てくるお試しの際に、利用したことがありました。 ●#toio を Alexa や micro:bit から操作する 〜概要編〜(JavaScriptライブラリを使ってみた) - Qiita  https://qiita.com/youtoy/items/0ee56f5395e3f4c72c51 今回は、読み取りだけできれば良いので、公式ドキュメントの Readline Parser のサンプルを利用します。 以下で「【自分の環境に合わせて変更】」と書いている部分は、ご自身の環境の設定に合わせて変更してください。 const SerialPort = require('serialport') const Readline = require('@serialport/parser-readline') const port = new SerialPort('/dev/【自分の環境に合わせて変更】') const parser = port.pipe(new Readline({ delimiter: '\r\n' })) parser.on('data', console.log) GR-ROSE は PC につないだまま動作させ、その状態でプログラムを実行すると、以下の出力が得られました。 おわりに とりあえず、公式サンプルを流用した GR-ROSE と Node.js のプログラムの間でシリアル通信を試しました。 さらに、両方のプログラムに処理を追加していって、何か面白そうなものを作っていければと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Azure Web PubSub を試してみるための下調べ(JavaScript を利用する方向で)

この記事は、以下の「Azure Web PubSub」に関する記事です。 どうやら、WebSocket を通信に使って、パブリッシュ - サブスクライブ型のメッセージングができるものらしく、「MQTTっぽい感じなのかな?」と気になりました。 ●Azure Web PubSub – WebSocket Web パブリッシング | Microsoft Azure  https://azure.microsoft.com/ja-jp/services/web-pubsub/ 過去に書いた Qiita の記事でも、リアルタイム通信系で WebSocket・MQTT は何度も登場していて、リアルタイム通信周りの技術は非常に気になるところです。 この Azure Web PubSub は、記事執筆時点では以下の公式ページのサービス名の部分に書かれているように、「プレビュー」という位置付けのようです。 調べてみた内容 とりあえず、ググって出てきた記事をいくつか見てみました。 Azure Web PubSub でリアルタイムメッセージングアプリを作ろう #Azure リレー | cloud.config Tech Blog Azure Web PubSub Public Preview - ほりひログ 公式の情報も見てみたり。 WebSocket と Azure Web PubSub を使用してリアルタイム アプリを簡単に構築する (プレビュー段階) | Azure のブログと更新プログラム | Microsoft Azure クイックスタート - ブラウザーから Azure Web PubSub インスタンスに接続する | Microsoft Docs チュートリアル - WebSocket API と Azure Web PubSub サービス SDK を使用してメッセージの発行とサブスクライブを行う | Microsoft Docs サクッと試す流れ ここまで情報を見ていって、とりあえずサクッとお試しをするには、以下の内容に手をつけるのが良さそうでした。 デモアプリ上で試す 上で書いていた 1つ目の記事の中で、ポータル上で情報を取得し、以下のデモアプリを使って簡単に試せそうな話が登場していました。 ●A Simple Client-Side WebSocket Chat  https://azure.github.io/azure-webpubsub/demos/clientpubsub.html その説明が出ていたので、具体的には以下の画像の部分です。 とりあえず、上記のインターフェースを使った PubSub を試すのが、ブラウザ上だけで完結して簡単そうでした。 JavaScriptライブラリを併用する ポータル上での動作確認が無事に行えたら、自分が書いたプログラムから試してみたいところです。 下調べをした中で、公式の GitHub の以下のサンプルページがひっかかりました。 ●azure-webpubsub/samples at main · Azure/azure-webpubsub  https://github.com/Azure/azure-webpubsub/tree/main/samples 複数の言語用のサンプルがあるようですが、普段、自分がやっている内容的には JavaScript が良いので、それを見てみます。 ●azure-webpubsub/samples/javascript at main · Azure/azure-webpubsub  https://github.com/Azure/azure-webpubsub/tree/main/samples/javascript こんな感じでサンプルが複数あるようですが、pubsub がシンプルそうで、最初に試すのに良さそうでした。 プログラム的には、こんな感じ。 subscribe.js const WebSocket = require('ws'); const { WebPubSubServiceClient } = require('@azure/web-pubsub'); async function main() { if (process.argv.length !== 4) { console.log('Usage: node subscribe <connection-string> <hub-name>'); return 1; } let serviceClient = new WebPubSubServiceClient(process.argv[2], process.argv[3]); let token = await serviceClient.getAuthenticationToken(); let ws = new WebSocket(token.url); ws.on('open', () => console.log('connected')); ws.on('message', data => console.log(data));; } main(); publish.js const { WebPubSubServiceClient } = require('@azure/web-pubsub'); if (process.argv.length !== 5) { console.log('Usage: node publish <connection-string> <hub-name> <message>'); return 1; } let serviceClient = new WebPubSubServiceClient(process.argv[2], process.argv[3]); // by default it uses `application/json`, specify contentType as `text/plain` if you want plain-text serviceClient.sendToAll(process.argv[4], { contentType: "text/plain" }); 気になったサンプル1: videoshare ぱっと見た中で、「videoshare」というやつが、ものすごく気になる... バイナリデータの PubSub。 気になったサンプル2: functions 以下も JavaScript で扱えそうな感じのもので、気になりました。 名前的に、Azure Functions で扱うようなものっぽいです。 ●azure-webpubsub/samples/functions/js at main · Azure/azure-webpubsub  https://github.com/Azure/azure-webpubsub/tree/main/samples/functions/js ●azure-webpubsub/samples/functions/client/nodeclient at main · Azure/azure-webpubsub  https://github.com/Azure/azure-webpubsub/tree/main/samples/functions/client/nodeclient おわりに Azure に関する調べものをしていて見かけた「Azure Web PubSub」について、お試しをする前段階の話を記事にしてみました。 この後は、JavaScriptライブラリを使って、過去に WebSocket・MQTT を使ってやっていたようなサービス間連携・デバイス連携などができそうか、調査・お試しを続けていければと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.jsでディレクトリを再帰的に作成/削除するのにmkdirpやrimrafはもう必要ない

Node.jsでディレクトリを再帰的に作成/削除するためのnpmパッケージとしてmkdirpやrimrafがありますが、現代のNode.js(v14.14.0以降)において、それらはもはや必要ありません。 ディレクトリを再帰的に作成する方法 mkdir -pのようにディレクトリを再帰的に作成するには、fs.mkdirのrecursiveオプションを使います。 コールバックAPIを使う場合: const fs = require('fs') const dir = process.argv[2] console.log(`try creating ${dir} directory`) fs.mkdir(dir, { recursive: true }, (e) => { if (e) { console.error(e) } else { console.log(`created ${dir} directory`) } }) Promise APIを使う場合: const fs = require('fs').promises const dir = process.argv[2] console.log(`try creating ${dir} directory`) fs.mkdir(dir, { recursive: true }) .then(() => console.log(`created ${dir} directory`)) .catch((e) => console.error(e)) なお、fs.mkdirにrecursiveオプションが追加されたのはv10.12.0です。 ディレクトリを再帰的に削除する方法 rm -rfのようにディレクトリを再帰的に削除するには、fs.rmのrecursiveオプションとforceオプションを使います。 コールバックAPIを使う場合: const fs = require('fs') const dir = process.argv[2] console.log(`try deleting ${dir} directory`) fs.rm(dir, { recursive: true, force: true }, (e) => { if (e) { console.error(e) } else { console.log(`deleted ${dir} directory`) } }) Promise APIを使う場合: const fs = require('fs').promises const dir = process.argv[2] console.log(`try deleting ${dir} directory`) fs.rm(dir, { recursive: true, force: true }) .then(() => console.log(`deleted ${dir} directory`)) .catch((e) => console.error(e)) なお、fs.rmが追加されたのはv14.14.0です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む