Node.js 在Heroku上使用typescript和react应用程序托管express时出现问题

Node.js 在Heroku上使用typescript和react应用程序托管express时出现问题,node.js,reactjs,express,heroku,webpack,Node.js,Reactjs,Express,Heroku,Webpack,当托管我的应用程序时,我遇到以下错误 2018-07-03T23:32:25.175363+00:00 heroku[web.1]: Starting process with command `npm start` 2018-07-03T23:32:28.093779+00:00 heroku[web.1]: State changed from starting to crashed 2018-07-03T23:32:27.719911+00:00 app[web.1]: 2018-07-

当托管我的应用程序时,我遇到以下错误

2018-07-03T23:32:25.175363+00:00 heroku[web.1]: Starting process with command `npm start`
2018-07-03T23:32:28.093779+00:00 heroku[web.1]: State changed from starting to crashed
2018-07-03T23:32:27.719911+00:00 app[web.1]: 
2018-07-03T23:32:27.719929+00:00 app[web.1]: > doombot@1.0.0 start /app
2018-07-03T23:32:27.719931+00:00 app[web.1]: > node src/server/dist/server.js
2018-07-03T23:32:27.719932+00:00 app[web.1]: 
2018-07-03T23:32:27.942441+00:00 app[web.1]: module.js:545
2018-07-03T23:32:27.942444+00:00 app[web.1]:     throw err;
2018-07-03T23:32:27.942446+00:00 app[web.1]:     ^
2018-07-03T23:32:27.942447+00:00 app[web.1]: 
2018-07-03T23:32:27.942449+00:00 app[web.1]: Error: Cannot find module '/app/src/server/dist/server.js'
2018-07-03T23:32:27.942451+00:00 app[web.1]:     at Function.Module._resolveFilename (module.js:543:15)
2018-07-03T23:32:27.942453+00:00 app[web.1]:     at Function.Module._load (module.js:470:25)
2018-07-03T23:32:27.942454+00:00 app[web.1]:     at Function.Module.runMain (module.js:690:10)
2018-07-03T23:32:27.942456+00:00 app[web.1]:     at startup (bootstrap_node.js:194:16)
2018-07-03T23:32:27.942457+00:00 app[web.1]:     at bootstrap_node.js:666:3
2018-07-03T23:32:27.960851+00:00 app[web.1]: npm ERR! code ELIFECYCLE
2018-07-03T23:32:27.961370+00:00 app[web.1]: npm ERR! errno 1
2018-07-03T23:32:27.965212+00:00 app[web.1]: npm ERR! doombot@1.0.0 start: `node src/server/dist/server.js`
2018-07-03T23:32:27.966189+00:00 app[web.1]: npm ERR! Exit status 1
2018-07-03T23:32:27.967067+00:00 app[web.1]: npm ERR! 
2018-07-03T23:32:27.967873+00:00 app[web.1]: npm ERR! Failed at the doombot@1.0.0 start script.
2018-07-03T23:32:27.968281+00:00 app[web.1]: npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
2018-07-03T23:32:28.070076+00:00 heroku[web.1]: Process exited with status 1
2018-07-03T23:32:28.010680+00:00 app[web.1]: 
2018-07-03T23:32:28.010886+00:00 app[web.1]: npm ERR! A complete log of this run can be found in:
2018-07-03T23:32:28.011019+00:00 app[web.1]: npm ERR!     /app/.npm/_logs/2018-07-03T23_32_27_989Z-debug.log
这是我的package.json文件

