News

Facebook Icon Twitter Icon Linkedin Icon

AnyMind Group

Facebook Icon Twitter Icon Linkedin Icon

[Tech Blog] Typescriptによるnpm packageの作成

はじめに

はじめまして、AnyManagerのエンジニアの鳥居と申します。

新卒でAnyMindに入社してから、AnyManagerの開発に携わっております。

今回は開発をする中で、Typescriptでnpm packageの作成をする事がありましたので、その方法を紹介したいと思います。

環境

弊社では以下の環境、ツールを使って開発を行っております

  • MacOS Catalina 10.15.7
  • Bitbucket:リポジトリ管理ツール。作成したモジュールのリポジトリを管理しています。
  • Typescript 4.6.3

実現したい事

以下のようなことをゴールとします。

  • typescriptで作成したモジュールをjavascriptにコンパイルし、異なるリポジトリ内ででモジュールを呼び出し可能にする。

Repositories

以下のようなリポジトリ構成で話を進めます。

  • Main Repository: 処理のエントリーポイント。Module 1とModule 2を内部でimport。
  • Module 1: Main Repositoryで使用されるmodule。Module 3を内部でimport。
  • Module 2: Main Repositoryで使用されるmodule。Module 3を内部でimport。
  • Module 3: Module 1とModule 2で共通してimportされるmodule。

ゴールを達成するためには、tsconfig.jsonとpackage.jsonを正しく設定しなければなりません。

tsconfig.jsonの設定(Module1、Module2、Module3側)

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",                                
    "module": "commonjs",                           
    "declaration": true,
    "outDir": "./dist",           
    "strict": true                            
  },
  "include": ["src/**/*"]
}
  • declaration: コンパイル時に.d.tsファイルを作成する必要があるのでtrueにします。
  • target: どのjavascriptのバージョンにトランスパイルするかを指定します。今回はコンパイルされたjavascriptがブラウザで動作するかつ、古いブラウザでも動作するようにes5を指定しています。 Typescript公式ドキュメント
  • outDir: javascriptをどのディレクトリ配下に配置するかを指定します。

declarationMapをtrueにすると、エディターなどで定義元のファイルに飛ぶ際に、.d.tsファイルではなく、.tsファイルに飛べるようになります。 ただし、今回はコンパイルのアウトプットに*.tsファイルを含めないので省略しています。

packages.jsonの設定(Module1、Module2、Module3側)

nameをモジュール名に応じて適宜変更してください

package.json

{
  "name": "@anymind/module3",
  "version": "1.0.0",
  "private": true,
  "files": ["dist"],
  "main": "dist/index.js",
  "scripts": {
    "clean": "rm -rf dist",
    "build": "npm run clean ; tsc"
  },
  "devDependencies": {
    "typescript": "^4.3.4"
  }
}
  • nameでimportする際のモジュールの名前を指定します。例のように階層を定義した場合、モジュールはnode_modules/anymind/module3に配置されます。
  • filesにnpm install時にインストールされるファイルまたはディレクトリを指定します。dist配下のファイルのみ必要なので、distと指定します。
  • mainで指定されたファイルにあるモジュールを、モジュールの呼び出し側は、nameで指定したpathからモジュールをimportすることができます。

(例)mainでモジュールのpathを指定することで、以下のようにコンパクトに記述することが可能です。

module3/package.json

{
  "main": "dist/index.js"
}

module3/dist/index.js

export * from "./functions";

module3を呼び出す側

import { func1 } from "@anymind/module3";
//  以下と同様
import { func1 } from "@anymind/module3/dist/functions";
  • buildではtscコマンドを実行することでtypescriptをjavascriptにコンパイルします。

参考 package.jsonドキュメント

package.jsonの設定(Main Repository、Module1、Module2側)

弊社ではBitBucketをリポジトリ管理ツールとして使用しているので、package.jsonのdependenciesには以下のように記載します。

Module1のmasterブランチを使用する際は#masterのようにハッシュをリポジトリ名の後に付与します。

参考: Private NPM Packages in Bitbucket

Main Repository

{
  "dependencies": {
    "@anymind/module1": "bitbucket:adasiaholdings/module1#master",
    "@anymind/module2": "bitbucket:adasiaholdings/module2#master"
  }
}

Module1

{
  "dependencies": {
    "@anymind/module3": "bitbucket:adasiaholdings/module3#master"
  }
}

Module2(Module1と同様)

{
  "dependencies": {
    "@anymind/module3": "bitbucket:adasiaholdings/module3#master"
  }
}

以上のように設定することで、異なるリポジトリ内で作成したモジュールを呼び出すことができます。

Latest News