子プロセスの生成・終了を管理するサンプルアプリ
背景
アプリが保持する状態が変化したときに、それを音声でつたえる仕組みが欲しくなった(青色になったら音が鳴る歩行者信号のような機能をイメージしてください)。
本記事では、上記機能を実現したときのメモを記す。
機能と方針
実現したい機能を示す。
- 前もって複数の音声ファイルを用意しておき、状態変化に応じて適切な音声ファイルを再生する
- ある状態Aから別の状態Bに遷移したら「状態Bに遷移しました」と音声で通知する。
- 状態Bに遷移を示す音声再生中(例えば「状態Bに」と発話された直後など)に状態Cへ遷移したら直前の音声ファイル再生を止め、新たな状態遷移を示す音声を再生する
上記実現のために今回選んだ方針を以下に示す。
- 状態遷移時に子プロセスを生成し、音声再生アプリ(例:aplay)を起動する
- ワーカスレッドを立て、上記子プロセスの終了を待ち受ける
- 音声再生中に新たな状態遷移が起きた場合はkillを使い、音声再生中の子プロセスを終了したあと、新しい状態への遷移をしめすための子プロセスを生成する。
ソースコード
以下に今回作成したリポジトリのリンクである。
n-hachi/sound-switcher
ここでは、本記事作成時の最新コミットn-hachi/sound-switcher at 4c2f8275880be9592c58fb074f8d2631c118d9bdを前提に記載する。
今回重要なコードはsrc/lib.cppである。
#include "sound/lib.hpp" #include <fcntl.h> #include <signal.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <iostream> #include <thread> #include <vector> void SoundSwitcher::Stop() { // If pid_ is less equal than 0, there is no child process. if (pid_ <= 0) { return; } // If pid is more than 0, stop child process. kill(pid_, SIGTERM); // If thread is joinable if (is_running_ && th_.joinable()) { th_.join(); } // Set false value to is_running is_running_ = false; } void SoundSwitcher::ThreadFunc() { // Setup flag is_running_ = true; waitpid(pid_, NULL, 0); } void SoundSwitcher::Start(const int num) { // If child process has already executed, stop it at first. Stop(); pid_ = vfork(); if (pid_ == -1) { std::cerr << "Error: vfork" << std::endl; return; } if (pid_ == 0) { if (Size() <= 0) { return; } int fd = open("/dev/null", O_WRONLY | O_CREAT, 0666); dup2(fd, 1); dup2(fd, 2); const char **argv = new const char *[3]; argv[0] = "/usr/bin/aplay"; argv[1] = map_.at(num).c_str(); argv[2] = NULL; const char *cmd = argv[0]; execvp(cmd, (char **)argv); } if (pid_ > 0) { // Wait for child process exit. std::thread th(&SoundSwitcher::ThreadFunc, this); th_ = std::move(th); } } void SoundSwitcher::Insert(const std::string &path) { int size = (int)map_.size(); map_.insert(std::pair<int, std::string>(size, path)); } size_t SoundSwitcher::Size() const { return map_.size(); } std::map<int, std::string> SoundSwitcher::map() { return map_; }
ここから各種メソッドを説明する
Insertメソッド
ファイル(この例では音声ファイル)のパスを引数に取りマップに格納する。
マップには、現状のマップのサイズをkey、ファイルパスをvalueとして値を格納する。
key値は後述するstartメソッドで音声ファイルを指定するために使う。
Stopメソッド
子プロセスのPIDが有効な値の場合=すでに子プロセスを生成している場合、子プロセスに対してシグナルを発行し子プロセスを停止する。
子プロセスの終了がきっかけでワーカスレッドが終了する(ワーカスレッド内で実行したwaitpidによる停止が解除される)ためthread::joinでスレッド完了を待つ。
Startメソッド
はじめにStopメソッドを使い、管理中の子プロセスが存在するなら停止する。
vforkを使い子プロセスを生成する。ここから親プロセスと子プロセスで処理が分かれる。
子プロセスはStartメソッドの引数として与えられた値とmap型の変数から再生するファイルパスを取得し、aplayを実行(exec)する。
親プロセスは子プロセスの終了を検知するためのワーカスレッドを作成する
以上が概要である。
終わりに
多分、好ましくない書き方など多くあると思うのでアドバイスなどあればコメントしていただけると嬉しいです。
express使用時のapp.use(express.static(__dirname + '/public'))の意味
背景
他者がつくったアプリを拝見していたときに app.use(express.static(__dirname + '/public'))
と書かれた箇所があり、この文の意味が分からなかったので調べた。
説明
Express での静的ファイルの提供に説明があった。
イメージ、CSS ファイル、JavaScript ファイルなどの静的ファイルを提供するには、Express に標準実装されている express.static ミドルウェア関数を使用します。
静的アセットファイルを格納しているディレクトリーの名前を express.static ミドルウェア関数に渡して、ファイルの直接提供を開始します。例えば、public というディレクトリー内のイメージ、CSS ファイル、JavaScript ファイルを提供するには、次のコードを使用します。
(中略)
ただし、express.static 関数に指定するパスは、node プロセスを起動するディレクトリーに対して相対的です。別のディレクトリーから Express アプリケーションを実行する場合は、提供するディレクトリーの絶対パスを使用する方が安全です。
試してみる
app.use(express.static('public'))
とapp.se(express.static(__dirname+'/public'))
の違いを確認するリポジトリを作成した。
n-hachi/prac_express_app_use
以下に確認方法を記す
前準備
アプリのインストールおよび起動準備
git clone https://github.com/n-hachi/prac_express_app_use cd prac_express_app_use npm install
case1:リポジトリのトップディレクトリでnodeを実行する
# case1 node index.js
この状態なら http://localhost:8000/path1 と http://localhost:8000/path2 ともにアクセスできる。
case2:リポジトリのトップ以外のディレクトリでnodeを実行する
まずcase1で走らせたnodeプロセスを終了する
mkdir tmp cd tmp node ../index.js
case1とは異なり http://localhost:8000/path1 はアクセスできるが http://localhost:8000/path2 はCannot GET /path2/
と表示される。
これはファイルtmp/path2/index.html
が存在しないために発生する。
まとめ
app.use(express.static(__dirname + '/public'))
の意味を勉強した。
あと__dirname
をつけないときはapp.use(express.static('public'))
のようにpublicの前にスラッシュが不要なのだが、__dirname
を付加するときはpublicの前にスラッシュが必要なことに気づかず、数分なやんでしまった。
もし同じような動きになったときはスラッシュの有無を確認してほしい。
autocmdの設定をvim実行時に削除する方法
背景
自分は.vimrc
に以下一行を追加することでファイル保存時に各行末尾に存在する空白を自動で削除するようにしている。
" Delete tailing blanks. autocmd BufWritePre * :%s/\s\+$//ge
- 参考:よく使うのにすぐ忘れる 行末の空白削除コマンド - Qiitaへのコメント
この方法は他者が作成したコードの末尾に空白が存在する場合、意図していない箇所が書き換わってしまいgit diff
を実行した場合に関係ないところまで表示されてしまい困るという課題がある。
上記理由からautocmdの設定を削除する方法を調べた。
参考箇所
autocmd - Vim日本語ドキュメントの "3. 自動コマンドの除去" に以下のように書かれている
:au[tocmd]! [group] {event} {pat} {event} と {pat} に関連づけられた全ての自動コマンドを 除去する。
解決方法
vim起動時に以下を実行することで自動末尾空白が消されることがなくなった
:autocmd! BufWritePre *
もうちょっと良い方法があるかも?
node_modules内パッケージのエントリーポイント定義方法
背景
最近node.jsを勉強しており、他者が作成したパッケージに含まれるファイルの中でどれがエントリーポイントとなるのかわからなかったので調べた。
パッケージのエントリーポイント
※Modules: Packages | Node.js v16.1.0 Documentationの一部を訳し以下に記す。
※訳に誤りがあれば指摘いただきたい。
パッケージ内のファイルpackage.json
はエントリーポイントを定義する2つのフィールドE、"main"
と"exports"
を定義することができる。
"main"
はどのバージョンにも対応しているがパッケージのメインエントリポイントのみ定義可能な制限を持つ。
"exports"
は"main"
の代替を提供する。 "exports"
はパッケージのメインエントリポイントを定義するのと同時に、パッケージをカプセル化し、"exports "で定義されたもの以外のエントリーポイントを防ぐ。
※この部分は訳した結果、完全には理解できていないです。
まとめるとpackage.json内の"main"もしくは"exports"フィールドで指定するようだ。
具体例
ここで今回の調査のきっかけになったパッケージを見てみる。
grpc-node/packages/grpc-js at master · grpc/grpc-node
このリポジトリはgrpcをjavascriptで使うために必要なパッケージらしい。
ここで var grpc = require('@grpc/grpc-js');
という一文が記載されている。
grpc-jsに含まれるpackage.jsonを見てみる。
ローカルの環境ではnode_modules/@grpc/grpc-js/package.json
に当たる。
エントリーポイントに関連する部分は"main": "build/src/index.js",
である(github上の対応する箇所)。
これによってnode_modules/@grpc/grpc-js/build/src/index.js
がエントリポイントと設定される。
まとめ
package.json
に含められた"main"
と"exports"
フィールドによってエントリポイントは定義される。
"main"
と"exports"
の違いがわかってないので、今後必要になったタイミングで調べていきたい。
create-react-appのメモ
背景
最近 create-react-app を使ったアプリ作成を勉強している。
その過程で、どのファイルが最初に呼ばれるのか(エントリーポイントといえばよいのだろうか?)がわからなくなったので調べてみた。
このメモを作成したときに使ったnpxのバージョンは以下の通り。
$ npx -v 6.12.0
前準備
環境を構築する
$ npx create-react-app myapp
$ cd myapp
上記コマンドにより下記構成が作成される。(※内容が多すぎるためnode_modules
は表示していない。)
$ tree -I node_modules . ├── package.json ├── package-lock.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── README.md └── src ├── App.css ├── App.js ├── App.test.js ├── index.css ├── index.js ├── logo.svg ├── reportWebVitals.js └── setupTests.js 2 directories, 17 files
この状態で npm start
を実行するとブラウザが立ち上がりlocalhost上で動作するページが起動する。
npm startの概要
npm start
に関連する内容は package.json
に記載されている。
ここでは関連する部分のみ抜粋する。
{ "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" } }
※ここからは予想を含む。
上記"scripts"
要素内の記載からキー:"start"に対応する値:react-scripts start
が実行される。
react-scripts
は./node_modules/.bin/react-scripts
に配置された実行ファイルが使われる。
Folder Structure | Create React App に以下記述を見つけた。
For the project to build, these files must exist with exact filenames:
・public/index.html is the page template;
・src/index.js is the JavaScript entry point.
この内容から、public/index.html
とsrc/index.js
が必須ファイルであると予想がたつ。
またreact-scripts
はデフォルトのエントリポイントとしてpublic/index.html
を扱っているのだろうと推測できる。
stackoverflowの記事
上記推測の裏付けを取るため調べたら関連しそうな記事を見つけた
以下に一番評価された回答の概要を示す(訳はかなり雑です、すいません)。
1. package.json内、start要素
package.json
内のstart
要素から探索を始めた。
"start": "react-script start"
2. react-scripts
上記内容からnode_modules/.bin
以下に存在するreact-scripts
に到達した。
以下に関連する箇所を記載する。
switch (script) { case 'build': case 'eject': case 'start': case 'test': { const result = spawn.sync( 'node', [require.resolve('../scripts/' + script)].concat(args), { stdio: 'inherit' } );
上記内容から../scripts/
ディレクトリ以下のスクリプトを探した。
3. start.js
続いてnpm start
に関連すると予想されるファイル、node_modules/react-scripts/scripts/start.js
を開いた。
このファイル内でwebpackの設定ファイルを見つけた。
これらはnode_modules/react-scripts/config/webpack.config.dev.js
に記載されていた。
以下に関連した箇所を抜粋する。
entry: [ // Finally, this is your app's code: paths.appIndexJs, ], plugins: [ // Generates an `index.html` file with the <script> injected. new HtmlWebpackPlugin({ inject: true, template: paths.appHtml, }),
よってwebpack configに含まれているpaths.appIndexJs
で参照されるファイルがエントリファイル(エントリポイント?)
である。
4. paths.js
関連する最後のファイルはpaths.js(おそらくnode_modules/react-scripts/config/paths.js)
である。
const appDirectory = fs.realpathSync(process.cwd()); const resolveApp = relativePath => path.resolve(appDirectory, relativePath); module.exports = { ... appHtml: resolveApp('public/index.html'), appIndexJs: resolveApp('src/index.js'), ... }
5. appHtmlおよびappIndexJs
以上からアプリケーションディレクトリ内のappHtmlはファイルpublic/index.html
であり、appIndexJsはファイルsrc/index.js
である。
まとめ
※公式ページの記載を見つけられなかったので、以下内容は調べた結果からの予想です。
npx create-react-app
を使いアプリをつくる場合、public/index.html
とsrc/index.js
は自動的に読み込まれると予想する。
最後に誤りなどあれば指摘ください。
Express web framework (Node.js/JavaScript)の勉強 part4、 directory-structure
The generated projectを読み進める。
日本語版の資料をかいつまんだような内容なので、詳細を知りたい人はこっちを見ることを勧める。
ディレクトリ構造
express
および関連するコマンドを実行することで以下のようなディレクトリ構造になる。
注意:一部コマンドの出力結果は省略している。
$ express express-locallibrary-tutorial --view=pug --git create : express-locallibrary-tutorial/ create : express-locallibrary-tutorial/public/ create : express-locallibrary-tutorial/public/javascripts/ create : express-locallibrary-tutorial/public/images/ create : express-locallibrary-tutorial/public/stylesheets/ create : express-locallibrary-tutorial/public/stylesheets/style.css create : express-locallibrary-tutorial/routes/ create : express-locallibrary-tutorial/routes/index.js create : express-locallibrary-tutorial/routes/users.js create : express-locallibrary-tutorial/views/ create : express-locallibrary-tutorial/views/error.pug create : express-locallibrary-tutorial/views/index.pug create : express-locallibrary-tutorial/views/layout.pug create : express-locallibrary-tutorial/.gitignore create : express-locallibrary-tutorial/app.js create : express-locallibrary-tutorial/package.json create : express-locallibrary-tutorial/bin/ create : express-locallibrary-tutorial/bin/www change directory: $ cd express-locallibrary-tutorial install dependencies: $ npm install run the app: $ DEBUG=express-locallibrary-tutorial:* npm start $ cd express-locallibrary-tutorial $ npm install up to date, audited 123 packages in 2s 6 packages are looking for funding run `npm fund` for details 3 low severity vulnerabilities To address all issues, run: npm audit fix --force Run `npm audit` for details. $ tree -F . ├── app.js ├── bin/ │ └── www* ├── node_modules/ │ ├── たくさんのサブディレクトリおよびファイル(表示は省略) │ ︙ │ ├── package.json ├── package-lock.json ├── public/ │ ├── images/ │ ├── javascripts/ │ └── stylesheets/ │ └── style.css ├── routes/ │ ├── index.js │ └── users.js └── views/ ├── error.pug ├── index.pug └── layout.pug 405 directories, 4784 files
nodemon
今後express-locallibrary-tutorial
以下を編集していくのだが、編集するたびアプリを起動し直すのは面倒である。
この煩わしさを解消するnodemon
というツールがある
下記コマンドを実行し、nodemon
をインストールする。
npm install -g nodemon
もし開発環境以下(?)にインストールしたい場合は-g
の代わりに--save-dev
を使う。
nodemon
を使ってアプリを起動すると、ファイル編集時に自動で反映してくれるためアプリの再起動の手間が省ける。
nodemon ./bin/www
package.json
package.json
はアプリの依存情報を保持する
nodemon
をインストールした直後のpackage.json
の内容を以下に示す。
タイミングによってバージョン番号は変化するので、次同じコマンドを実行しても下記と同じ結果になるとは限らない(と思う)。
{ "name": "express-locallibrary-tutorial", "version": "0.0.0", "private": true, "scripts": { "start": "node ./bin/www", }, "dependencies": { "cookie-parser": "~1.4.4", "debug": "~2.6.9", "express": "~4.16.1", "http-errors": "~1.6.3", "morgan": "~1.9.1", "nodemon": "^2.0.7", "pug": "2.0.0-beta11" } }
npm run-script
参考:npm-run-script | npm Docs
npm run-script
コマンドによってpackage.json
の"scripts"
オブジェクトに記載されたコマンドを実行できる。
上記の場合、"scripts"
というオブジェクトの中にキー"start"
、バリュー"node ./bin/www"
が存在しているため、npm run-script start
と入力するとnode ./bin/www
が実行される。
引数なしの場合は、以下のように利用可能なコマンドが表示される。
$ npm run-script Lifecycle scripts included in express-locallibrary-tutorial: start node ./bin/www
以下npm run-script -h
の実行結果からわかるようにrun-script
はrun
というエイリアスを持っている。
入力文字の短さからnpm run
を使ったほうが良いだろう(npm run-script
のほうがnpm run
より良いケースってあるのだろうか?)。
$ npm run-script -h npm run-script <command> [-- <args>] aliases: run, rum, urn
scripts
package.json
内のscripts
を以下のように編集する
"scripts": { "start": "node ./bin/www", "devstart": "nodemon ./bin/www", "serverstart": "DEBUG-express-lcallibrary-tutorial:* npm run devstart" }
"start"
で始まる行の末尾にカンマ(,
)が追記されていることに注意する。
以降はnpm run serverstart
と実行することでnodemon
でアプリが実行される
/bin/www
ファイル/bin/www
はアプリケーションのエントリポイントである。
下記コードによって、後述するapp.js
を呼び出す。
#!/usr/bin/env node /** * Module dependencies. */ var app = require('../app');
残りのコードでapp.js
を使用するHTTPサーバの設定、ポートの設定、リスニングやサーバエラーのレポートを開始するらしい。
/app.js
express
アプリケーションオブジェクト(app
という名前が慣習である)を生成、アプリケーションおよびミドルウェアの設定、app
をエクスポートする。
上記した/bin/www
はエクスポートされたapp
を使用する。
var express = require('express'); ... var app = express(); ... module.exports = app;
app.js
の詳細を見ていく。
最初にいくつかのnodeライブラリを取り込む。
var createError = require('http-errors'); var express = require('express'); var path = require('path'); var cookieParser = require('cookie-parser'); var logger = require('morgan');
その後require()
を使い、routes
ディレクトリからモジュールを取り込む。
これらファイルには、特定のURLへのリクエストを受け取った場合の処理が書かれている。
var indexRouter = require('./routes/index'); var usersRouter = require('./routes/users');
次にappオブジェクトをexpress
モジュールを使い作成し、view(template)エンジンを設定する。
エンジンの設定は2段階に分かれる。
最初に値'views'
を使ってテンプレートが保存されているフォルダを指定する。
その後、値'view engine'
を使いテンプレートライブラリを指定する。
参考:Using template engines with Express
var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug');
続いてapp.use()
を使いミドルウェアライブラリをリクエストハンドリングの連鎖に加える。
app.use(logger('dev')); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public')));
更に特定のパスへの要求を別のルータへ対応付ける。
app.use('/', indexRouter); app.use('/users', usersRouter);
最後はエラーとHTTP404レスポンスを返却するためのミドルウェアを追加する。
// catch 404 and forward to error handler app.use(function(req, res, next) { next(createError(404)); }); // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page res.status(err.status || 500); res.render('error'); });
以上でexpressアプリケーションオブジェクト(app)の設定は完了する。
最後にmodule.exports
にapp
を追加することで、/bin/www
からアクセスできるようにする。
module.exports = app;
Router
/routes
以下にはusers.js
とindex.js
があるが基本的に処理が同じなので、ここではindex.js
のみを見ていく。
最初にexpress
モジュールをロードしexpress.routerオブジェクトを取得する。
var express = require('express'); var router = express.Router(); /* GET users listing. */ router.get('/', function(req, res, next) { res.send('respond with a resource!!'); }); module.exports = router;
Views(templates)
views(template)は/views
ディレクトリに格納され、拡張子.pug
を持つ。
Response.render()メソッドは特定のテンプレートを描画するために使われ、レスポンスとして結果を送信する。
以下/routes/index.js
の例ではルートレンダーはテンプレートindex(index.pug)
を使い、テンプレート変数title
を渡している。
/* GET home page. */ router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); });
上記コードに対応するテンプレート/views/index.pug
を以下に示す。
ここでは数変title
の箇所に値Express
が挿入される。
extends layout block content h1= title p Welcome to #{title}
まとめ
個人的にこの章は今までメインでやってきたこと(組み込み寄り)と比べて多くの差異を感じた。
特に重要に違いを感じた点を以下にまとめる。
npm express
でアプリケーションの雛形が作成されること。app.js
ではルーターやビューの設定、その他ライブラリのインポートなどを行うこと。routes
ディレクトリ以下にはルーター(router)が配置され、ルーターは特定のパスへの要求を受理したときに対応する処理へのルーティングを担当すること。- 変数
res
はrender
メソッドを使うとテンプレートを使って描画する。 views
ディレクトリにはビュー(view)のテンプレートが配置され、これらは描画の際に使われること。
これらは繰り返し実装しないと身につかなさそうだ。
Express web framework (Node.js/JavaScript)の勉強 part3、 express-generator
Express Tutorial Part 2: Creating a skeleton website を読み進める
ジェネレータのインストール
はじめに下記コマンドを実行しジェネレータをインストールする。
npm install express-generator -g
ジェネレータのオプション
ジェネレータは下記オプションを持つ
$ express -h Usage: express [options] [dir] Options: --version output the version number -e, --ejs add ejs engine support --pug add pug engine support --hbs add handlebars engine support -H, --hogan add hogan.js engine support -v, --view <engine> add view <engine> support (dust|ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade) --no-view use static html instead of view engine -c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css) --git add .gitignore -f, --force force on non-empty directory -h, --help output usage information
プロジェクトの生成
ジェネレータを使いプロジェクトの雛形をつくる。
参考元 の例では express-locallibrary-tutorial
をプロジェクト名としているので、それに倣う。
$ express express-locallibrary-tutorial --view=pug --git create : express-locallibrary-tutorial/ create : express-locallibrary-tutorial/public/ create : express-locallibrary-tutorial/public/javascripts/ create : express-locallibrary-tutorial/public/images/ create : express-locallibrary-tutorial/public/stylesheets/ create : express-locallibrary-tutorial/public/stylesheets/style.css create : express-locallibrary-tutorial/routes/ create : express-locallibrary-tutorial/routes/index.js create : express-locallibrary-tutorial/routes/users.js create : express-locallibrary-tutorial/views/ create : express-locallibrary-tutorial/views/error.pug create : express-locallibrary-tutorial/views/index.pug create : express-locallibrary-tutorial/views/layout.pug create : express-locallibrary-tutorial/.gitignore create : express-locallibrary-tutorial/app.js create : express-locallibrary-tutorial/package.json create : express-locallibrary-tutorial/bin/ create : express-locallibrary-tutorial/bin/www change directory: $ cd express-locallibrary-tutorial install dependencies: $ npm install run the app: $ DEBUG=express-locallibrary-tutorial:* npm start
第1引数で指定した名前のディレクトリがカレントディレクトリ以下に作成される。
--git
オプションで.gitignore
も同時に作られる。
この.gitignore
は中身が充実しており、これを使うのが好ましいと判断したため--git
オプションを付加して実行した。
以下に express
が作る.gitignore
を残す。
expressが作成する.gitignore
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# next.js build output
.next
まとめ
express
を使うことでアプリケーションの雛形を作成できる
引数によってビューアなどを切り替えることが可能
--git
オプションによって.gitignore
も同時に作られる