{
  "name": "doombot",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "tsc": "tsc",
    "start": "node src/server/dist/server.js",
    "heroku-postbuild": "webpack --config webpack.prod.js; tsc -p ./tsconfig.json",
    "server": "nodemon src/server/lib/server.ts",
    "client": "webpack-dev-server --open --config webpack.dev.js",
    "dev": "concurrently \"npm run server\" \"npm run client\""
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "engines": {
    "npm": "6.0.0",
    "node": "9.9.0"
  },
  "dependencies": {
    "@types/express": "^4.11.1",
    "antd": "^3.6.4",
    "app-root-path": "^2.1.0",
    "axios": "^0.18.0",
    "body-parser": "^1.18.3",
    "cors": "^2.8.4",
    "express": "^4.16.3",
    "prop-types": "^15.6.2",
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "typescript": "2.9.1"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-plugin-import": "^1.8.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "clean-webpack-plugin": "^0.1.19",
    "concurrently": "^3.5.1",
    "css-loader": "^0.28.11",
    "eslint": "^4.19.1",
    "eslint-config-airbnb": "^16.1.0",
    "eslint-plugin-import": "^2.11.0",
    "eslint-plugin-jsx-a11y": "^6.0.3",
    "eslint-plugin-react": "^7.7.0",
    "html-webpack-plugin": "^3.2.0",
    "nodemon": "^1.17.3",
    "style-loader": "^0.20.3",
    "uglifyjs-webpack-plugin": "^1.2.7",
    "webpack": "^4.5.0",
    "webpack-cli": "^2.0.14",
    "webpack-dev-server": "^3.1.3",
    "webpack-merge": "^4.1.3"
  }
}
{
  "compilerOptions": {
    "module": "commonjs",
    "moduleResolution": "node",
    "pretty": true,
    "sourceMap": true,
    "target": "es6",
    "outDir": "./src/server/dist", // creates the dist directory & places compiles files here
    "baseUrl": "./src/server/lib"
  },
  "include": [
    "./src/server/lib/**/*.ts" // specifies that we should include all ts files within lib
  ],
  "exclude": ["node_modules"]
}
webpack.common.js

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/client/index.js',
  plugins: [new CleanWebpackPlugin(['build']), new HtmlWebpackPlugin()],
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'build')
  }
};
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    contentBase: './build',
    port: 3000,
    open: true,
    proxy: {
      '/api': 'http://localhost:4040'
    }
  }
});
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const path = require('path');

module.exports = merge(common, {
  mode: 'production',
  devtool: 'source-map',
  plugins: [
    new UglifyJSPlugin({
      sourceMap: true
    }),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production')
    })
  ]
});
webpack.dev.js

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/client/index.js',
  plugins: [new CleanWebpackPlugin(['build']), new HtmlWebpackPlugin()],
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'build')
  }
};
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    contentBase: './build',
    port: 3000,
    open: true,
    proxy: {
      '/api': 'http://localhost:4040'
    }
  }
});
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const path = require('path');

module.exports = merge(common, {
  mode: 'production',
  devtool: 'source-map',
  plugins: [
    new UglifyJSPlugin({
      sourceMap: true
    }),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production')
    })
  ]
});
webpack.prod.js

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/client/index.js',
  plugins: [new CleanWebpackPlugin(['build']), new HtmlWebpackPlugin()],
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'build')
  }
};
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    contentBase: './build',
    port: 3000,
    open: true,
    proxy: {
      '/api': 'http://localhost:4040'
    }
  }
});
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const path = require('path');

module.exports = merge(common, {
  mode: 'production',
  devtool: 'source-map',
  plugins: [
    new UglifyJSPlugin({
      sourceMap: true
    }),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production')
    })
  ]
});
和我的tsconfig文件

{
  "name": "doombot",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "tsc": "tsc",
    "start": "node src/server/dist/server.js",
    "heroku-postbuild": "webpack --config webpack.prod.js; tsc -p ./tsconfig.json",
    "server": "nodemon src/server/lib/server.ts",
    "client": "webpack-dev-server --open --config webpack.dev.js",
    "dev": "concurrently \"npm run server\" \"npm run client\""
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "engines": {
    "npm": "6.0.0",
    "node": "9.9.0"
  },
  "dependencies": {
    "@types/express": "^4.11.1",
    "antd": "^3.6.4",
    "app-root-path": "^2.1.0",
    "axios": "^0.18.0",
    "body-parser": "^1.18.3",
    "cors": "^2.8.4",
    "express": "^4.16.3",
    "prop-types": "^15.6.2",
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "typescript": "2.9.1"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-plugin-import": "^1.8.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "clean-webpack-plugin": "^0.1.19",
    "concurrently": "^3.5.1",
    "css-loader": "^0.28.11",
    "eslint": "^4.19.1",
    "eslint-config-airbnb": "^16.1.0",
    "eslint-plugin-import": "^2.11.0",
    "eslint-plugin-jsx-a11y": "^6.0.3",
    "eslint-plugin-react": "^7.7.0",
    "html-webpack-plugin": "^3.2.0",
    "nodemon": "^1.17.3",
    "style-loader": "^0.20.3",
    "uglifyjs-webpack-plugin": "^1.2.7",
    "webpack": "^4.5.0",
    "webpack-cli": "^2.0.14",
    "webpack-dev-server": "^3.1.3",
    "webpack-merge": "^4.1.3"
  }
}
{
  "compilerOptions": {
    "module": "commonjs",
    "moduleResolution": "node",
    "pretty": true,
    "sourceMap": true,
    "target": "es6",
    "outDir": "./src/server/dist", // creates the dist directory & places compiles files here
    "baseUrl": "./src/server/lib"
  },
  "include": [
    "./src/server/lib/**/*.ts" // specifies that we should include all ts files within lib
  ],
  "exclude": ["node_modules"]
}
如果我理解正确的话,这不是因为它没有正确构建而出现的。我的问题是如何以正确的方式构建和运行我的应用程序


