この記事では、わざわざTypeScriptでnpmライブラリ開発したいという読者を対象としています。
とはいえ今どきはVS Codeさんという素晴らしいエディターのおかげもあって、型が提供されていないnpmライブラリは使いづらい立場にあります。
では早速ですが、TypeScriptで"Hello だれだれ"とコンソールに表示されるnpmライブラリを開発してみましょう。
基本的なnpmライブラリ開発の知識
この記事では「TypeScriptで」npmライブラリ開発することに主眼を置きたいため、基本的なnpmライブラリ開発の知識は「本当にやさしいnpmライブラリ開発入門」くらいは知っている前提で進めます。
package.jsonのあれこれ
私の趣味は人の書いたpackage.jsonを見ることです。(趣味悪いでしょうw)
ではまずは今回お題にするpackage.jsonを見ていただきましょう。
{
"name": "hello-world-typescript",
"version": "1.0.0",
"main": "dist/index.js",
"license": "MIT",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"prepublishOnly": "npm run build"
},
"devDependencies": {
"typescript": "^3.3.4000"
}
}
とても綺麗ですよね。
ひとつひとつ意味があるので解説していきます。
package.json#name
npmライブラリの名前です。require('xxx')のxxxにあたるアレです。
package.json#version
npmライブラリはこのバージョン情報を毎回インクリメントして公開する必要があります。
TypeScriptが一度3.3.3333というアレなバージョンをつけてしまったために、3.3.4にできずに3.3.4000になってしまったのは、笑えない笑える話として有名かもしれませんね。
package.json#main
ここに相対パスで有効なJavaScriptファイルが指定されていないとrequire('xxx')できません。
今回はTypeScriptのビルド結果を読み込ませたいので、dist/index.jsになっています。
package.json#files
package.jsonのfilesプロパティは、使う人と使わない人がいると思います。
Webpackのincludeオプションとexcludeオプションに似ていて、前者はpackage.jsonのfilesプロパティ、後者は.npmignoreです。
要はnpmはライブラリをnpm publishコマンドで公開する際に、filesプロパティが指定してあればそれらのみを公開対象とします。
TypeScriptはtscコマンドでビルドする前提なので、filesプロパティにビルド結果フォルダを指定してやると楽だよ、という話になるわけです。
package.json#scripts
npm run xxxを作れるプロパティですね。
npm run buildは実際にはtscコマンドを実行するところはみなさんお分かりかと思います。
prepublishOnlyがニッチなやつで、npm publishをする「前に」必ず実行されるという意味になります。
今回はnpm run buildを必ず走らせてからライブラリ公開したいので、これを指定しています。(開発したのにビルド忘れてバージョンしか上がらなかったという事故を防ぐやつです。)
ちなみに、scriptsプロパティにはいくつかのマジックがありまして、それが今回のpreにあたります。
例えばnpm run xxxを実行する場合、prexxxとpostxxxを作成しておくと、それぞれ実行前と後に指定されたコマンドが叩かれたりします。
(なかなか便利なのですが駆使しすぎるとpackage.jsonの管理が大変になるので注意。)
tsconfig.json
お待たせしました。
みなさんこれが早く見たかったですよね。
ご査収ください。
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"moduleResolution": "node",
"strict": true,
"skipLibCheck": true,
"declaration": true,
"pretty": true,
"newLine": "lf",
"outDir": "dist"
}
}
ニッチなところだけ説明していきますね。
targetとmoduleはどのようなライブラリの種類にするのか(Node.jsで利用されるのか、ブラウザで利用されるのか等)によって変わってきます。今回は最新のNode.jsで叩くだけのライブラリですのでtarget: "esnext"のmodule: "commonjs"になります。Node.jsで利用される場合は常にmodule: "commonjs"と覚えておいても構いません。
せっかくなのでTypeScriptにきちんと仕事をさせたい。なのでstrict: trueにします。
でもライブラリのエラーが無限に出てくることがあるので、それは無視するためにskipLibCheck: trueにします。
型定義をきちんと出力したいので、declaration: trueにします。
あとWindowsで開発したい方は、クロスプラットフォームでの利用を念頭に改行コードをLFに寄せます。そのためにnewLine: "lf"します。
(例えばコマンドラインツール系のnpmライブラリをWindowsで開発した際に、Linux等で実行するとエラーになります。それを防ぐために改行コードをLFに寄せます。)
最後に今回はdistフォルダにコンパイル結果を出力したいので、outDir: "dist"とします。
TypeScriptでnpmライブラリ開発
やっと開発に入りますが、もう終わったようなものです。
function hi(name: string) {
console.log(`Hello ${name}`);
}
export default hi;
ビルドしてみます。
$ npm run build
distにビルド結果が出ました。
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function hi(name) {
console.log(`Hello ${name}`);
}
exports.default = hi;
型定義も出力されています。
declare function hi(name: string): void;
export default hi;
最後にnpmライブラリとして公開してみます。
$ npm publish
ちゃんとnpm run build(tsc)されてから公開されましたね。
まとめ
- TypeScriptはコンパイル作業が必要なので、事前準備がひと手間かかる
- それをクリアすればTypeScriptでもサクサクnpmライブラリ開発ができる!
いかがでしたでしょうか。
私は.NETやらTypeScriptやらでMicrosoftさんにはお世話になっていますが、型安全なのはとても気持ちいいです。
少しでも皆さまのお役に立てたらと思います。
では良いTypeScriptライフを!!