首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >应用程序没有显示前端

应用程序没有显示前端
EN

Stack Overflow用户
提问于 2018-02-09 20:34:33
回答 2查看 4.2K关注 0票数 8

问题摘要

最近,我尝试将本地应用程序部署到Heroku。它是由一个酒瓶后端和一个React/Redux前端构建的。在研究了Heroku的复杂性之后(procfiles,其中读取package.json等)我能够让后端显示(例如:烧瓶-管理部分和我的数据库一样工作),但我仍然无法到达我的网站的前端(反应)部分。在Heroku日志中没有发现错误,在本地版本上,当我启动python服务器并在静态目录中执行NPM start时,我的应用程序工作得非常好。

知道为什么前端不会显示或者如何访问它吗?

日志:

我已经从细节中删除了一些敏感信息,但是当我尝试刷新应用程序时,下面是heroku logs --tail给我的信息。

代码语言:javascript
复制
2018-02-11T01:18:01.000000+00:00 app[api]: Build succeeded
2018-02-11T01:21:12.305017+00:00 heroku[web.1]: Starting process with command `gunicorn main:app`
2018-02-11T01:21:16.374150+00:00 heroku[web.1]: State changed from starting to up
2018-02-11T01:21:15.948707+00:00 app[web.1]: [2018-02-11 01:21:15 +0000] [4] [INFO] Starting gunicorn 19.6.0
2018-02-11T01:21:15.949430+00:00 app[web.1]: [2018-02-11 01:21:15 +0000] [4] [INFO] Listening at: http://0.0.0.0:29162



2018-02-11T01:21:19.278810+00:00 heroku[router]: at=info method=GET path="/" host=removed.herokuapp.com request_id=bd74ea4c-3e3a-403b-8850-198b7dec20e2 fwd="104.152.1.62" dyno=web.1 connect=1ms service=2146ms status=200 bytes=2895 protocol=https
2018-02-11T01:21:19.650759+00:00 heroku[router]: at=info method=GET path="/dist/bundle.css" host=removed.herokuapp.com request_id=48183249-fb12-4c7a-9a53-2a57ab58d89b fwd="104.152.1.62" dyno=web.1 connect=0ms service=3ms status=200 bytes=2895 protocol=https
2018-02-11T01:21:19.816113+00:00 heroku[router]: at=info method=GET path="/dist/bundle.js" host=removed.herokuapp.com request_id=1c8b258b-4187-4df6-af35-784e62fb97e5 fwd="104.152.1.62" dyno=web.1 connect=1ms service=3ms status=200 bytes=2895 protocol=https

当我查看源代码时,我看到了来自我的index.html文件的代码(在静态文件夹中,这是正确的),这一行被高亮显示为红色,这让我觉得它缺少了bundle.js?<script src="/dist/bundle.js"></script>

当我试图访问前端的时候,它们都没有显示出来。我真的不知道下一步该去哪儿找。

初步设想:

  1. 我的server.js文件实际上是从Heroku开始的吗?我的package.json中有一个“启动”脚本,但是如果procfile正在执行Python...does,那么它实际上启动了吗?我如何使它开始,而不把它放在一个后安装或后构建步骤?
  2. 是webpack搞砸了什么。我的作品webpack与我的发展略有不同,所以也许在制作过程中:生产过程会变得一团糟?然而,这并不能解释为什么构建总是成功的。
  3. 我的server.js或webpack是在index.html文件上强制格式化,所以它不能正确解析吗?也许这就是我在控制台上看到SyntaxError: expected expression, got '< bundle.js:1的原因?

更新:我收到Heroku支持小组的通知,告诉我Heroku不是为支持像我这样的多进程应用程序而构建的。因此,他们觉得我需要做一些重要的更改,让所有HTTP请求通过一个dyno转发。也许这就是我的问题?

以下是可能有助于调试的文件:

Server.js

代码语言:javascript
复制
const http = require('http');
const express = require('express');
const httpProxy = require('http-proxy');
const path = require('path');
const apiPort = process.env.PORT || 8081;

const proxy = httpProxy.createProxyServer({});

const app = express();

app.use(require('morgan')('short'));

