TL;DR
- https://github.com/3846masa/memi
- JSer のためのタスクランナー MEMI
- ES module で 1タスク 1Function で書ける
- 依存関係を自動でインストールしてくれる
なんで作ったのか
きっかけは mimorisuzuko/memi.
要約すると,
-
JavaScript で書けるタスクランナーが欲しい
- Makefile やシェルスクリプトは,凝った処理を書くのが怠い
- どのディレクトリでも手間なく使いたい
- Node.js に関係ないディレクトリで
node_modules
やpackage.json
を置きたくない
- Node.js に関係ないディレクトリで
- タスクで使うモジュールのグローバルインストールは避けたい
-
npm root -g
の場所とは別のところに置きたい
-
既存のタスクランナーと問題点
- Makefile
- シェルスクリプトで書かないといけないので,ちょっと複雑なことをしようとすると怠い
- Windows で make を入れるのが怠い
- npm scripts
-
package.json
を置きたくない
-
- gulp
- 使うモジュールもグローバルかローカルに入れないといけない
-
node_modules
を置きたくない - グローバルインストールは増やしたくない
-
- 使うモジュールもグローバルかローカルに入れないといけない
JSer のためのタスクランナー MEMI
Memifile.js
でタスクを定義できる.
import fs from 'fs-extra';
import path from 'path';
import execa from 'execa';
export default {
async clean() {
await fs.remove(path.join(__dirname, 'dist'));
},
async build() {
await this.clean();
await execa.shell('webpack');
},
};
ネストが気になる人や Default export 排除派は, Named exports でも書ける.
import fs from 'fs-extra';
import path from 'path';
import execa from 'execa';
export async function clean() {
await fs.remove(path.join(__dirname, 'dist'));
}
export async function build() {
await clean();
await execa.shell('webpack');
}
ついでに, CommonJS 方式でも書ける.
const fs = require('fs-extra');
const path = require('path');
const execa = require('execa');
module.exports = {
async clean() {
await fs.remove(path.join(__dirname, 'dist'));
},
async build() {
await this.clean();
await execa.shell('webpack');
},
};
タスクは,memi <taskname>
で実行する.例えば, build したいなら memi build
とすれば動く.
もちろんサブディレクトリ内にいても,Memifile.js
を再帰的に探しに行くので問題ない.
これを応用すると,ホームディレクトリに Memifile.js
を入れておくことで,どこでも使えるコマンドも作れる.
memi <taskname> arg1 arg2 ...
とすると,Function の引数に arg1
などが渡されるので,ちゃんとしたコマンドを作ることもできる.
Inquirer なども使えるので,対話式のコマンドも難なく作れる.
import inquirer from 'inquirer';
import cowsay from 'cowsay';
export default {
async echo(text) {
if (!text) {
const res = await inquirer.prompt([{
name: 'text',
message: "How's it going?",
}]);
text = res.text;
}
console.log(cowsay.say({ text }));
},
};
さらにここからが MEMI の真骨頂で,依存するモジュールを自動でインストールしてくれる.
例えば,上の Memifile.js
では, fs-extra
と execa
がインストールされる.
インストール先は $HOME/.memi
か %USERPROFILE%\.memi
になるので,グローバルと混ざらないし,ローカルに入れる必要もない.
MEMI は 小さいスクリプトを手間なく書き始められて ,出来が良ければ そのままホームディレクトリに突っ込んで,いつでも使える CLI コマンドにできる.
気軽にも使えるし,本格的にも使えるタスクランナー.
ぜひ使ってみてほしい.
余談: Qiita API と MEMI
この記事は VSCode から書いて API 経由で投稿したが,それも MEMI でざっくりコマンドを作った.
import 'dotenv/config';
import fs from 'fs-extra';
import fm from 'front-matter';
import axios from 'axios';
import opn from 'opn';
export async function qiita(file) {
if (!file) {
return;
}
const { attributes, body } = fm(await fs.readFile(file, 'utf8'));
const { data: res } = await axios.request({
method: 'post',
url: 'https://qiita.com/api/v2/items',
data: {
body,
title: attributes.title,
tags: attributes.tags.map(name => ({ name })) || [],
private: true,
},
headers: {
Authorization: `Bearer ${process.env.QIITA_TOKEN}`,
'Content-Type': 'application/json',
},
});
console.log(res.url);
opn(res.url);
}
memi qiita filename.md
とすれば,投稿されて URL がブラウザで開く.
しっかり作るなら更新機能とかも欲しくなるが,取っ掛かりとしてはこの程度から始めるのでも良い気がする.
余談: MEMI とは
発案者曰く,
柿崎芽実さんはけやき坂46のメンバーで,memiとmakeが似てるから選びました.推しは齊藤京子です.