如果您想查看我的全部代码,可以在这里找到-

您缺少很多步骤。让我们回溯一下

  • 你告诉Heroku要启动你的应用程序,它应该运行
    节点src/server/dist/server.js
    (因为你在
    包.json
    中指定它为
    启动
    脚本)。但是,Heroku上不存在
    server.js
    ,只有
    server.ts
    (即TypeScript文件)
  • 因此,您必须告诉Heroku将您的TypeScript文件转换为Javascript-现在,您只告诉它构建您的客户端(即通过
    Heroku postbuild
    脚本中的
    webpack
    )。要解决此问题,可以将该脚本更改为
    “webpack--mode production;tsc--project=tsconfig.json”,
  • 但是,这也不行,因为Heroku上没有安装TypeScript编译器。因此,请确保将
    typescript
    添加到依赖项中(请注意,IIRC、Heroku不安装
    devDependencies
    ,因此请将其设置为常规依赖项或
  • 即使您的服务器运行正常,它也只为您的API服务。如果您还希望您的客户端可以访问,您必须让Express为其服务。您可以这样做:


我认为,这应该能起到作用,但显然更多的可能是错误的。巧合的是,我正在开发一个具有非常类似设置的应用程序,而且它是开源的——因此,如果你需要灵感,请随意选择。

你错过了很多步骤。让我们回溯一下

  • 你告诉Heroku要启动你的应用程序,它应该运行
    节点src/server/dist/server.js
    (因为你在
    包.json
    中指定它为
    启动
    脚本)。但是,
    服务器.js
    在Heroku上不存在,只有
    服务器.ts
    (即TypeScript文件)
  • 因此,您必须告诉Heroku将您的TypeScript文件转换为Javascript-现在,您只需要告诉它构建您的客户端(即通过
    Heroku postbuild
    脚本中的
    webpack
    ),要解决这个问题,您可以将该脚本更改为
    “webpack--mode production;tsc--project=tsconfig.json”,
  • 但是,这也不起作用,因为Heroku上没有安装TypeScript编译器。因此,请确保将
    TypeScript
    添加到依赖项中(注意IIRC,Heroku不安装
    devDependencies
    ,因此请将其设为常规依赖项或
  • 即使您的服务器运行正常,它也只为您的API服务。如果您还希望您的客户端可以访问,您必须让Express为其服务。您可以这样做:


我认为,这应该能起到作用,但显然更多的可能是错误的。巧合的是,我正在开发一个具有非常类似设置的应用程序,而且它是开源的,所以如果你需要灵感,请随意使用。

非常感谢你。这让我达到了可以成功构建的程度,但正如你提到的,现在我遇到了以下问题:e React没有出现。到目前为止,我已经尝试了很多方法,但没有成功。我在server.ts文件
app.use(express.static(path.join(approt+/build'),{index:false}));app.get('*',function(request,response){response.sendFile(approt+/build/index.html');});app.listen(port,function(){console.log('Express server侦听端口'+端口);})
当我输出路径时,我得到了正确的路径。我也对网页进行了一些更改,并编辑了我的原始帖子以反映这一点。再次感谢您的帮助!非常感谢。这使我能够成功构建,但正如您所提到的,我遇到了React不是sh的问题到目前为止,我已经尝试了很多方法,但是没有成功。我在我的server.ts文件
app.use(express.static(path.join(approt+'/build'),{index:false}));app.get('*',function(request,response){response.sendFile(approt+'/build/index.html');});app.listen(port,function(){console.log('Express server Listing on port'+port);});
当我输出路径时,我得到了正确的路径。我也对网页包做了一些更改,并编辑了我的原始帖子以反映这一点。再次感谢您的帮助!