(function initWebpack() {
    const webpack = require('webpack');
    const webpackConfig = require('./webpack/common.config');

    const compiler = webpack(webpackConfig);

    app.use(require('webpack-dev-middleware')(compiler, {
        noInfo: true, publicPath: webpackConfig.output.publicPath,
    }));

    app.use(require('webpack-hot-middleware')(compiler, {
        log: console.log, path: '/__webpack_hmr', heartbeat: 10 * 1000,
    }));

    app.use(express.static(path.join(__dirname, '/')));
}());


 app.all(/^\/api\/(.*)/, (req, res) => {
    proxy.web(req, res, { target: `http://0.0.0.0:${apiPort}` });
});

app.get(/.*/, (req, res) => {
    res.sendFile(path.join(__dirname, '/index.html'));
});


const server = http.createServer(app);
server.listen(process.env.PORT || 8080, () => {
    const address = server.address();
    console.log('Listening on: %j', address);
    console.log(' -> that probably means: http://0.0.0.0:%d', address.port);
});

文件结构

代码语言:javascript
复制
ROOT
├──/application
│   ├── models.py
│   ├── app.py
├──/static
│   ├──/bin
│   ├──/dist
│   │   ├──bundle.js
│   ├──/node_modules
│   ├──/src
│   │   ├──/actions
│   │   ├──/components
│   │   │   ├──/examplecomponenthere
│   │   │   │   ├──index.js (for example component)
│   │   ├──/constants
│   │   ├──/containers
│   │   ├──/reducers
│   │   ├──/store
│   │   ├──/webpack
│   ├──index.html
│   ├──package.json (the true one)
│   ├──server.js
├──/tests
├──config.py
├──index.py
├──main.py
├──package.json (one to help heroku start)
├──procfile
├──requirements.txt.
├──setup.py
├──tests.py

Package.json in root这个文件的存在是因为我正在运行多个构建。Heroku似乎不认识静态的package.json,直到我用它把它推到那里。

代码语言:javascript
复制
    { 
"name": "rmmd", 
"version": "0.0.1", 
"engines": { 
"node": "6.11.1", 
"npm": "3.10.10" 
}, 
"scripts": { 
"start": "node static/bin/server.js", 
"heroku-postbuild": "cd static && npm install && npm run build:production"
 } 
}

静态Package.json中的

