简体   繁体   English

如何将带有 Node 后端的 Svelte 前端部署到 Heroku?

[英]How to deploy Svelte frontend with Node backend to Heroku?

I've created a small test app in svelte and want to push it live to Heroku.我在 svelte 中创建了一个小型测试应用程序,并希望将其实时推送到 Heroku。 I haven't been able to figure out how to serve it up so that Heroku.我一直无法弄清楚如何为 Heroku 提供服务。 I'm new to testing and trying these things on my own.我是自己测试和尝试这些东西的新手。 I've tried configuring the package.json but have been unsuccessful.我试过配置 package.json 但没有成功。

When I deploy to Heroku it deploys successfully but shows up this in console.当我部署到 Heroku 时,它部署成功,但在控制台中显示了这一点。

Github repo here Github 仓库在这里

这是错误

Package.json包.json

{
  "name": "svelte-app",
  "version": "1.0.0",
  "main": "app.js",
  "scripts": {
    "build": "node app.js && npm run build:css && rollup -c",
    "build:css": "cd public && touch global.css && cd ../ && tailwind build src/style.css -o public/global.css",
    "dev": "rollup -c -w",
    "start": "sirv public"
  },
  "devDependencies": {
    "@rollup/plugin-commonjs": "^14.0.0",
    "@rollup/plugin-node-resolve": "^8.0.0",
    "rollup": "^2.3.4",
    "rollup-plugin-livereload": "^2.0.0",
    "rollup-plugin-svelte": "^6.0.0",
    "rollup-plugin-terser": "^7.0.0",
    "svelte": "^3.0.0"
  },
  "dependencies": {
    "axios": "^0.20.0",
    "bcryptjs": "^2.4.3",
    "body-parser": "^1.19.0",
    "cookie-parser": "^1.4.5",
    "cookie-session": "^1.4.0",
    "cors": "^2.8.5",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "express-session": "^1.17.1",
    "mongoose": "^5.10.5",
    "passport": "^0.4.1",
    "passport-local": "^1.0.0",
    "sirv-cli": "^1.0.0",
    "tailwindcss": "^1.8.10"
  }
}

app.js应用程序.js

const dotenv = require("dotenv");
dotenv.config();
const mongoose = require("mongoose");
const express = require("express");
const cors = require("cors");
const passport = require("passport");
const cookieParser = require("cookie-parser");
const bcrypt = require("bcryptjs");
const session = require("express-session");
const bodyParser = require("body-parser");
const app = express();
const path = require("path");
const { URI } = process.env;
const User = require("./user");

//middleware
app.use(bodyParser.json());
app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(
  cors({
    origin: "http://localhost:5000", // <-- location of the react app were connecting to
    credentials: true,
  })
);
app.use(
  session({
    secret: "secretcode", // <-- here we are defining the cookie name to be stored in the users browser
    resave: true,
    saveUninitialized: true,
  })
);
app.use(cookieParser("secretcode"));
app.use(passport.initialize());
app.use(passport.session());
require("./passportConfig")(passport); // defining passport and passing in the passport library

//db
mongoose.connect(URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  useFindAndModify: false,
});
mongoose.connection.on("connected", () => {
  console.log("Mongoose Database is Connected");
});

app.post("/login", (req, res, next) => {
  //check to see if user exists
  passport.authenticate("local", (err, user, info) => {
    console.log(user);
    if (err) throw err;
    if (!user) res.json({ message: "User does not exist" });
    else {
      req.logIn(user, (err) => {
        if (err) throw err;
        res.json({ message: "User exists" });
      });
    }
  })(req, res, next);
});
app.post("/create", async (req, res) => {
  //check to see if user exists
  const { username, password } = req.body;

  try {
    const data = await User.findOne({ username });
    if (!data) {
      const hashedPassword = await bcrypt.hash(password, 10);

      const newUser = new User({
        username,
        password: hashedPassword,
      });
      await newUser.save();
      res.json({ message: "Client created" });
    } else {
      res.json({ message: "Client already exists" });
    }
  } catch (err) {
    res.json({ message: err });
  }
});
app.get("/user", (req, res) => {
  console.log("getting user...");
  res.json({ message: req.user }); // The req.user stores the entire user that has been authenticated inside of it.
});
app.get("/logout", (req, res, next) => {
  req.logOut();
  res.json({ message: "User logged out" });
});
app.use(express.static("public"));
app.get("*", (req, res) => {
  res.sendFile(path.resolve(__dirname, "public", "index.html"));
});
app.listen(5001, () => {
  console.log("App's running on port 5001");
});

We were also facing the same problem a few weeks ago:几周前我们也面临同样的问题:

I used express-csp-header package to add headers (Not a very optimal solution but worked after 6-7hrs of crying on why I chose svelete)我使用 express-csp-header 包添加标题(不是一个非常理想的解决方案,但在为我选择 svelete 的原因哭了 6-7 小时后工作)

   this.app.use(
      expressCspHeader({
        directives: {
          "default-src": [SELF, INLINE],
          "script-src": [
            SELF,
            INLINE,
            "*",
          ],
          "style-src": [
            SELF,
            INLINE,
            "*",
          ],
          "img-src": ["data:", "*", SELF, INLINE],
          "worker-src": [NONE],
          "frame-src": ["*"],
          "font-src": ["*"],
          "connect-src": ["*"],
          "block-all-mixed-content": false,
        },
      })
    );
  }

Link to express csp header: https://www.npmjs.com/package/express-csp-header链接表达 csp 头: https : //www.npmjs.com/package/express-csp-header

And then,进而,

app.use(express.static("public"));
app.get("*", (req, res) => {
  res.sendFile(path.resolve(__dirname, "public", "index.html"));
});

Just route to svelete by serving it from nodeJs只需通过从 nodeJs 提供服务来路由到 svelete

This should fix your problem.这应该可以解决您的问题。

app.use('/build', express.static('public/build'))

The problem is that your svelte app is located in public folder but you are serving index.html on "/" and it express doesn't know what to do when it receives a request on /build/.问题是您的 svelte 应用程序位于公共文件夹中,但您在“/”上提供 index.html 并且它表示在收到 /build/ 上的请求时不知道该怎么做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM