在Netlify上部署Express时显示API路由

我用create-react-app创build了一个网站,我在./client/build构build并使用express 。

使用快递 ,我还设置了2个基本的API路由,在dev(localhost)中运行良好。

我在Netlify上部署什么 ?

我用react-scripts构build客户端
然后,我手动将环境设置为生产,以使用webpack在本地构build服务器
最后,我将代码推送到我的GitLab仓库,并自动触发部署。

使用Netlify部署的设置:

 Build command: Not set Publish directory: client/build 

问题

当我尝试使用我的API路由之一,我得到一个错误404 …

项目

我的项目结构是这样的:

 | package.json | server.js | webpack.config.js +---API | dbHandler.js | routesHandler.js +---client | | package.json | +---src | | | App.js | | | ... | +---node_modules | +---public | | index.html | | manifest.json | | _redirects | \---build | | index.html | | manifest.json | | _redirects | | asset-manifest.json | | favicon_rings.ico | | service-worker.js | \---static | +---media | | ... | +---js | | main.1e7ccdbf.js | | main.1e7ccdbf.js.map | \---css | main.fc8f2d26.css | main.fc8f2d26.css.map +---public | _redirects \---bundles bundle.js 

./package.json提取:

 "main": "server.js", "homepage": "https://custom.netlify.com", "scripts": { "start": "node server.js", "build": "webpack --config webpack.config.js", "postinstall": "npm run build", "start:dev": "nodemon -e js --exec babel-node -- ./server.js" } 

./client/package.json

 "homepage": "https://custom.netlify.com", "scripts": { "start": "react-scripts start", "build": "react-scripts build && cp build/index.html build/404.html", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" }, "proxy": "http://localhost:5000" 

./client/build/_redirects./public/_redirects

 # Redirects from what the browser requests to what we serve /* /index.html 200 

./server.js

 import webpackDevMiddleware from "webpack-dev-middleware"; import webpackHotMiddleware from "webpack-hot-middleware"; import routesHandler from "./API/routesHandler"; import config from "./webpack.config"; import bodyParser from "body-parser"; import webpack from "webpack"; import express from "express"; import path from "path"; const port = process.env.PORT || 5000; const ExpressServer = express(); const CLI_BUILD_DIR = path.join(__dirname, "client/build"); const HTML_BUNDLE = path.join(CLI_BUILD_DIR, "index.html"); const compiler = webpack(config); const isDevelopment = process.env.NODE_ENV === "development"; ExpressServer.use(bodyParser.urlencoded({ extended: true })); ExpressServer.use(bodyParser.json()); ExpressServer.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header( "Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept" ); next(); }); if (isDevelopment) { ExpressServer.use( webpackDevMiddleware(compiler, { publicPath: config.output.publicPath }) ); ExpressServer.use(webpackHotMiddleware(compiler)); } else { // Serve static files from the React app ExpressServer.use(express.static(CLI_BUILD_DIR)); } // Define API routes var router = express.Router(); router.post("/register", routesHandler.register); router.post("/login", routesHandler.login); // Put all API endpoints under '/API' ExpressServer.use("/API", router); // All other routes will be directed to the main page of user interface ExpressServer.get("/", (req, res) => res.sendFile(HTML_BUNDLE)); ExpressServer.get("*", (req, res) => res.redirect(301, "/")); // Start the server ExpressServer.listen(port, function() { console.log("Express server listening on http://localhost:" + port); }); 

./webpack.config.js

 const path = require('path'); const webpack = require('webpack'); process.env.NODE_ENV = process.env.NODE_ENV || 'development'; module.exports = { entry: [ 'webpack-hot-middleware/client', './API/routesHandler.js', './API/dbHandler.js', './server.js' ], externals: { jquery: 'jQuery', 'react/addons': 'react', 'react/lib/ExecutionEnvironment': 'react', 'react/lib/ReactContext': 'react', }, output: { path: path.resolve(__dirname, 'bundles'), filename: 'bundle.js', publicPath: '/public', sourceMapFilename: 'bundle.map', }, devtool: process.env.NODE_ENV === 'production' ? undefined : 'cheap-module-eval-source-map', resolve: { modules: ['node_modules', './client/build', './API', '.'], extensions: ['.js', '.jsx', '.css'], }, module: { rules: [ { test: /(\.js$|\.jsx$)/, exclude: /(node_modules|bower_components)/, use: [ { loader: 'babel-loader', options: { presets: ['react', 'es2015', 'stage-0', 'airbnb'], }, }, ], }, { test: /(\.css$|\.scss$)/, use: ['style-loader', 'css-loader', 'sass-loader'], }, { test: /\.(eot|svg|ttf|woff|woff2|png|jpg|jpeg|gif)(\?v=\d+\.\d+\.\d+)?$/, use: { loader: 'file-loader', options: { name: '[name].[ext]' } } } ], }, node: { console: false, fs: 'empty', fsevents: 'empty' }, plugins: [ new webpack.IgnorePlugin(/fs/)], new webpack.optimize.OccurrenceOrderPlugin(), new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin(), new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', }), new webpack.optimize.UglifyJsPlugin({ sourceMap: true, minimize: true, compressor: { warnings: false, }, }), new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV) }, }), ], }; 

Netlify是用于静态文件托pipe – 你不能部署一个Express应用程序,只有你的前端。 您需要为您的API托pipe使用不同的服务(如DigitalOcean或Heroku)。 如果您想使用自己的CDN进行响应caching,则可以使用redirect通过Netlify 将stream量路由到该API服务器。