将Node Express应用部署到服务React应用的Heroku

时间:2019-09-07 07:19:39

标签: node.js reactjs express heroku webpack

我正在尝试将我的express,node和react应用程序部署到heroku。一切都可以完美构建和运行。但是,当我尝试发送时,部署因语法错误而失败。它应该编译所有内容,但令人窒息。配置不是我的专长。你能帮我吗?谢谢!

这是错误(还显示了我的server / index.js文件的样子)

remote:            Module build failed: SyntaxError: /tmp/build_932acc5e4d70ba43150e066b1e0f5fe1/src/server/index.js: Unexpected token (45:6)
remote:            
remote:              43 | app.get("*", (req, res, next) => {
remote:              44 |     const markup = renderToString(
remote:            > 45 |       <StaticRouter location={req.url} context={{}}>
remote:                 |       ^
remote:              46 |         <App />
remote:              47 |       </StaticRouter>
remote:              48 |     )

我也收到客户端的错误

remote:            ERROR in ./src/browser/index.js
remote:            Module build failed: SyntaxError: /tmp/build_932acc5e4d70ba43150e066b1e0f5fe1/src/browser/index.js: Unexpected token (10:2)
remote:            
remote:               8 | 
remote:               9 | const jsx = (
remote:            > 10 |   <Router><App /></Router>
remote:                 |   ^
remote:              11 | )
remote:              12 | 
remote:              13 | hydrate(

这是我的package.json

{
  "name": "client",
  "version": "0.1.0",
  "private": true,
  "main": "index.js",
  "scripts": {
    "dev": "webpack -w & nodemon server.js",
    "start": "webpack & node server.js",
    "heroku-postbuild": "yarn && yarn build",
    "build": "webpack"
  },
  "dependencies": {
    "@babel/plugin-transform-runtime": "^7.5.5",
    "@babel/runtime": "^7.5.5",
    "@emotion/core": "^10.0.16",
    "aws-sdk": "2.x",
    "babel-loader": "^8.0.6",
    "bcrypt": "^3.0.6",
    "body-parser": "~1.18.2",
    "cookie-parser": "~1.4.3",
    "cors": "^2.8.5",
    "debug": "~2.6.9",
    "ejs": "2.x",
    "es6-promise": "^4.2.8",
    "express": "^4.17.1",
    "form-data": "^2.3.2",
    "fs": "^0.0.1-security",
    "history": "4.9.0",
    "http": "0.0.0",
    "isomorphic-fetch": "^2.2.1",
    "jade": "~1.11.0",
    "jsonwebtoken": "^8.1.1",
    "mime": "^2.2.0",
    "mongodb": "^3.0.1",
    "mongoose": "^4.13.9",
    "morgan": "~1.9.0",
    "multer": "^1.3.0",
    "multer-s3": "^2.7.0",
    "prop-types": "^15.7.2",
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
    "react-router-dom": "^5.0.1",
    "react-scripts": "1.1.0",
    "react-validation": "3.0.7",
    "request": "^2.83.0",
    "serialize-javascript": "^1.8.0",
    "serve-favicon": "~2.4.5",
    "validator": "^11.1.0",
    "webpack-node-externals": "^1.7.2",
    "webpack-cli": "^3.3.7",
    "webpack-dev-server": "^3.8.0"
  },
  "devDependencies": {
    "@babel/cli": "7.6.0",
    "@babel/core": "7.6.0",
    "@babel/plugin-proposal-class-properties": "^7.5.5",
    "@babel/plugin-proposal-do-expressions": "7.6.0",
    "@babel/plugin-syntax-flow": "7.2.0",
    "@babel/plugin-transform-regenerator": "7.4.5",
    "@babel/preset-env": "^7.6.0",
    "@babel/preset-flow": "7.0.0",
    "@babel/preset-react": "7.0.0",
    "@babel/preset-stage-2": "7.0.0",
    "css-loader": "^0.28.11",
    "emotion": "^10.0.14",
    "html-webpack-plugin": "^3.2.0",
    "jest": "22.1.4",
    "nodemon": "^1.14.11",
    "react-test-renderer": "16.2.0",
    "regenerator-runtime": "^0.13.3"
  }
}

和我的.babelrc

{
    "env": {
      "development": {
        "presets": [
          [ "@babel/preset-env", {
            "targets": {
              "browsers": [ "last 2 versions", "ie >= 11" ]
            }
          } ],
          "@babel/preset-react",
          "@babel/preset-flow"
        ],
        "plugins": [
          ["emotion"],
          "@babel/plugin-transform-runtime",
          "@babel/plugin-proposal-do-expressions",
          "@babel/plugin-syntax-flow",
          "@babel/plugin-proposal-class-properties",
        ],
        "comments": true
      },
      "test": {
        "sourceMaps": false,
        "presets": [
          [ "@babel/preset-env", {
            "targets": {
              "browsers": [ "last 2 versions", "ie >= 11" ]
            }
          } ],
          "@babel/preset-react",        
          "@babel/preset-flow"
        ],
        "plugins": [
            ["emotion"],
            "@babel/plugin-transform-runtime",
            "@babel/plugin-proposal-do-expressions",
            "@babel/plugin-syntax-flow",
            "babel-plugin-dynamic-import-node",
            "@babel/plugin-proposal-class-properties",
        ],
        "comments": true
      }
    }
  }

这是我的webpack配置

var path = require('path')
var webpack = require('webpack')
var nodeExternals = require('webpack-node-externals')

var browserConfig = {
  entry: './src/browser/index.js',
  output: {
    path: path.resolve(__dirname, 'public'),
    filename: 'bundle.js',
    publicPath: '/'
  },
  node: {
    fs: 'empty'
  },
  module: {
    rules: [
      { test: /\.(js)$/, use: 'babel-loader' },
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      __isBrowser__: "true"
    })
  ],
  externals: [
    'child_process'
  ]
}

var serverConfig = {
  entry: './src/server/index.js',
  target: 'node',
  externals: [nodeExternals()],
  output: {
    path: __dirname,
    filename: 'server.js',
    publicPath: '/'
  },
  node: {
    fs: 'empty'
  },
  module: {
    rules: [
      { test: /\.(js)$/, use: 'babel-loader' }
    ]
  },
  plugins: [
    new webpack.EnvironmentPlugin({ NODE_ENV: 'development' }),
    new webpack.DefinePlugin({
      __isBrowser__: "false"
    })
  ],
  externals: [
    'child_process'
  ],
}

module.exports = [browserConfig, serverConfig]

和我的server / index.js

import express from "express"
import { renderToString } from "react-dom/server"
import App from '../browser/App'
import React from 'react'
import { StaticRouter } from "react-router-dom"
import "isomorphic-fetch" // gives the ability to use fetch in server-loaded react code
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var env = process.env.NODE_ENV || 'development';
if (env === 'test' || env == 'development') {
  require('./config/config');
}
require('./routes/api/cors');
var books = require('./routes/api/book');
var blogposts = require('./routes/api/post');
var projects = require('./routes/api/project');
var users = require('./routes/api/user');
var external = require('./routes/api/external');

const app = express()

app.use(logger('dev'));
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({ extended: false, limit: '50mb' }));
app.use(cookieParser());
app.use('/api/users', users);
app.use('/api/books', books);
app.use('/api/projects', projects);
app.use('/api/blogposts', blogposts);
app.use('/api/external', external);

app.use(express.static("public"))
app.get("*", (req, res, next) => {
    const markup = renderToString(
      <StaticRouter location={req.url} context={{}}>
        <App />
      </StaticRouter>
    )

    res.send(`
      <!DOCTYPE html>
      <html>
        <head>
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
          <meta name="theme-color" content="#000000">
          <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Open+Sans|Medula+One">
          <title>Website</title>
            <script src="/bundle.js" defer></script>
          <style>
            body {
              margin: 0;
              padding: 0;
              font-family: sans-serif;
            }
            </style>
        </head>

        <body>
          <div id="app">
            ${markup}</div>
        </body>
      </html>
    `
  )
});

app.listen(3000, () => {
  console.log(`Server is listening on port: 3000`)
})

有什么主意我做错了吗?谢谢!

2 个答案:

答案 0 :(得分:1)

var express = require('express');
var path = require('path');
var serveStatic = require('serve-static');
const history = require('connect-history-api-fallback');

app = express();

const staticFileMiddleware = express.static(path.join(__dirname + '/build/'));

app.use(staticFileMiddleware);
app.use(history({
  disableDotRule: true,
  verbose: true
}));
app.use(staticFileMiddleware);

var port = process.env.PORT || 5000;
app.listen(port);

console.log('server started '+ port);

用此代码替换您的服务器端代码,安装这4个软件包

npm i express -s
npm i path -s
npm i serve-static -s
npm i connect-history-api-fallback -s

您的React App现在将在Express服务器localhost上运行。 另外,请查看此React Starter Kit,我使之很容易在Github

上在快速服务器上制作和部署应用

答案 1 :(得分:0)

Heroku回到我身边,并指出我在.babelrc中缺少生产配置。他们很棒。