20200522のNode.jsに関する記事は6件です。

あなたのnpmパッケージ、脆弱性の塊説。急いで最新にするよ!

npm便利ですよね。

昨今フロントweb開発でNode.jsが登場しないことはないので、みなさんお使いかと思いますが、ちゃんとバージョン管理していますか?

私はしがないweb制作者ですが、npmパッケージなしでの開発はありえないです。

ただそういえばバージョン管理をしていないなと思い、現在バージョンと最新バージョンを比べてみることに。そしたら...

$ npm outdated

スクリーンショット 2020-05-22 20.25.53.png

微妙にパッケージが古くなってた...

npm-check-updatesをインストール

まずはpackage.jsonを最新バージョンにアップグレードしてくれるnpm-check-updatesをインストールします。

npm i npm-check-updates

そしたら、

ncu -u

すると、
スクリーンショット 2020-05-22 20.52.38.png

Run npm install to install new versions.

というメッセージが出たらOK、最後にパッケージをインストールします。

npm i

すると...

スクリーンショット 2020-05-22 20.54.41.png
何やら不穏なメッセージ。

660の脆弱性があるから直すためにnpm audit fixしろよな!

ということらしいです?

ヒェ...
(npmの更新サボってた人はみんな数百レベルであると思われます)

とりあえずコマンドを実行します。脆弱性のある箇所を自動修正してくれるコマンドです。

npm audit fix

すると

スクリーンショット 2020-05-22 21.00.49.png

残り12個の脆弱性は手作業でオナシャス!!

ということらしい。

マジかい。

npm audit

で脆弱性一覧を出してみる。

スクリーンショット 2020-05-22 21.05.31.png

