deepblue-will’s diary

JS、CSS,Ruby、Railsなど仕事や趣味で試した技術系のことを書いていきます。

Angular Libraryでハマったこと

現在携わってるプロダクトで、Angular CLIのライブラリ作成機能をつかうことにしたので、その時ハマったことを紹介。

Angular Library

Angular CLIにはアプリケーションを作る機能だけでなく、アプリケーション内で使うライブラリを作成する機能があります。
作り方は簡単で my-lib というライブラリを作りたいなら

$ ng generate library my-lib

このように ng generate コマンドでライブラリ用のprojectを生成することができます。
作成したライブラリはビルドしてから各アプリケーションで参照する形で使用します。
また、npmにも簡単に公開できる仕組みも用意されています。

詳しくは Creating Libraries を見てみてください。

ハマったこと

何点かlibraryを作る上でハマったポイントがあったのでそれを紹介します。

moment

ビルドしたらmomentがないよ!って怒られました。

BUILD ERROR
Cannot call a namespace ('moment')
Error: Cannot call a namespace ('moment')

momentに限らず import * as xxx from 'xxx' でimportしてるライブラリはビルド時に怒られます。
その場合は、このようにするとビルドがとおります。

import * as _moment from 'moment'
const moment = _moment
type Moment = _moment.Moment

ただ、これだけだとビルドは通るようになりますが、以下のようなWarningはでてしまうます。

No name was provided for external module 'moment' in output.globals – guessing '_moment'

このwarningは ng-package.json に以下を追加すると解消します

{
  ...
  "lib": {
    ...
     "umdModuleIds": { // これを追加
       "moment": "moment"
    }
  }
}

index.ts

index.tsディレクトリ内のすべてのファイルをexportして、rootにおいてある public-api.ts はそれ参照するようにしていたのですが、これだと何故かlibraryを利用しているアプリのproductionビルドが通りませんでした。(library自体のビルドはできます)

ERROR in : Unexpected value 'XXXModule in xxx/xxx.d.ts' imported by the module 'YYYModule in yyy.module.ts'. Please add a @NgModule annotation.

index.ts を作るのをやめて、各ディレクトリに public-api.ts をおいて、それを参照するようにしたらビルド通るようになりました。
ただ、Angular MaterialとかNG-ZORRO など他のライブラリを見ると index.ts があるので、もしかしたら方法があるのかもしれません。

tsconfigのpaths

Angular libraryをnpmに公開せず、内部だけで使用する場合、以下のフローになります。
ライブラリをビルド→/distなどに配置→各アプリケーションは/distにあるライブラリを参照。
この/distのものを参照するためにTypescriptのパスマッピングという機能を使うことになります。これはtsconfigのpathsの設定で行います。

{
  "compilerOptions": {
    "paths": {
      "my-lib": ["/dist/my-lib"],
      "my-lib/*": ["/dist/my-lib/*"]
    }    
  }
}

このように定義しておくとアプリケーション側は

import { XXX } from `my-lib`

と、このようにimportできるようになります。
ただ、このパスマッピングの設定で気をつける点があります。
それはライブラリにあるpackage.jsonname に設定しているライブラリ名とパスマッピングで実際importすることになる名称を揃えないと、利用側のアプリのProductionビルドで失敗します。
例えば、package.json

{
  "name": "xxx-my-lib"
}

という名前をつけたのであれば、

{
  "compilerOptions": {
    "paths": {
        "xxx-my-lib": ["/dist/my-lib"],
         "xxx-my-lib/*": ["/dist/my-lib/*"]
    } 
  }
}

と、このようにしないと、アプリケーションのビルド時にエラーになります。

React v16.2 ~ v16.7で入った新機能

ここ1年ぐらい古いverのReactで開発し続けていて、最近ようやく最新のReactに対応したのでここ1年ぐらいでどんな機能が追加されてのかまとめてみることにしました。

※ v16.5, v16.7は大きな機能追加がなかったみたいなので書いてないです

続きを読む