MERN(MongoDB、Express、React、Node)スタックを使用してプロジェクトに取り組んでいますが、Reactコンポーネント内のフォームから定義されたAPIエンドポイントにデータを投稿するときに問題が発生しますNode.jsで。フォームを送信すると、ブラウザーにCANNOT POSTエラーが表示されます。フォーム送信用のイベントハンドラーを作成すると、Reactそして、この問題を回避できるAxiosなどのライブラリを使用してPOSTを処理します。
しかし、最終的には、この問題はNodeバックエンドがReactフロントエンドとは異なるポートで実行されているためだと思います。自分で設定できる方法はありますか?スタックして、標準形式POSTを使用し、FEとBEを同じポートで実行できるようにしますか?
しかし、最終的には、この問題は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 });
});
}
出来上がり!数時間読んだ後、簡単にできます。
私はこれが答えるのが遅いことを知っていますが、もう一つの解決策を探している人には役立つかもしれません。このソリューションは、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フロントエンドの変更後の自動リロードなど)によって提供される機能を使用して、開発を容易にすることができます。