15個の脆弱性のうち、一個の危険性がhighになっていました(脆弱性から正規表現を使ったDoS攻撃を受ける可能性があるそうです

highのものを詳しくみてみます。

───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ Denial of Service                                            │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ http-proxy                                                   │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=1.18.1                                                     │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ browser-sync [dev]                                           │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ browser-sync > http-proxy                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://npmjs.com/advisories/1486                            │
└───────────────┴──────────────────────────────────────────────────────────────┘

browser-syncが依存している、http-proxyに問題があるそう。なんぞこれ...?

調べてみると、執筆時点5日前にアップデートが出ており、最新版にする必要がありそうです。

https://www.npmjs.com/advisories/1486

とりあえず

$ npm install http-proxy

で最新版をダウンロードし、再度脆弱性のある箇所を自動修正してくれるコマンド↓

npm audit fix

すると...

スクリーンショット 2020-05-22 21.37.11.png

fixed 9 of 13 vulnerabilities in 1275 scanned packages
  4 vulnerabilities required manual review and could not be updated

high消えたし、4つまで減らせたよかった!!

ぬわ〜ん疲れたも〜ん!!

結論 npmは定期的にお手入れせよ

バージョンは古くなってるし、脆弱性はあるし、多分自動化できるんだろうけど弱弱エンジニアなので、これから調べてみます。

みんなもnpmパッケージのバージョン管理、やろう!!

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

HTMLから画像を生成するシンプルな方法(Node.js)

どうもこんにちは、@y_temp4です。

最近、趣味で個人開発している Web サービスの AnyMake にて、画像を動的に生成するプログラムを書く機会があったのでその方法についてまとめてみます。

関連記事:埋め込みコンテンツを追加しました!| AnyMake | note

node-html-to-image を使う

自分は画像生成周りは全然詳しくないのですが、普段フロントエンドのコードを書くことが多いので

HTML から画像生成できたら便利だな〜

と思いました。

そこで少し調べると、node-html-to-imageというライブラリが見つかり、これを使うと割と簡単にやりたいことが実現できそうでした。

使い方

以下のコードは README からの引用ですが、このように HTML を引数として渡してやると、その HTML の表示結果が画像として出力されます。

const nodeHtmlToImage = require("node-html-to-image");

nodeHtmlToImage({
  output: "./image.png",
  html: "<html><body>Hello world!</body></html>"
}).then(() => console.log("The image was created successfully!"));

上記の例だと、「Hello World!」と書かれたシンプルな画像ファイルが生成されます。

今回自分は画像を返す API を作りたかったので、README にある以下のコードを参考に作成しました。

const express = require("express");
const router = express.Router();
const nodeHtmlToImage = require("node-html-to-image");

router.get(`/api/tweet/render`, async function(req, res) {
  const image = await nodeHtmlToImage({
    html:
      "<html><body><div>Check out what I just did! #cool</div></body></html>"
  });
  res.writeHead(200, { "Content-Type": "image/png" });
  res.end(image, "binary");
});

非常にシンプルですがこれで最低限やりたいことは実現できたので、お手軽に画像生成したい場合はこれが良さそうです。


ちなみにですが、このライブラリの内部処理としては Puppeteer で HTML を描画してスクリーンショットを撮っているだけです。

言われてみれば確かにこれでいけるな...と README や内部の処理を読んでいて思いましたが、やっている事的にあんまり軽くはなさそうなので、もしこれより良さそうな方法で簡単に HTML から画像を生成する方法をご存知の方がいらっしゃればぜひコメント欄にて教えていただけますと嬉しいです ?

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

【超初級】Node.jsの始め方 〜 2020.05.22ver〜

? Node.jsをインストールしてみよう♪

https://nodejs.org/ja/
こちらをクリックするとHPに行くと以下のような画面が出てくると思います。
スクリーンショット 2020-05-22 16.40.36.png

どっちでも良いですが、推奨版をインストールするほうが安定的かもしれません。
流石に、インストールの方法は皆さんご存知かと思うので割愛します。

? nodeがインストールできたか確認してみよう

実際にnodeが入っているかを確認しましょう!

ターミナル
node -v

ターミナルを開き上記のように入力してみてください。
v12.16.3などと出てきたらOKです!

? npmについて

nodeで開発を行っていく上で、必須となってくるのがnpmと呼ばれるもので
ノード関連のパッケージマネージャーです。
Node Package Maneger の略です。

Ruby on Railsでいうgemみたいな感じです。
多様なライブラリを後から追加で使うことができます。
expressなどが有名です。

これは、nodeをインストールすると同時にnpmもインストールされます。
確認してみましょう

ターミナル
% npm

スクリーンショット 2020-05-22 16.54.08.png
このような画面が出ていればnpmもインストールされています。

? ファイルを立ち上げてみよう!

今回はVSCodeを使っていきます。
それに類するものであればなんでもいいです。
早速、どこでも良いので適当なフォルダを作ります。
スクリーンショット 2020-05-22 17.04.30.png

先程作ったフォルダの中に、ファイルを作成します。
nodeはJavaScriptなので.jsファイルを作成します。
適当にコードも書いてみましょう。

では、nodeで実際にファイルを立ち上げてみましょう。
ターミナルから自身が作ったディレクトリまで行きます。
スクリーンショット 2020-05-22 17.11.53.png

すると、先程作成した、hello.jsが存在していると思います。

ターミナル
% node hello.js

このように記入してみてください。
すると、hello.jsに書いたコードが実際にターミナルに反映されています。
書いていて気づきましたが、helloを誤字ってるのは気にしないでください(恥)

このように、nodeでファイルを立ち上げるときは、 node ファイル名 という形でターミナルに記載すればOKです。
ちなみに、ターミナルに入力するときは、.jsといった拡張子は実は書く必要がないので、次回から省いていきましょう!

超基礎的で退屈だったかもしれませんが、今回は以上です!

? 次回予告

今後の方針として、expressを使わずに、簡単なメモツールを作成していこうかと思います。
nodeの基本をさっくりと沿っていくような形になります。
興味のある方は是非、見ていってください!

記事を見てくださりありがとうございます。
5分で理解できるを記事を目標に執筆しております!
自身も学びの途中ですので、間違い等ありましたら、ドシドシ編集リクエストまでお願いします!

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

ShopifyアプリをTypescriptで開発する方法

はじめに

Shopifyアプリとは、Shopifyストアに機能を追加するWebアプリケーションです。
下記URLのチュートリアルでは、Node.js、React、GraphQLを使用して埋め込みShopifyアプリを構築するプロセスについて説明されておりますが、Typescriptで開発したいと思い、実装する方法を調べて実現できたのでご紹介したいと思います。

https://shopify.dev/tutorials/build-a-shopify-app-with-node-and-react

開発環境

下記環境で確認しています。

  • Mac
  • VSCode
  • node.js
  • Shopify App CLI

プロジェクト作成

Shopify App CLIでベースのnodeのプロジェクトを作成します。

  • PublicかCustomを選択します。
% shopify create node --name=starter-embedded-app
? What type of app are you building? (Choose with ↑ ↓ ⏎, filter with 'f')
> 1. Public: An app built for a wide merchant audience.
  2. Custom: An app custom built for a single client.
  • 次にどの開発ストア向けで作成するか選択します。
% shopify create node --name=starter-embedded-app
? What type of app are you building? (You chose: Public: An app built for a wide merchant audience.)
Organization [Shopify Partnerアカウントのビジネス名] 
? Select a Development Store (Choose with ↑ ↓ ⏎, filter with 'f')                                                                                                                                           
  1. xn-xxxxx1.myshopify.com
> 2. xn-xxxxx2.myshopify.com
  • プロジェクトが生成されます。
% shopify create node --name=starter-embedded-app
? What type of app are you building? (You chose: Public: An app built for a wide merchant audience.)
Organization [Shopify Partnerアカウントのビジネス名]                                                                                                                                                                      
? Select a Development Store (You chose: xn-xxxxx2.myshopify.com)
✓ node v14.3.0                                                                                                                                                                                              
✓ npm 6.14.4                                                                                                                                                                                                
┏━━ Cloning into starter-embedded-app... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃ Cloning into 'starter-embedded-app'...
┃ remote: Enumerating objects: 3, done.        
remote: Counting objects: 100% (3/3), done.        
remote: Compressing objects: 100% (3/3), done.        
remote: Total 1071 (delta 0), reused 0 (delta 0), pack-reused 1068        
Receiving objects: 100% (1071/1071), 1.83 MiB | 1.97 MiB/s, done.
Resolving deltas: 100% (720/720), done.
┃                                                                                                                                                                                                       100%
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ (3.11s) ━━
✓ Cloned into starter-embedded-app
┏━━ Installing dependencies with npm... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃ ✓ 37 npm dependencies installed
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ (53.38s) ━━
✓ Dependencies installed
✓ .env saved to project root
✓ starter-embedded-app was created in your Partner Dashboard https://partners.shopify.com/xxxxx/apps/xxxxx
⭑ Run shopify serve to start a local server
⭑ Then, visit https://partners.shopify.com/xxxxx/apps/xxxxx/test to install starter-embedded-app on your Dev Store
  • アプリを起動し、アプリをストアにインストールして動作を確認します。

Typescript開発セットアップ

Typescript開発で必要なパッケージをインストールします。
※ 先にncuで既存パッケージの最新化もします。
※ typescriptに関しては、最新の3.9.3ではエラーがでてたのでバージョンを3.8.3に指定してインストールしています。

% ncu -u
% npm install
% npm install --save-dev typescript@3.8.3 ts-node @types/node @types/react @types/react-dom @types/koa @types/koa-session @types/koa-router @types/js-cookie

tsconfig.json, tsconfig.server.json, next-env.d.ts, nodemon.json ファイルを作成します。

tsconfig.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "jsx": "preserve",
    "lib": ["dom", "es2017"],
    "baseUrl": ".",
    "moduleResolution": "node",
    "strict": true,
    "allowJs": true,
    "noEmit": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "isolatedModules": true,
    "removeComments": false,
    "preserveConstEnums": true,
    "sourceMap": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true
  },
  "exclude": ["dist", ".next", "out", "next.config.js"],
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}
tsconfig.server.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs",
    "outDir": "dist",
    "target": "es2017",
    "isolatedModules": false,
    "noEmit": false
  },
  "include": ["server/**/*.ts"]
}
nodemon.json
{
  "watch": ["server"],
  "exec": "ts-node --project tsconfig.server.json server/server.ts",
  "ext": "js ts"
}
next-env.d.ts
/// <reference types="next" />
/// <reference types="next/types/global" />