代码语言:javascript
复制
{
  "name": "redux-easy-boilerplate",
  "version": "1.3.3",
  "description": "",
  "scripts": {
    "clean": "rimraf dist",
    "build": "webpack --progress --verbose --colors --display-error-details --config webpack/common.config.js",
    "build:production": "npm run clean && npm run build",
    "lint": "eslint src",
    "start": "node bin/server.js",
    "test": "karma start"
  },
  "repository": {
    "type": "git",
    "url": ""
  },
  "keywords": [
    "react",
    "reactjs",
    "boilerplate",
    "redux",
    "hot",
    "reload",
    "hmr",
    "live",
    "edit",
    "webpack"
  ],
  "author": "https://github.com/anorudes, https://github.com/keske",
  "license": "MIT",
  "devDependencies": {
    "webpack-dev-middleware": "^1.5.0",
    "webpack-dev-server": "^1.14.1",
    "webpack-hot-middleware": "^2.6.0",
  },
  "dependencies": {
    "ant-design-pro": "^0.3.1",
    "antd": "^3.0.0",
    "lodash": "^4.17.4",
    "prop-types": "^15.6.0",
    "react-bootstrap": "^0.31.0",
    "redux-devtools-extension": "^2.13.2",
"autoprefixer": "6.5.3",
    "axios": "^0.15.3",
    "babel-core": "^6.4.5",
    "babel-eslint": "^7.1.1",
    "babel-loader": "^6.2.1",
    "babel-plugin-import": "^1.2.1",
    "babel-plugin-react-transform": "^2.0.0",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-polyfill": "^6.3.14",
    "babel-preset-es2015": "^6.3.13",
    "babel-preset-react": "^6.3.13",
    "babel-preset-react-hmre": "^1.0.1",
    "babel-preset-stage-0": "^6.3.13",
    "bootstrap": "^3.3.5",
    "bootstrap-loader": "^1.2.0-beta.1",
    "bootstrap-sass": "^3.3.6",
    "bootstrap-webpack": "0.0.5",
    "classnames": "^2.2.3",
    "css-loader": "^0.26.4",
    "csswring": "^5.1.0",
    "deep-equal": "^1.0.1",
    "eslint": "^3.4.0",
    "eslint-config-airbnb": "13.0.0",
    "eslint-plugin-import": "^2.2.0",
    "eslint-plugin-jsx-a11y": "^3.0.1",
    "eslint-plugin-react": "^6.1.2",
    "expect": "^1.13.4",
    "exports-loader": "^0.6.2",
    "expose-loader": "^0.7.1",
    "express": "^4.13.4",
    "express-open-in-editor": "^1.1.0",
    "extract-text-webpack-plugin": "^1.0.1",
    "file-loader": "^0.9.0",
    "gapi": "0.0.3",
    "history": "^4.4.1",
    "http-proxy": "^1.12.0",
    "imports-loader": "^0.6.5",
    "jasmine-core": "^2.4.1",
    "jquery": "^3.1.0",
    "jwt-decode": "^2.1.0",
    "karma": "^1.2.0",
    "karma-chrome-launcher": "^2.0.0",
    "karma-mocha": "^1.1.1",
    "karma-webpack": "^1.7.0",
    "less": "^2.7.2",
    "less-loader": "^2.2.3",
    "lodash": "^4.5.1",
    "material-ui": "^0.16.4",
    "mocha": "^3.0.2",
    "morgan": "^1.6.1",
    "node-sass": "^3.4.2",
    "postcss-import": "^9.0.0",
    "postcss-loader": "^1.1.1",
    "q": "^1.4.1",
    "qs": "^6.1.0",
    "rc-datepicker": "^4.0.1",
    "react": "^15.3.1",
    "react-addons-css-transition-group": "^15.3.1",
    "react-bootstrap": "^0.31.0",
    "react-calendar-component": "^1.0.0",
    "react-date-picker": "^5.3.28",
    "react-datepicker": "^0.37.0",
    "react-document-meta": "^2.0.0-rc2",
    "react-dom": "^15.1.0",
    "react-forms": "^2.0.0-beta33",
    "react-hot-loader": "^1.3.0",
    "react-loading-order-with-animation": "^1.0.0",
    "react-onclickoutside": "^5.3.3",
    "react-redux": "^4.3.0",
    "react-router": "3.0.0",
    "react-router-redux": "^4.0.0",
    "react-tap-event-plugin": "^2.0.1",
    "react-transform-hmr": "^1.0.1",
    "redux": "^3.2.1",
    "redux-form": "^6.0.1",
    "redux-logger": "2.7.4",
    "redux-thunk": "^2.1.0",
    "resolve-url-loader": "^1.4.3",
    "rimraf": "^2.5.0",
    "sass-loader": "^4.0.0",
    "style-loader": "^0.13.0",
    "url-loader": "^0.5.7",
    "webpack": "^1.12.11",
    "webpack-merge": "^1.0.2",
    "yargs": "^6.5.0"
  }
}

Webpack戳

代码语言:javascript
复制
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  devtool: 'source-map',

  entry: ['bootstrap-loader/extractStyles', './src/index'],
  output: {
    publicPath: '/dist/',
  },

  module: {
    loaders: [
      {
        test: /\.scss$/,
        loader: 'style!css!postcss-loader!sass',
      },
    ],
  },

  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"',
      },
      __DEVELOPMENT__: false,
    }),
    new ExtractTextPlugin('bundle.css'),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
      },
    }),
  ],
};

Webpack普通

代码语言:javascript
复制
const path = require('path');
const autoprefixer = require('autoprefixer');
const postcssImport = require('postcss-import');
const merge = require('webpack-merge');

const development = require('./dev.config');
const production = require('./prod.config');

require('babel-polyfill').default;

const TARGET = process.env.npm_lifecycle_event;

const PATHS = {
    app: path.join(__dirname, '../src'),
    build: path.join(__dirname, '../dist'),
};

process.env.BABEL_ENV = TARGET;

