npm
React

アプリケーションを跨いでプライベートな共通npmモジュールを使う方法

はじめに

今回、私が試したのはReact、PostCSSを使っているプロジェクトです。基本的に各プロジェクトがGitHubで管理されているものとします。
Reactのバージョンなどは後述のpackage.jsonをご確認ください。

今回やりたいこと

こんな感じで、各アプリケーションにそれぞれcommonが存在してしまっている状態でした。
commonの中には各アプリケーションで汎用的に使えるcomponentやhelperメソッドやutil的なstyleなどが入っています。

├─ app_1
|   ├─ admin
|   ├─ user
|   ├─ common
|
├─ app_2
    ├─ admin
    ├─ user
    ├─ common

二重管理になってしまっていたcommonを下記のようにプライベートな共通npmモジュールとして使えるようにしたいというのが今回の趣旨になります。

├─ common
├─ app_1
├─ app_2

プライベートな共通npmモジュールを作る

srcの中で開発を進めるようにします。今回はes2015で書いているので、npmモジュールとして使うためにbabelでトランスパイルする必要があります。トランスパイルされたものの置き場所としてpublicがあります。

├─ common
    ├─ public
    ├─ src
        ├─ components
        ├─ helper
        ├─ styles

package.json

はじめにnpm run buildをしたらあとはnpm startでwatchしながら開発する形になります。

{
  "name": "common",
  "version": "0.0.1",
  "description": "",
  "main": "./bundle.js",
  "scripts": {
    "build": "npm run build:babel & npm run build:css",
    "build:babel": "npm run clean && ./node_modules/.bin/babel ./src --out-dir ./public",
    "build:css": "npm run clean && postcss --u postcss-import postcss-cssnext cssnano --dir public/css/ src/styles/**/*.pcss",
    "start": "npm run watch:babel & npm run watch:css",
    "watch:babel": "./node_modules/.bin/babel ./src --out-dir ./public -w",
    "watch:css": "postcss --u postcss-import postcss-cssnext cssnano --dir public/css/ src/styles/**/*.pcss -w",
    "clean": "rimraf ./public"
  },
  "devDependencies": {
    "babel-cli": "6.26.0",
    "babel-core": "6.26.0",
    "babel-eslint": "8.1.2",
    "babel-loader": "7.1.2",
    "babel-plugin-transform-class-properties": "6.24.1",
    "babel-plugin-transform-object-rest-spread": "6.26.0",
    "babel-plugin-transform-react-constant-elements": "6.23.0",
    "babel-plugin-transform-react-remove-prop-types": "0.4.12",
    "babel-preset-es2015": "6.24.1",
    "babel-preset-react": "6.24.1",
    "css-loader": "^0.28.0",
    "cssnano": "^3.10.0",
    "eslint": "4.14.0",
    "eslint-plugin-react": "7.5.1",
    "file-loader": "1.1.6",
    "postcss": "6.0.15",
    "postcss-cli": "4.1.1",
    "postcss-cssnext": "3.0.2",
    "postcss-import": "11.0.0",
    "postcss-loader": "2.0.10",
    "rimraf": "2.6.2",
    "style-loader": "0.19.1",
    "stylelint": "8.4.0",
    "stylelint-config-standard": "18.0.0"
  },
  "dependencies": {
    "babel-polyfill": "6.26.0",
    "classnames": "2.2.5",
    "prop-types": "15.6.0",
    "react": "16.2.0",
    "react-dom": "16.2.0"
  }
}

各アプリケーションで呼び出す

package.jsonで呼び出しできるようにします。ブランチの指定とか、バージョンの指定もできるみたいです。これにより、こっちのプロジェクトでは、まだAPIの実装できてないから一旦npmモジュールの方のバージョンはあげないでおこうとかできそうな予感。

参照: package.json | npm Documentation

{
  "name": "app_1",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "dependencies": {
    "common": "git+ssh://git@github.com:hogeAccount/common.git",
    ・・・
  }
}

あとは普通にnpmパッケージを使うのと一緒です。

rm -rf package-lock.json // 必要なら
rm -rf node_modules // 必要なら
npm install
npm run build
npm start

npmパッケージ使うのと同じなので、例えばcomponentsを使いたければ以下のような感じで使えます。

import hoge from 'node_modules/common/public/components/hoge'

<hoge>ホゲホゲ</hoge>

問題点

ただ、このままだと開発時に問題というかめんどくさい部分があります。というのも、GitHubに上がっているものを使うことになるのでcommonリポジトリをいちいちpushしてから
アプリケーション側でnpm update,npm startをやり直さなければなりません。ステージングやプロダクションであればそれで問題ないのですが、どうしても開発している時、特に開発の初期段階ではcommonをいじることはどうしても避けられません。(commonという性質上あまり変更が加わるのはあまり良いとは言えないけど・・・)

問題点の改善

開発がスムーズに行えるように改善します。

1. commonリポジトリをclone

commonリポジトリをローカル環境にcloneします。

2. webpackの設定

webpackにてaliasにcommonリポジトリを登録します。ちなみに、開発環境とステージング・プロダクション環境で呼び出しを変えたいのでwebpack.config.jswebpack.production.config.jswebpack.staging.config.jsが必要になります。

webpack.config.js

・・・
resolve: {
  modules: ["node_modules"],
  alias: {
    common: path.join(__dirname, '../../project-common/public') //任意の相対パス
  }
},
・・・

webpack.production.config.js, webpack.staging.config.js

・・・
resolve: {
  modules: ["node_modules"],
  alias: {
    common: path.join(__dirname, './node_modules/project-common/public')
  }
},
・・・

3. 開発するときはwatch必須

開発する時には共通npmモジュール側でbabel等でwatchしている状態にしなければ変更を加えても、ブラウザ上に反映されません。

npm start

これでimportは下記のようにすれば、開発とステージング等で呼び出すモジュールを変えられます。

import hoge from 'common/componetns/hoge'

<hoge>ホゲホゲ</hoge>

最後に

以上、参考になれば幸いです。

また必要に応じて追記・更新したいと思います。