web-dev-qa-db-ja.com

Expressのクライアント側ルーティングで複数の反応アプリを提供する

単一のサーバーに展開する必要がある単一のサービスに対して、さまざまなソフトウェア製品があります。クライアントは、サーバーがNode.jsとExpressを実行している間に、create-react-appによるビルドセットアップで、reactを使用してビルドされます。

サーバーから単一のアプリケーションを提供する場合、次の方法で行われます。

// App.js
// ...
// Entry point for data routes (API)
app.use('/data', indexRoute);

if(process.env.NODE_ENV !== 'development') {
  app.use(express.static(path.join(__dirname, 'build-client')));

  app.get('/*', function(req, res) {
    return res.sendFile(path.resolve( __dirname, 'build-client' , 'index.html'));
  });
}

サーバーから複数のアプリを提供できるようにしたい。どうすればいいですか?

私が試したのは、アセットに異なる静的パスを配線し、異なる名前でクライアントを分離することですが、機能しませんでした。このような:

// App.js
// ...
// Entry point for data routes (API)
app.use('/data', indexRoute);

if(process.env.NODE_ENV !== 'development') {
  app.use(express.static(path.join(__dirname, 'build-client')));
  app.use(express.static(path.join(__dirname, 'build-admin')));

  app.get('/client/*', function(req, res) {
    return res.sendFile(path.resolve( __dirname, 'build-client' , 'index.html'));
  });
  app.get('/admin/*', function(req, res) {
    return res.sendFile(path.resolve( __dirname, 'build-client' , 'index.html'));
  });
}

私もこのようにしてみましたが、エクスプレススローエラー:デフォルトのエンジンが指定されておらず、拡張機能が提供されていません:

if(process.env.NODE_ENV !== 'development') {
  // Admin paths
  app.use('/admin', express.static(path.join(__dirname, 'build-admin')));
  app.get('/admin/*', function(req, res) {
    return res.sendFile(path.resolve( __dirname, 'build-admin' , 'index.html'));
  });

  // Site paths
  app.use('/', express.static(path.join(__dirname, 'build-client')));
  app.get('/*', function(req, res) {
    return res.sendFile(path.resolve( __dirname, 'build-client' , 'index.html'));
  });
}

これまたは同様のことをどのように達成できますか?

12
sznrbrt

この問題でしばらく苦労した後、私は元の設定を損なうことなく可能な解決策を見つけました。

Express vhost package を使用して、仮想ドメインを介した要求の処理をセットアップしました。

アプリインスタンスを作成するときは、個別に公開するのと同じ数のExpressでアプリを初期化する必要があります(この場合、3つの個別のアプリと元のアプリインスタンス)

// Create an express instance
const app = express();
const appAdmin = express();
const appClient = express();
const appVendor = express();

その後、vhostをインストールしてインポートする必要があります。次に、各アプリの静的フォルダーを指定して、静的ファイルの提供を個別に処理できます。残りの部分では、特定のサブドメインのリクエストをそれぞれ処理します。

  appAdmin.use(express.static(path.join(__dirname, 'build-admin')));
  appClient.use(express.static(path.join(__dirname, 'build-client')));
  appVendor.use(express.static(path.join(__dirname, 'build-vendor')));

  appAdmin.use((req, res, next) => {
    return res.sendFile(path.resolve( __dirname, 'build-admin' , 'index.html'));
  });

  appClient.use((req, res, next) => {
    return res.sendFile(path.resolve( __dirname, 'build-client' , 'index.html'));
  });

  appVendor.use((req, res, next) => {
    return res.sendFile(path.resolve( __dirname, 'build-vendor' , 'index.html'));
  });

  app.use(vhost('domain.com', appClient));
  app.use(vhost('www.domain.com', appClient));
  app.use(vhost('a.domain.com', appAdmin));
  app.use(vhost('b.domain.com', appVendor));

ドメインのDNSレジストリに目的のサブドメインを追加することを忘れないでください。例:

...records
CNAME   vendor  @
CNAME   admin   @
5
sznrbrt

いじくり回した後、仮想ホストを使用せずにこれを達成することができました。メインアプリをルート(つまり、_/_)に残した以外は、あなたが質問で最初に挙げたアイデアを使用しました。

_// when going to `/app2`, serve the files at app2/build/* as static files
app.use('/app2', express.static(path.join(__dirname, 'app2/build')))
// when going to `/`, serve the files at mainApp/build/* as static files
app.use(express.static(path.join(__dirname, 'mainApp/build')))


// These are necessary for routing within react
app.get('app2/*', (req, res) => {
  res.sendFile(path.join(__dirname + '/app2/build/index.html'))
})

app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname + '/mainApp/build/index.html'));
});
_

この後、私は_mainApp/package.json_に入り、追加しました

_"proxy": "http://localhost:4141"
_

_:4141_は、Expressサーバーが実行されているポートです。この行は、fetch('/some/route')への呼び出しを行い、reactアプリ自体ではなくサーバーに戻ります。

最後に、_app2/package.json_に移動して、

_"proxy": "http://localhost:4141/app2",
"homepage": "/app2"
_

ここのキーは_"homepage"_キーだと思います。私が理解している方法では、reactが開始すると、ホームページでいくつかの静的ファイルが検索されます。_"homepage"_なしでは、空白の白い画面またはmainAppしか取得できませんでした。

これが誰かの役に立つことを願っています!

7
Danny Harding