web-dev-qa-db-ja.com

MERNスタック-ExpressとReact同じポート上にありますか?

MERN(MongoDB、Express、React、Node)スタックを使用してプロジェクトに取り組んでいますが、Reactコンポーネント内のフォームから定義されたAPIエンドポイントにデータを投稿するときに問題が発生しますNode.jsで。フォームを送信すると、ブラウザーにCANNOT POSTエラーが表示されます。フォーム送信用のイベントハンドラーを作成すると、Reactそして、この問題を回避できるAxiosなどのライブラリを使用してPOSTを処理します。

しかし、最終的には、この問題はNodeバックエンドがReactフロントエンドとは異なるポートで実行されているためだと思います。自分で設定できる方法はありますか?スタックして、標準形式POSTを使用し、FEとBEを同じポートで実行できるようにしますか?

3
James Howell

しかし、最終的には、この問題はNodeバックエンドがReactフロントエンドとは異なるポートで実行されているためだと思います。

はい、

MERNは素晴らしいです。私の唯一の問題は、React側でMongooseを使用できなかったことです。この問題に遭遇し、数時間後、より良い解決策を見つけました。

Package.jsonに何も置く必要はなく、CORSについて心配する必要もありません。

これは、mongooseを使用したユーザー登録の実際の例です(mongooseはクライアント側で実行されることはなく、時間を無駄にしないでください。ライブラリの変更には時間がかかります)、

expressサーバーをポート(たとえば3030)で起動すると、Reactは3000で実行され、

on React side

constructor(){ 
...
  this.server = server || 'https://my.ip.add.ress:3030'
...
}

register(username, password, signup = true) { 
return this.fetch(`${this.server}/server/register`, {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                username,
                password,
                signup
            })
        }).then(res => { console.log(res);
            this.setToken(res.token) // Setting the token in localStorage
            return Promise.resolve(res);
        })
}

Node.JSサーバー(エクスプレス)側

フォルダ「server」を作成し、ファイルserver.jsを作成します。

var MongoNode   = require('mongoosenode')   // I created this package for just to test mongoose which doesn't run on React side, 
var cors        = require('cors');  //use cors for cross-site request

var options = {
        key     : fs.readFileSync('server.key'),
        cert    : fs.readFileSync('server.cert'),
    };

    /*
     * Cors Options
     */ 
    var whitelist = config.allowedOrigins //put https://my.ip.add.ress:3000 in the allowedOrigins array in your config file
    var corsOptions = {
        Origin: function (Origin, callback) {
            if (whitelist.indexOf(Origin) !== -1) {
                callback(null, true)
            } else {
                callback(new Error('Not allowed by CORS'))
            }
        }
    }
    //specify the port
    var https_port = config.server.port || 3030;

    //use app or any route included to server.js
     app.post('/register', cors(corsOptions),function(req, res) {
        //Process requests
        console.log(req.body);  //see if request payload popping up
        var mn = new MongoNode('mongodb://username:[email protected]:27017/databasename')

        var user = mn.retrieveModel('User','User').then(async(res) => { 
           try { 
             user = res.model;
              console.log(user);
              user.username = req.body.username
              user.password = req.body.password
              user.token = token_str  //jwt web token to save browser cookie 
              user.save(function(err) {
                 if (err) throw err;
                 console.log('user saved successfully');
                 res.json({ success: true, token: user.token});
              });                  

           }catch(e) { 
             console.log(e);
           }
        })

        user.save(function(err) {
            if (err) throw err;
            //console.log('user saved successfully');
            res.json({ success: true , message: 'user saved successfully', token : user.token });
        });

    }

出来上がり!数時間読んだ後、簡単にできます。

0
Cosmo Arun

私はこれが答えるのが遅いことを知っていますが、もう一つの解決策を探している人には役立つかもしれません。このソリューションは、reactアプリケーションまたはangularアプリケーションで、同じポートにノードバックエンドがあり、Dockerを使用してイメージを作成している場合に適用できます。

したがって、プロジェクトを本番レベルでデプロイするときはいつでも。 angularをビルドするか、npm run buildを使用してプロジェクトに反応し、ExpressアプリでExpressStaticを使用してビルドフォルダー全体を提供するだけです。

したがって、Dockerファイルは次のようになります

# The builder from node image
FROM node:8-Alpine as web-app

# Move our files into directory name "app"
WORKDIR /app
COPY package.json /app/
RUN cd /app && npm install
COPY . /app
RUN cd /app && npm run build  // build your front end

EXPOSE 5000

CMD [ "node", "server.js" ] // start your backend

これにより、ポート5000でバックエンドが開始されます。

今あなたのapp.jsファイルで、このようにビルドフォルダを提供します

app.use(express.static(path.join(__dirname, 'build')))

あなたがあなたの地元でそれをテストしたいなら。上記のDockerファイルを作成し、上記のようにapp.jsを変更して、静的ファイルを提供できます。そして、このようにDockerイメージをビルドして開始します

docker build . -t web-app
docker run -p 5000:5000 web-app

これで、フロントエンドは本番レベルでビルドされ、エクスプレスから提供されます。

ローカルでは、いつでも両方のポートを開発用に開始し、reactまたはangularフロントエンドの変更後の自動リロードなど)によって提供される機能を使用して、開発を容易にすることができます。

0
Ani