React NativeでOSSのライセンス表記を楽にやりたい (続編)

昨日以下のようなブログを書いた。

www.keisuke69.net

この投稿ではlicense-checkerというツールを使って利用しているOSSライブラリの一覧とライセンス情報を出力し、それを読み取って画面に出力するという内容だった。

だがしかし、前回の投稿の最後に書いたようにとても重いのである。

なんかダサいし重いのでもうちょっと考えよう。。。

出力されるファイルが1万行近いものだったため、都度読み込んで表示するにはとても重い状態だったのである。ファイルの中身を見るとbabel関連などが--productionで指定しているにも関わらず出力されていた。また、--directというオプションを指定していたにも関わらずそれがあまり機能していないというIssueもあって未解決のようだった。

github.com

というわけで、前回の選定時には落としたnpm-license-crawlerというのを試してみた。

これはlicense-checker同様にnpmをスキャンしてJSONで結果を出力してくれるというものだが、license-checkerほどは利用されていないようだ。確かに出力するJSONの内容のカスタマイズなどはlicense-checkerのほうに分がある。

だがしかし、license-checker--directオプション相当の--onlyDirectDependenciesというオプションがあり、先ほどのIssueではこれが機能しているということだった。

というわけで早速試してみる。今回はyarn global addでインストールせずにnpxで実行する。

npx npm-license-crawler --dependencies --production --onlyDirectDependencies --omitVersion --json ./src/licenses.json

--omitVersionてのは出力にバージョン番号を含まないという指定。

そしてこの出力結果は以下のような感じである。

{
  "@react-native-community/async-storage": {
    "licenses": "MIT",
    "repository": "https://github.com/react-native-community/react-native-async-storage",
    "licenseUrl": "https://github.com/react-native-community/react-native-async-storage/raw/master/LICENSE",
    "parents": "patrolcommunity"
  },
  "@react-native-community/masked-view": {
    "licenses": "MIT",
    "repository": "https://github.com/react-native-community/react-native-masked-view",
    "licenseUrl": "https://github.com/react-native-community/react-native-masked-view",
    "parents": "patrolcommunity"
  },
  "@react-native-community/slider": {
    "licenses": "MIT",
    "repository": "https://github.com/react-native-community/react-native-slider",
    "licenseUrl": "https://github.com/react-native-community/react-native-slider",
    "parents": "patrolcommunity"
  },
  "@react-navigation/bottom-tabs": {
    "licenses": "MIT",
    "repository": "https://github.com/react-navigation/react-navigation",
    "licenseUrl": "https://github.com/react-navigation/react-navigation/raw/master/LICENSE",
    "parents": "patrolcommunity"
  },

以下略

以下略としたがlicense-checkerの出力と異なりbabel関連が出力されていないだけでなく全体的に直接的な依存関係にあるもの以外は出力されていないようだ。サイズ的にも300行ちょっととだいぶスリムになった。

残念ながら、license-checkerではライセンスファイルの中身そのものも出力できていたのだがそれはnpm-license-crawlerではできない模様。

というわけで、これを表示する処理は以下のように変更した。

import React from 'react'
import { Container } from 'native-base'
import { StyledScrollView, StyledView, NameText, LicenseText } from './styled'
import HyperLink from 'react-native-hyperlink'
import { Linking } from 'react-native'

interface LicenseFile {
  [key: string]: any
}

export const LicenseScreen: React.FC = () => {
  const licenseFile: LicenseFile = require('../../licenses.json')
  const licenseKeys = Object.keys(licenseFile)
  return (
    <Container>
      <HyperLink
        linkStyle={{ color: '#0071C8' }}
        onPress={(url: string): void => {
          Linking.openURL(url).catch((err) =>
            console.error("Can't open the url.", err)
          )
        }}
      >
        <StyledScrollView>
          {licenseKeys.map((packageName: string) => {
            const license = licenseFile[packageName].licenses
            const licenseUrl = licenseFile[packageName].licenseUrl
            return (
              <StyledView key={packageName}>
                <NameText>{packageName}:</NameText>
                <LicenseText>{license}</LicenseText>
                <LicenseText>{licenseUrl}</LicenseText>
              </StyledView>
            )
          })}
        </StyledScrollView>
      </HyperLink>
    </Container>
  )
}

export default LicenseScreen

基本的には前回とほぼ同じ内容でJSONの出力内容が少し異なるのでそれにあわせてプロパティ名を変更したくらい。ただし、TypeScriptの場合はJSONファイルを直接importしてmapで扱おうとすると以下のようなエラーが出る。

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 
No index signature with a parameter of type 'string' was found on type

というわけでちょいちょいと型を定義してあげて、それを指定してimportではなくrequireで読み込むことにした。あとは前述のとおりnpm-license-crawlerはライセンスファイルの中身そのものは出力してくれず、ライセンスファイルへのURLのみなので画面上もURLを表示してハイパーリンクを設定してブラウザで表示してもらうようにするためにreact-native-hyperlinkでまるっと囲みつつonPress()Linking.openURLを使ってブラウザでタッチされたURLを表示するようにした。

というわけでだいぶ軽くなったのでこれなら都度JSONを読み込んでもまあ使用に耐えうるということでいったんこれで行くことにした。

本当はビルドのタイミングで処理したりするのがいいんだろうけど。

©Keisuke Nishitani, 2020   プライバシーポリシー