1. NPMスクリプトとは
NPMスクリプトは、Node.jsのパッケージマネージャであるnpmで提供される機能の1つです。NPMスクリプトを使用すると、JavaScriptアプリケーションの開発、テスト、ビルド、デプロイなどのタスクを自動化できます。NPMスクリプトは、package.jsonファイルに定義され、npm runコマンドを使用して実行できます。
開発中のWebアプリケーションを運用するために使用するモジュール群です。以下でそれぞれの役割を説明します。
-
npm-run-all: 複数のnpm scriptコマンドを同時に実行したり、シーケンシャルに実行したりすることができるパッケージです。
-
cpx: ファイルのコピーを簡単に実行することができるツールです。
-
rimraf: ファイルやディレクトリを削除するためのパッケージです。通常、rm -rfの代替手段として使用されます。
これらのツールを使用することで、エラーハンドリングやファイル操作などを簡単に処理することができます。特に、npm run scriptにおいて便利な機能を提供します。
npm install --save-dev npm-run-all cpx rimraf
2. Gulpとは
Gulpは、JavaScriptアプリケーションの開発、テスト、ビルド、デプロイなどのタスクを自動化するためのJavaScriptタスクランナーです。Gulpは、プラグインを使用して、JavaScript、CSS、画像などのファイルを処理できます。Gulpは、gulpfile.jsファイルに定義されたタスクを実行することができます。
Gulpは、JavaScriptアプリケーションの開発、テスト、ビルド、デプロイなどのタスクを自動化するためのJavaScriptタスクランナーです。Gulpは、プラグインを使用して、JavaScript、CSS、画像などのファイルを処理できます。Gulpは、gulpfile.jsファイルに定義されたタスクを実行することができます。
-
Gulpをインストールします
npm install --save-dev gulp
-
Gulpタスクを作成します
function defaultTask(cb) {
// place code for your default task here
cb();
}
exports.default = defaultTask
-
Gulpタスクを実行します
npx gulp --tasks
npx gulp
3. Asciidocとは
Asciidocは、テキストベースのドキュメントフォーマットであり、HTML、PDF、EPUBなどのフォーマットに変換できます。Asciidocは、ドキュメントの構造を定義するためのマークアップ言語であり、テキストエディタで編集できます。Asciidocは、Node.jsのパッケージマネージャであるnpmで提供されています。
-
Asciidocをインストールします
npm install --save-dev asciidoctor asciidoctor-kroki
-
Asciidocファイルを作成します
docs
ディレクトリに index.adoc
と sample.adoc
ファイルを作成し、以下の内容を記述します。
:toc: left
:toclevels: 5
:sectnums:
= Asciidoc
== 目的
== 前提
== 構成
=== link:./sample.html[サンプル^][[anchor-1]]
== 参照
* link:/docs/sample.html[サンプル^]
:toc: left
:toclevels: 5
:sectnums:
:stem:
:source-highlighter: coderay
= AppTemplate
== 仕様
== 設計
=== TODOリスト
* [ ] TODO
* [x] [line-through]#TODO DONE#
=== ユースケース図
[plantuml]
----
left to right direction
skinparam packageStyle rectangle
actor customer
actor clerk
rectangle checkout {
customer -- (checkout)
(checkout) .> (payment) : include
(help) .> (checkout) : extends
(checkout) -- clerk
}
----
=== クラス図
[plantuml]
----
class Car
Driver - Car : drives >
Car *- Wheel : have 4 >
Car -- Person : < owns
----
=== シーケンス図
[plantuml]
----
participant User
User -> A: DoWork
activate A
A -> B: << createRequest >>
activate B
B -> C: DoWork
activate C
C --> B: WorkDone
destroy C
B --> A: RequestCreated
deactivate B
A -> User: Done
deactivate A
----
=== 数式
https://asciidoctor.org/docs/user-manual/#activating-stem-support[Using Multiple Stem Interpreters^]
stem:[sqrt(4) = 2]
Water (stem:[H_2O]) is a critical component.
[stem]
++++
sqrt(4) = 2
++++
latexmath:[C = \alpha + \beta Y^{\gamma} + \epsilon]
== 開発
== 参照
-
Gulpタスクを作成します
const { series } = require("gulp");
const { default: rimraf } = require("rimraf");
const asciidoctor = {
clean: async (cb) => {
await rimraf("./public/docs");
cb();
},
build: (cb) => {
const fs = require("fs");
const asciidoctor = require("@asciidoctor/core")();
const kroki = require("asciidoctor-kroki");
const krokiRegister = () => {
const registry = asciidoctor.Extensions.create();
kroki.register(registry);
return registry;
};
const inputRootDir = "./docs";
const outputRootDir = "./public/docs";
const fileNameList = fs.readdirSync(inputRootDir);
const docs = fileNameList.filter(RegExp.prototype.test, /.*\.adoc$/);
docs.map((input) => {
const file = `${inputRootDir}/${input}`;
asciidoctor.convertFile(file, {
safe: "safe",
extension_registry: krokiRegister(),
to_dir: outputRootDir,
mkdirs: true,
});
});
cb();
},
watch: (cb) => {
watch("./docs/**/*.adoc", asciidoctor.build);
cb();
},
}
exports.docs = series(asciidoctor.clean, asciidoctor.build);
-
Gulpタスクを実行します
npx gulp docs
public
ディレクトリはgit管理対象外にするため.gitignoreに以下を追加します。
/public
4. BrowserSyncとは
BrowserSyncは、ブラウザーの自動リロード、CSSのインジェクション、デバイス同期などの機能を提供するJavaScriptライブラリです。BrowserSyncは、gulpfile.jsファイルに定義されたタスクを実行することができます。
-
BrowserSyncをインストールします
npm install --save-dev browser-sync
-
Gulpタスクを変更します
function defaultTask(cb) {
// place code for your default task here
cb();
}
exports.default = defaultTask
const { series, watch } = require("gulp");
const { default: rimraf } = require("rimraf");
const browserSync = require('browser-sync').create();
const asciidoctor = {
clean: async (cb) => {
await rimraf("./public/docs");
cb();
},
build: (cb) => {
const fs = require("fs");
const asciidoctor = require("@asciidoctor/core")();
const kroki = require("asciidoctor-kroki");
const krokiRegister = () => {
const registry = asciidoctor.Extensions.create();
kroki.register(registry);
return registry;
};
const inputRootDir = "./docs";
const outputRootDir = "./public/docs";
const fileNameList = fs.readdirSync(inputRootDir);
const docs = fileNameList.filter(RegExp.prototype.test, /.*\.adoc$/);
docs.map((input) => {
const file = `${inputRootDir}/${input}`;
asciidoctor.convertFile(file, {
safe: "safe",
extension_registry: krokiRegister(),
to_dir: outputRootDir,
mkdirs: true,
});
});
cb();
},
watch: (cb) => {
watch("./docs/**/*.adoc", asciidoctor.build);
cb();
},
server: (cb) => {
browserSync.init({
server: {
baseDir: "./public",
},
});
watch("./public/**/*.html").on("change", browserSync.reload);
cb();
},
}
exports.docs = series(asciidoctor.clean, asciidoctor.build, asciidoctor.watch, asciidoctor.server)
-
Gulpタスクを実行します
npx gulp docs
これで、adocファイルを編集するたびにドキュメントがビルドされブラウザが自動でリロードされます。
5. Marpとは
Marpは、Markdownを使用してスライドを作成するためのJavaScriptアプリケーションです。Marpは、スライドのデザインをカスタマイズするためのテーマを提供し、PDF、HTML、PNGなどのフォーマットにエクスポートできます。Marpは、Node.jsのパッケージマネージャであるnpmで提供されています。
-
Marpをインストールします
npm install --save-dev @marp-team/marp-cli
-
スライドを作成します
./docs/slides/PITCHME.md
---
marp: true
---
### タイトル
---
### 構成
- 自己紹介
- トピック 1
- トピック 2
- トピック 3
---
### 自己紹介
---
### トピック 1
---
### トピック 2
---
### トピック 3
---
### おわり
---
### 参照
---
-
スライドをビルドします
npx marp --html --pdf ./docs/slides/PITCHME.md
-
Gulpタスクを追加します
marp = {
build: (cb) => {
const { marpCli } = require('@marp-team/marp-cli')
marpCli(['./docs/slides/PITCHME.md', '--html', '--output', './public/slides/index.html'])
.then((exitStatus) => {
if (exitStatus > 0) {
console.error(`Failure (Exit status: ${exitStatus})`)
} else {
console.log('Success')
}
})
.catch(console.error)
cb();
},
clean: async (cb) => {
await rimraf("./public/slides");
cb();
},
watch: (cb) => {
watch("./docs/slides/**/*.md", marp.build);
cb();
}
}
exports.slides = series(marp.build);
-
Gulpタスクを実行します
npx gulp slides
6. 既存のnpmタスクを統合する
既存のnpmタスクを統合するには、gulpfile.jsファイルにタスクを定義し、npmスクリプトを使用してタスクを実行します。タスクは、JavaScript関数として定義され、gulpプラグインを使用して、JavaScript、CSS、画像などのファイルを処理できます。
-
webpackのタスクを追加します
const webpack = {
clean: async (cb) => {
await rimraf("./public");
cb();
},
build: (cb) => {
const webpack = require("webpack");
const webpackConfig = require("./webpack.config.js");
webpack(webpackConfig, (err, stats) => {
if (err || stats.hasErrors()) {
console.error(err);
}
cb();
});
},
watch: (cb) => {
const webpack = require("webpack");
const webpackConfig = require("./webpack.config.js");
const compiler = webpack(webpackConfig);
compiler.watch({}, (err, stats) => {
if (err || stats.hasErrors()) {
console.error(err);
}
});
cb();
},
server: (cb) => {
const webpack = require("webpack");
const webpackConfig = require("./webpack.config.js");
const compiler = webpack(webpackConfig);
const WebpackDevServer = require("webpack-dev-server");
const devServerOptions = Object.assign({}, webpackConfig.devServer, {
open: false,
});
const server = new WebpackDevServer(compiler, devServerOptions);
server.start(devServerOptions.port, devServerOptions.host, () => {
console.log("Starting server on http://localhost:8080");
});
cb();
},
}
-
jestのタスクを追加します
const jest = {
test: (cb) => {
const jest = require("jest");
jest.run(["--coverage"]);
cb();
},
watch: (cb) => {
const jest = require("jest");
jest.run(["--watch"]);
cb();
},
}
-
prettierのタスクを追加します
npm install gulp-prettier --save-dev
const prettier = {
format: (cb) => {
const prettier = require('gulp-prettier');
return src("./src/**/*.{js,jsx,ts,tsx,json,css,scss,md}")
.pipe(prettier({ singleQuote: true }))
.pipe(dest('src'));
},
watch: (cb) => {
watch("./src/**/*.{js,jsx,ts,tsx,json,css,scss,md}", prettier.format);
cb();
},
};
-
既存のタスクと統合します
const { series, parallel, watch } = require("gulp");
....
const webpackBuildTasks = () => {
return series(webpack.clean, webpack.build);
}
const asciidoctorBuildTasks = () => {
return series(asciidoctor.clean, asciidoctor.build);
}
const marpBuildTasks = () => {
return series(marp.clean, marp.build);
}
exports.default = series(
webpackBuildTasks(),
asciidoctorBuildTasks(),
marpBuildTasks(),
prettier.format,
series(
parallel(webpack.server, asciidoctor.server),
parallel(webpack.watch, asciidoctor.watch, marp.watch),
parallel(jest.watch)
)
);
exports.build = series(
webpackBuildTasks(),
asciidoctorBuildTasks(),
marpBuildTasks(),
prettier.format
);
exports.test = series(jest.test);
exports.format = series(prettier.format);
exports.slides = series(marp.build);
exports.docs = series(
asciidoctorBuildTasks(),
marpBuildTasks(),
parallel(asciidoctor.server, asciidoctor.watch, marp.watch),
);
exports.watch = parallel(webpack.watch, asciidoctor.watch, marp.watch, jest.watch);
-
package.jsonのscriptsを更新します
{
"scripts": {
"start": "npx gulp",
"build": "npx gulp build",
"test": "npx gulp test",
"format": "npx gulp format",
"slides": "npx gulp slides",
"docs": "npx gulp docs",
"watch": "npx gulp watch",
"heroku-postbuild": "webpack --config ./webpack.config.js --progress"
},
}
-
デプロイタスクを追加します
{
"scripts": {
"start": "npx gulp",
"build": "npx gulp build",
"test": "npx gulp test",
"format": "npx gulp format",
"slides": "npx gulp slides",
"docs": "npx gulp docs",
"watch": "npx gulp watch",
"deploy": "vercel",
"deploy:local": "vercel dev",
"deploy:heroku": "git push heroku wip/episode/00:master ",
"heroku-postbuild": "webpack --config ./webpack.config.js --progress"
},
}
-
npmタスクからgulpのdefaultタスクを実行します。
npm start