const common = {
    entry: [
        PATHS.app,
    ],

    output: {
        path: PATHS.build,
        filename: 'bundle.js',
    },

    resolve: {
        extensions: ['', '.jsx', '.js', '.json', '.scss'],
        modulesDirectories: ['node_modules', PATHS.app],
    },

    module: {
        loaders: [{
            test: /bootstrap-sass\/assets\/javascripts\//,
            loader: 'imports?jQuery=jquery',
        }, {
            test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
            loader: 'url?limit=10000&mimetype=application/font-woff',
        }, {
            test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
            loader: 'url?limit=10000&mimetype=application/font-woff2',
        }, {
            test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
            loader: 'url?limit=10000&mimetype=application/octet-stream',
        }, {
            test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
            loader: 'url?limit=10000&mimetype=application/font-otf',
        }, {
            test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
            loader: 'file',
        }, {
            test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
            loader: 'url?limit=10000&mimetype=image/svg+xml',
        }, {
            test: /\.js$/,
            loaders: ['babel-loader'],
            exclude: /node_modules/,
        }, {
            test: /\.css$/,
            include: /node_modules/,
            loaders: ['style-loader', 'css-loader'],
        }, {
            test: /\.png$/,
            loader: 'file?name=[name].[ext]',
        }, {
            test: /\.jpg$/,
            loader: 'file?name=[name].[ext]',
        }],
    },

    postcss: (webpack) => (
        [
            autoprefixer({
                browsers: ['last 2 versions'],
            })
        ]
    ),
};

if (TARGET === 'start' || !TARGET) {
    module.exports = merge(development, common);
}

if (TARGET === 'build' || !TARGET) {
    module.exports = merge(production, common);
}

ProcFile

web: gunicorn main:app

Heroku中的构建包

代码语言:javascript
复制
heroku buildpacks:set heroku/python
heroku buildpacks:add heroku/nodejs
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-02-17 02:04:25

所以!原来Heroku支持小组在分析我的应用程序时是不正确的。我的应用程序是以两种不同的方式构建的(一种用于生产,另一种用于开发)。在本地使用static/package.json (参见npm run start )使用热重加载,并通过server.js从更快的本地更改中获益。但是,在生产环境中,您希望使用压缩的static/package.json.文件,因此我的目标是使用npm run build:production (参见

我遇到的问题是控制台中的SyntaxError: expected expression, got '< bundle.js:1,在我看来,bundle.js根本没有加载。我在上面列出了一系列有效的问题,说明了为什么我认为会发生这种情况,但他们都认为主要的问题是无法在我的烧瓶应用程序的同时运行我的反应性应用程序。

我完全错了。我根本不需要运行server.js。index.html和烧瓶/python无法在生产中找到我的bundle.js并加载前端的真正原因是我从未想过要发布的烧瓶中的config.py文件中的一个错误。

烧瓶有一个非常特殊的配置,允许定义static_foldertemplate_folder。不久前,我在处理一些图像上传功能时,把我的static_folder换成了另一个目录。我没有捕捉到它的原因是因为在本地运行server.js是为了热重新加载,所以我从未看到压缩的bundle.js文件出错。

在纠正了这个错误之后,我推到heroku,amazingly...it开始了第一次尝试!

下面是修复它的正确代码:

代码语言:javascript
复制
app = Flask(__name__, static_folder="./static/dist", template_folder="./static")

最后,在Heroku上运行一个烧瓶/反应应用程序:

  • 使用多个构建包(一个用于节点,一个用于python)。
  • 使用procfile只加载烧瓶一侧。
  • 如果像我这样的静态文件夹中有另一个文件,则需要根directory...even中的一个directory...even文件。
  • 使用webpack压缩您的反应代码,并以压缩的方式服务它。
  • 使用render_template与烧瓶一起呈现包含root div的index.html文件以供反应。
  • 确保所有用于React的依赖项都列在实际的“依赖项”中,而不是“Heroku”中,否则Heroku将忽略它们。

我真希望这能帮上忙!我用头撞墙了两个星期,结果发现这是个小问题.不是总是这样吗?

附加资源:https://codeburst.io/creating-a-full-stack-web-application-with-python-npm-webpack-and-react-8925800503d9,虽然这非常简单.这是我找到我的bug的原因,所以我会在这里发布它。

票数 9
EN

Stack Overflow用户

发布于 2018-02-09 20:41:46

您的烧瓶后端似乎也不运行在同一端口,因为您转发您的流量:

代码语言:javascript
复制
Starting gunicorn 19.6.0 Listening at: 0.0.0.0:13521 (4) 

app.all(/^\/api\/(.*)/, (req, res) => {
    proxy.web(req, res, { target: 'http://0.0.0.0:8081' });
});

烧瓶正在监听端口13521 (随机选择),但是/api/路由被转发到端口8081。相反,您可能应该配置gunicorn使用一个固定端口:http://docs.gunicorn.org/en/latest/settings.html#bind

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48713701

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档