package.jsonを下記の通り編集します。

package.json
〜省略〜
  "scripts": {
    "test": "jest",
    "dev": "NODE_ENV=development nodemon",
    "build": "next build && tsc --project tsconfig.server.json && cp server/index.js dist/",
    "start": "NODE_ENV=production node dist/index.js"
  },
〜省略〜

JSファイルをTS/TSXファイルに変更する

JSファイルをTS/TSXファイルに変更して、エラー箇所を修正していきます。

  • pages/index.js は pages/index.tsx にリネームのみ
  • pages/_app.js は pages/_app.tsx にリネームし、下記の通り編集します。
pages/_app.tsx
〜省略〜
import translations from "@shopify/polaris/locales/en.json";

declare var API_KEY: string; // 追加

const client = new ApolloClient({
〜省略〜
    const { Component, pageProps } = this.props;
    const shopOrigin = Cookies.get("shopOrigin") ?? "error"; // 変更
    return (
〜省略〜
  • server/server.js は server/server.ts にリネームし、下記の通り編集します。
server/server.ts
〜省略〜
import session from "koa-session";
// import * as handlers from "./handlers/index"; コメントアウト
dotenv.config();
const port = parseInt(process.env.PORT || '8081', 10); // 変更
const dev = process.env.NODE_ENV !== "production";
〜省略〜
const handle = app.getRequestHandler();
const SHOPIFY_API_SECRET = process.env.SHOPIFY_API_SECRET ?? "error"; // 変更
const SHOPIFY_API_KEY = process.env.SHOPIFY_API_KEY ?? "error"; // 変更
const SCOPES = process.env.SCOPES ?? "error"; // 変更
app.prepare().then(() => {
〜省略〜
      async afterAuth(ctx) {
        //Auth token and shop available in session
        //Redirect to shop upon auth
        const shop = ctx.session?.shop; // 変更
        ctx.cookies.set("shopOrigin", shop, {
          httpOnly: false,
          secure: true,
          sameSite: "none"
        });
        ctx.redirect("/");
      }
〜省略〜

上記の必要最低限の修正のみで初期プロジェクトは動作するようになると思います。
エラーを回避する修正しかしていないので、適宜修正してください。

まとめ

ここまで変更を加えたときのフォルダ構成は下記の通りになります。

starter-embedded-app
├── .dependabot
│   └── config.yml
├── .editorconfig
├── .env
├── .env.example
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .npmrc
├── .prettierignore
├── .shopify-cli.yml
├── .stylelintignore
├── .stylelintrc.js
├── .travis.yml
├── LICENSE.md
├── README.md
├── next-env.d.ts
├── next.config.js
├── nodemon.json
├── package-lock.json
├── package.json
├── pages
│   ├── _app.tsx
│   └── index.tsx
├── server
│   ├── handlers
│   │   ├── client.js
│   │   ├── index.js
│   │   ├── mutations
│   │   │   ├── get-one-time-url.js
│   │   │   └── get-subscription-url.js
│   │   └── register-webhooks.js
│   ├── index.js
│   └── server.ts
├── tsconfig.json
└── tsconfig.server.json

あとは、チュートリアルに沿って機能を追加していけば、Typescriptでも開発できることが確認できると思います。

本記事のリポジトリは下記においてますので何かの参考になれば幸いです。
https://github.com/winuim/starter-embedded-app

参考サイト

Shopify App CLI でアプリを開発する
TypeScript Next.js example
Custom server with TypeScript + Nodemon example

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

VercelでLINE BOTを動かす 2020年5月版

よく使う記事(↓)のソースコードを元にVercel(旧: now.sh)にLINE BOTをデプロイします。

https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d

ちなみに、Vercelはnow時代から仕様がちょくちょく変わる印象があるのであくまでも現時点版だと思った方が良さそうです。

事前準備: LINE BOTを作成し、ngrokで動作確認

参考記事のSTEP3のngrokでトンネリングさせるところまで進めます。

参考: 1時間でLINE BOTを作るハンズオン (資料+レポート)

1. Vercelコマンドのインストール

$ npm i -g vercel

既にインストールしている人はこの手順はスキップしましょう。

参考: 爆速!Vercelとfreenomで独自ドメインのサイトを無料で作成する

2. プロジェクトのファイル微修正

Vercelにデプロイするにあたりちょっとした修正を3箇所行います

2-1. server.jsをapiフォルダへ

プロジェクトのルート(package.jsonがある階層)にapiという名前でフォルダを作成します。

apiフォルダ内に、もともLINE BOTで作成したserver.jsを移動させます。

Vercel上ではapiフォルダ内に置いたプログラム(.js or .ts)をNode.jsで実行する模様です。

2-2. vercel.jsonを作成

プロジェクトのルート(package.jsonがある階層)にvercel.jsonという名前でファイルを作成します。

vercel.json
{
    "version": 2,
    "routes": [
        { "src": "/", "dest": "api/server.js" },
        { "src": "/webhook", "dest": "api/server.js" }
    ]
}

2-3. server.jsを更新

server.jsの末尾を以下に変更します。

server.js


(省略)



// app.listen(PORT);
// console.log(`Server running at ${PORT}`);
(process.env.NOW_REGION) ? module.exports = app : app.listen(PORT);
console.log(`Server running at ${PORT}`);

3. デプロイ

あとはプロジェクトのルートでvercelコマンドを実行するだけです。デプロイ時に対話式に質問が来ますが全てエンターで進めます。

Vercelの利用が初めての場合のみログイン認証があります。

$ vercel

デプロイが成功するとhttps://<アプリ名>.now.shというURLが発行されます。

この時点で、このURLにブラウザでアクセスし、Hello LINE BOT!(GET)の文字が表示されれば問題なくデプロイできています。

4. LINE Developersの管理画面でWebhook URLを更新

LINE DevelopersのWebhook設定の管理画面からhttps://<アプリ名>.now.sh/webhookというURLを設定します。

これで完成となります。

更新する際

デプロイし直す場合はvercelコマンドだけでデプロイ可能です。

$ vercel

ローカルでngrokで試す際はapiフォルダにserver.jsを移動させてあるので

$ node api/server.js

という実行の仕方に変えましょう。

所感 now時代と違うところなど

割と軽微な変更でデプロイできました。一回感覚を掴むと問題ないですが、初見だとちょっと戸惑う人いるかもなぁという印象です。

vercel.jsonは基本的にはnow.jsonと同じような書き方でしたが、buldsが非推奨っぽくなってたり、apiフォルダに入れると認識されるなど微妙に変わってるところがありうまく行くまでなんどかやり直しが発生しました。

今回はもともとローカル起動させるnode.jsプログラムの記述をあまり変えずにVercelにデプロイするやり方ですが、Vercelのドキュメント的にはapiフォルダにhoge.jsを設置すると /api/hogeという形でアクセスできるようになるみたいですね。

詳細はこの辺を見ると良さそうです。

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

systemctlってめちゃくちゃ便利なんだな...

nodeのアプリをforeverでデーモン化しようと思っていたところ、そもそもsystemctl使えば必要なかったという話です。

前提

  • ts-nodeのexpressアプリをデーモン化したい
  • サーバー起動時にも起動したい
  • AWSのEC2

systemctlの設定を書く

systemctlは昔のserviceコマンドに替わるものですがだいぶ便利になっています。

昔はinit.dにややこしい起動スクリプトを書く必要がありましたが今では、

/usr/lib/systemd/system/foo.service
[Unit]
Description=foo

[Service]
Type=simple
ExecStart="/home/ec2-user/repo/script/start.sh"

[Install]
WantedBy=multi-user.target

これだけで

$ sudo systemctl enable foo
$ sudo systemctl start foo
$ sudo systemctl stop foo

できます。

start.shには、普通にyarn startが書かれています。
もちろんパスを通したりする必要はありますが。
こんな感じで書いてます。

start.sh
#!/bin/bash

set -e

cd /home/ec2-user/repo

export PATH=/home/ec2-user/.nvm/versions/node/v14.3.0/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/ec2-user/.local/bin:/home/ec2-user/bin:$PATH

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

/home/ec2-user/.nvm/versions/node/v14.3.0/bin/yarn start

便利な世の中になりましたね。

どうでもいいけどserviceコマンドと違って

$ service foo start
$ systemctl start foo

逆なのがなかなか慣れない...

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