window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster υπάρχει ήδη') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Ανάπτυξη GraphQL/MongoDB API χρησιμοποιώντας Netlify Functions - The Codest
The Codest
  • Σχετικά με εμάς
  • Υπηρεσίες
    • Ανάπτυξη λογισμικού
      • Ανάπτυξη Frontend
      • Backend Ανάπτυξη
    • Staff Augmentation
      • Frontend Developers
      • Backend Developers
      • Μηχανικοί δεδομένων
      • Μηχανικοί cloud
      • Μηχανικοί QA
      • Άλλα
    • Συμβουλευτική
      • Έλεγχος & Συμβουλευτική
  • Βιομηχανίες
    • Fintech & Τραπεζική
    • E-commerce
    • Adtech
    • Healthtech
    • Κατασκευή
    • Εφοδιαστική
    • Αυτοκίνητο
    • IOT
  • Αξία για
    • CEO
    • CTO
    • Διευθυντής παράδοσης
  • Η ομάδα μας
  • Case Studies
  • Μάθετε πώς
    • Blog
    • Συναντήσεις
    • Διαδικτυακά σεμινάρια
    • Πόροι
Καριέρα Ελάτε σε επαφή
  • Σχετικά με εμάς
  • Υπηρεσίες
    • Ανάπτυξη λογισμικού
      • Ανάπτυξη Frontend
      • Backend Ανάπτυξη
    • Staff Augmentation
      • Frontend Developers
      • Backend Developers
      • Μηχανικοί δεδομένων
      • Μηχανικοί cloud
      • Μηχανικοί QA
      • Άλλα
    • Συμβουλευτική
      • Έλεγχος & Συμβουλευτική
  • Αξία για
    • CEO
    • CTO
    • Διευθυντής παράδοσης
  • Η ομάδα μας
  • Case Studies
  • Μάθετε πώς
    • Blog
    • Συναντήσεις
    • Διαδικτυακά σεμινάρια
    • Πόροι
Καριέρα Ελάτε σε επαφή
Πίσω βέλος GO BACK
2021-05-13
Ανάπτυξη λογισμικού

Ανάπτυξη GraphQL/MongoDB API χρησιμοποιώντας Netlify Functions

The Codest

Pawel Rybczynski

Software Engineer

Στόχοι Αρχική ρύθμιση Εγκατάσταση εξαρτήσεων Ας ξεκινήσουμε Αρχικά, προσθέστε το tsconfig.json στον κύριο κατάλογο: Τώρα, ας δημιουργήσουμε το src/server.ts για τις υλοποιήσεις των διακομιστών. Στη συνέχεια, προσθέστε δύο συναρτήσεις: μία για τον τοπικό διακομιστή και μία για το lambda. Εντάξει, δεν έχουμε resolvers ή ορισμούς τύπων, οπότε πρέπει να δημιουργήσουμε κάποιους. Ας υποθέσουμε ότι, αρχικά, θέλουμε [...]

Στόχοι

  1. Διαμορφώστε τόσο τους τοπικούς όσο και τους διακομιστές lambda.
  2. Συνδέστε και τα δύο στη MongoDB.
  3. Εφαρμόστε βασικό έλεγχο ταυτότητας.
  4. Ανάπτυξη του Apollo χωρίς διακομιστή GraphQL API με την Netlify.
  5. Χρήση Typescript.

Αρχική ρύθμιση

npm init -y

Εγκατάσταση εξαρτήσεων

npm install --save typescript graphql aws-lambda @types/aws-lambda

Ας ξεκινήσουμε

Πρώτα, προσθέστε το tsconfig.json στον κύριο κατάλογο:

 {
 "compilerOptions": {
 "target": "es5",
 "module": "commonjs",
 "allowJs": true,
 "strict": true,
 "esModuleInterop": true,
 "skipLibCheck": true,
 "forceConsistentCasingInFileNames": true
 },
 "include": [ts", "src/**/*.ts", "src/**/*.js"],
 "exclude": ["node_modules"]
 }

Τώρα, ας δημιουργήσουμε src/server.ts για υλοποιήσεις διακομιστών. Στη συνέχεια, προσθέστε δύο συναρτήσεις: μία για τον τοπικό διακομιστή και μία για το lambda.

// src/server.ts
import { ApolloServer as ApolloServerLambda } from "apollo-server-lambda",
import { ApolloServer } from "apollo-server",


const createLambdaServer = () =>
  new ApolloServerLambda({
    typeDefs,
    resolvers,
    introspection: true,
    playground: true,
    },
  });

const createLocalServer = () =>
  new ApolloServer({
    typeDefs,
    resolvers,
    introspection: true,
    playground: true,
    },
  });

export { createLambdaServer, createLocalServer },

Εντάξει, δεν έχουμε resolvers ή ορισμούς τύπων, οπότε πρέπει να δημιουργήσουμε μερικούς. Ας υποθέσουμε ότι, αρχικά, θέλουμε να δημιουργήσουμε χρήστες και να λαμβάνουμε πληροφορίες για αυτούς.

// src/schemas.ts
const { gql } = require("apollo-server-lambda"),

const userSchema = gql`
  type User {
    id: ID!
    email: String!
    name: String!
  }

  type Query {
    user(id: ID!): User!
  }

  type Μετάλλαξη {
    createUser(name: String!, email: String!, password: String!): User!
  }
`;

Αν δεν είστε εξοικειωμένοι με αυτό, Ο Απόλλων ετοίμασε ένα πολύ ωραίο σεμινάριο

Τώρα ας δημιουργήσουμε έναν αναλυτή χρηστών με ένα ερώτημα και μια μετάλλαξη.

// src/resolvers.ts
const userResolver = {
  Query: {
    user: async (parent, args, context, info) => {
      {...}
    },
  },
  Μετάλλαξη: {
    createUser: async (parent, args, context, info) => {
      {...}
    },
  },
};

Αλλά δεν έχουμε δεδομένα... Ας το διορθώσουμε 😉

Μην ξεχάσετε να εισαγάγετε τον ορισμό τύπου και τον επιλύτη στον διακομιστή.

// src/server.ts
import { ApolloServer as ApolloServerLambda } from "apollo-server-lambda",
import { ApolloServer } from "apollo-server",

import { typeDefs } from "./schemas",
import { resolvers } from "./resolvers",

{...}

Σύνδεση με τη MongoDB μέσω του mongoose

Τώρα είναι η κατάλληλη στιγμή να δημιουργήσουμε μια σύνδεση με τη βάση δεδομένων μας. Στη συγκεκριμένη περίπτωση, θα είναι η MongoDB. Είναι δωρεάν και εύκολη στη συντήρηση. Αλλά πριν από αυτό, ας εγκαταστήσουμε δύο ακόμα εξαρτήσεις:

npm install --save mongoose dotenv

Το πρώτο βήμα είναι η δημιουργία ενός Μοντέλου χρήστη.

// src/model.ts
import mongoose, { Document, Error, Schema } from "mongoose",

export type User = Document & {
  _id: string,
  email: string,
  name: string,
  password: string,
};

delete mongoose.connection.models["User"],

const UserSchema: Schema = new Schema({
  email: {
    type: String,
    required: true,
    unique: true,
  },
  name: {
    type: String,
    required: true,
    minLength: 3,
    maxLength: 32,
  },
  password: {
    type: String,
    required: true,
  },
});

export const userModel = mongoose.model  ("User", UserSchema),

Κάντε τους κωδικούς πρόσβασης πιο ασφαλείς

Πρώτα η ασφάλεια! Ας ασφαλίσουμε τώρα τους κωδικούς μας με κατακερματισμό.

npm install --save bcrypt @types/bcrypt

Τώρα, υλοποιήστε την ασφάλεια του κωδικού πρόσβασης μέσα στην επανάκληση προ-μεσολάβησης. Οι συναρτήσεις pre-middleware εκτελούνται η μία μετά την άλλη, όταν κάθε middleware καλεί το επόμενο. Για να κάνουμε τους κωδικούς πρόσβασης ασφαλείς, χρησιμοποιούμε μια τεχνική που παράγει ένα salt και ένα hash σε ξεχωριστές κλήσεις συναρτήσεων.

// src/model.ts
import bcrypt from "bcrypt",
{...}
const SALT_WORK_FACTOR: number = 10,

UserSchema.pre("save", function (next) {
  const user = this as User,
  if (!this.isModified("password")) return next(),

  bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
    if (err) return next(err),

    bcrypt.hash(user.password, salt, function (err, hash) {
      if (err) return next(err),
      user.password = hash,
      next(),
    });
  });
});
{...}

Στη συνέχεια, προσθέστε τη μέθοδο comparePasswords στο UserSchema:

// src/model.ts
{...}
UserSchema.methods.comparePasswords = function (
  candidatePassword: string,
  cb: (err: Error | null, same: boolean | null) => void
) {
  const user = this as User,
  bcrypt.compare(candidatePassword, user.password, (err, isMatch) => {
    if (err) {
      return cb(err, null),
    }
    cb(null, isMatch),
  });
};
{...}

Και φυσικά, τροποποιήστε τον τύπο χρήστη.

type comparePasswordFunction = (
  candidatePassword: string,
  cb: (err: Error, isMatch: boolean) => void
) => void,

export type User = Document & {
  _id: string,
  email: string,
  name: string,
  password: string,
  comparePasswords: comparePasswordFunction,
};

Τώρα μπορούμε να οργανώσουμε μια σύνδεση μεταξύ διακομιστών και βάσεων δεδομένων. MONGODB_URI είναι μια μεταβλητή περιβάλλοντος που περιέχει μια συμβολοσειρά σύνδεσης που απαιτείται για τη δημιουργία της σύνδεσης. Μπορείτε να τη λάβετε από τον πίνακα του cluster σας αφού συνδεθείτε στο λογαριασμό σας MongoDB atlas. Βάλτε την μέσα στο .env

// .env
MONGODB_URI = ...,

Να θυμάστε πάντα να προσθέτετε αυτό το αρχείο στο .gitignore. Υπέροχα! Τώρα ας προσθέσουμε μια συνάρτηση που επιτρέπει τη σύνδεση με την db.

// src/server.ts
import mongoose, { Connection } from "mongoose",
{...}
let cachedDb: Connection,

const connectToDatabase = async () => {
  if (cachedDb) return,

  await mongoose.connect(process.env.MONGODB_URI || "", {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useFindAndModify: false,
    useCreateIndex: true,
  });
  cachedDb = mongoose.connection,
};
{...}

Το πλαίσιο είναι ένα αντικείμενο το οποίο μοιράζονται όλοι οι επιλύτες. Για να το παρέχουμε, πρέπει απλώς να προσθέσουμε μια συνάρτηση αρχικοποίησης του πλαισίου στον κατασκευαστή του ApolloServer. Ας το κάνουμε.

// src/server.ts
import { userModel } from "./models/user.model",
{...}
const createLambdaServer = async () =>
  new ApolloServerLambda({
    typeDefs,
    resolvers,
    introspection: true,
    playground: true,
    context: async () => {
      await connectToDatabase(),

      return {
        models: {
          userModel,
        },
      };
    },
  });

const createLocalServer = () =>
  new ApolloServer({
    typeDefs,
    resolvers,
    introspection: true,
    playground: true,
    context: async () => {
      await connectToDatabase(),

      return {
        models: {
          userModel,
        },
      };
    }
  });

Όπως μπορείτε να δείτε, περνάμε επίσης userModel μέσω του πλαίσιο. Μπορούμε τώρα να ενημερώσουμε το resolver:

// resolvers.ts
const userResolver = {
  Query: {
    user: async (_, { email, name, password }, { models: { userModel } }) => {
      const user = await userModel.findById({ _id: id }).exec(),
      return user,
    },
  },
  Μετάλλαξη: {
    createUser: async (_, { id }, { models: { userModel } }) => {
      const user = await userModel.create({ email, name, password }),
      return user,
    },
  },
};

Φαίνεται ωραίο! Τώρα δημιουργήστε μια βασική περίπτωση διακομιστή:

// src/index.ts
import { createLocalServer } from "./server",
require("dotenv").config(),

const port = process.env.PORT || 4000,

const server = createLocalServer(),

server.listen(port).then(({ url }) => {
  console.log(`Server ir running at ${url}`),
});

Εκκίνηση του τοπικού διακομιστή με το Nodemon

Τελευταίο πράγμα πριν την εκτέλεση, προσθέστε nodemon.json

{
  "watch": ["src"],
  "ext": ".ts,.js",
  "ignore": [],
  "exec": "ts-node --transpile-only ./src/index.ts"
}

Προσθέστε σενάριο στο package.json

"σενάρια": {
    "start": "nodemon"
  },

Και τρέξτε!

npm start

Θα πρέπει να λάβετε τέτοιες πληροφορίες μέσα στο τερματικό:

Ο διακομιστής ir τρέχει στο http://localhost:4000/

Αν ναι, ανοίξτε το http://localhost:4000/ μέσα στο πρόγραμμα περιήγησής σας.

Θα πρέπει να εμφανιστεί η παιδική χαρά GraphQL. Ας δημιουργήσουμε έναν νέο χρήστη!

createUser.png

Ρίξτε μια ματιά στο πώς φαίνεται στη βάση δεδομένων.

databaseJohnDoe.png

Ωραία! Όλα λειτουργούν μια χαρά!

Ας προσπαθήσουμε να πάρουμε μερικές πληροφορίες χρήστη.

userWithoutAuth.png

Και προσθέστε το πεδίο κωδικού πρόσβασης...

userPassword.png

Ωραία! Λαμβάνουμε σφάλμα Δεν είναι δυνατή η αναζήτηση του πεδίου "password" στον τύπο "User".". Όπως μπορείτε να ελέγξετε ξανά, δεν προσθέσαμε αυτό το πεδίο μέσα στον ορισμό του τύπου χρήστη. Βρίσκεται εκεί επίτηδες. Δεν θα πρέπει να καταστήσουμε δυνατή την αναζήτηση οποιουδήποτε κωδικού πρόσβασης ή άλλων ευαίσθητων δεδομένων.

Ένα άλλο πράγμα... Μπορούμε να πάρουμε τα δεδομένα των χρηστών χωρίς έλεγχο ταυτότητας... δεν είναι μια καλή λύση. Πρέπει να το διορθώσουμε.

Αλλά πριν...

Διαμόρφωση του Codegen

Ας χρησιμοποιήσουμε την GraphQL κωδικός γεννήτρια για να πάρει έναν συμβατό βασικό τύπο, με βάση το σχήμα μας.

npm install --save @graphql-codegen/cli @graphql-codegen/introspection
@graphql-codegen/typescript @graphql-codegen/typescript-resolvers

Δημιουργία codegen.yml

αντικατάσταση: true
schema: "http://localhost:4000"
generates:
  ./src/generated/graphql.ts:
    plugins:
      - "typescript"
      - "typescript-resolvers"
  ./graphql.schema.json:
    plugins:
      - "introspection"

Προσθέστε codegen σενάριο για να package.json

"σενάρια": {
    "start": "nodemon",
    "codegen": "graphql-codegen --config ./codegen.yml": "graphql-codegen --config ./codegen.yml",
  },

Στη συνέχεια, όταν εκτελείται ο τοπικός διακομιστής, εκτελέστε το σενάριο:

npm run codegen

Σε περίπτωση επιτυχίας θα λάβετε μήνυμα:

  √ Διαμόρφωση ανάλυσης
  √ Δημιουργία εξόδων

Εάν λάβετε αυτές τις πληροφορίες, θα πρέπει να εμφανιστούν δύο αρχεία:

  • graphql.schema.json στον κύριο κατάλογο
  • graphql.ts στη νεοδημιουργηθείσα διαδρομή src/generated

Μας ενδιαφέρει περισσότερο το δεύτερο. Αν το ανοίξετε, θα παρατηρήσετε μια ωραία δομή τύπων.

Τώρα μπορούμε να βελτιώσουμε τους επιλύτες μας:

// src/resolvers.ts
import { Resolvers, Token, User } from "./generated/graphql",

const userResolver: Resolvers = {
  Query: {
    user: async (_, { id }, { models: { userModel }, auth }): Promise => {
      const user = await userModel.findById({ _id: id }).exec(),
      return user,
    },
  },
  Μετάλλαξη: {
    createUser: async (
      _,
      { email, name, password },
      { models: { userModel } }
    ): Promise => {
      const user = await userModel.create({
        email,
        name,
        password,
      });
      return user,
    },
  },
};

Αυθεντικοποίηση

Στη συνέχεια, ας ρυθμίσουμε έναν απλό έλεγχο ταυτότητας με βάση το κουπόνι.

npm install --save jsonwebtoken @types/jsonwebtoken

Δημιουργία checkAuth συνάρτηση για να επαληθεύσει αν το κουπόνι είναι έγκυρο. Θα προσθέσουμε το αποτέλεσμα στο πλαίσιο, ώστε να μπορούμε να έχουμε πρόσβαση σε αυτό μέσα στους resolvers.

// src/server.ts
import { IncomingHttpHeaders } from "http";
import {
  APIGatewayProxyEvent,
  APIGatewayProxyEventHeaders,
  Context,
} from "aws-lambda";
import jwt from "jsonwebtoken";
{...}
const checkAuth = async ({ token } : APIGatewayProxyEventHeaders | IncomingHttpHeaders ) => {
  if (typeof token === "string") {
    try {
      return await jwt.verify(token, "riddlemethis");
    } catch (e) {
      throw new AuthenticationError(`Your session expired. Sign in again.`);
    }
  }
};
{...}
const createLambdaServer = async (
  { headers }: APIGatewayProxyEvent,
  context: Context
) => {
  return new ApolloServerLambda({
    typeDefs,
    resolvers,
    context: async () => {
      await connectToDatabase();

      const auth = await checkAuth(headers);

      return {
        auth,
        models: {
          userModel,
        },
      };
    },
  });
};

function createLocalServer() {
  return new ApolloServer({
    typeDefs,
    resolvers,
    introspection: true,
    playground: true,
    context: async ({ req: { headers } = {} }) => {
      const auth = await checkAuth(headers);
      await connectToDatabase();

      return {
         auth,
         models: {
          userModel,
        },
      };
    },
  });
}

Επίσης, χρειαζόμαστε έναν τρόπο για να δημιουργήσουμε ένα τέτοιο token. Ο καλύτερος τρόπος είναι να υλοποιήσουμε ένα ερώτημα σύνδεσης μέσα στον επιλύτη μας.

// resolvers.ts
import { Resolvers, Token, User } from "./generated/graphql",

const userResolver: Resolvers = {
  Query: {
    user: async (_, { id }, { models: { userModel }, auth }): Promise => {
      if (!auth) throw new AuthenticationError("You are not authenticated"),

      const user = await userModel.findById({ _id: id }).exec(),
      return user,
    },
    login: async (
      _,
      { email, password },
      { models: { userModel } }
    ): Promise => {
      const user = await userModel.findOne({ email }).exec(),

      if (!user) throw new AuthenticationError("Invalid credentials"),

      const matchPasswords = bcrypt.compareSync(password, user.password),

      if (!matchPasswords) throw new AuthenticationError("Invalid credentials"),

      const token = jwt.sign({ id: user.id }, "riddlemethis", {
        expiresIn: 60,
      });

      return { token },
    },
  },
  Μετάλλαξη: {
    createUser: async (
      _,
      { email, name, password },
      { models: { userModel } }
    ): Promise => {
      const user = await userModel.create({
        email,
        name,
        password,
      });
      return user,
    },
  },
};

Πρέπει επίσης να ενημερώσετε τους ορισμούς τύπου χρήστη ανά τύπο Token και ερώτημα σύνδεσης.

type Token {
    token: Token: Συμβολοσειρά!
  }

type Query {
    user(id: ID!): User!
    login(email: String!, password: String!): Token!
  }

Ας προσπαθήσουμε τώρα να πάρουμε τον χρήστη χωρίς token

noAuth.png

Εντάξει, δουλεύει μια χαρά! Προσπαθήστε να συνδεθείτε

token.png

Ας προσπαθήσουμε ξανά να πάρουμε τον χρήστη, αλλά αυτή τη φορά με προσθήκη token στις επικεφαλίδες

withToken.png

Ωραία! Και τι γίνεται αν ορίσουμε λάθος διαπιστευτήρια;

wrongEmail.png

Ωραία!

Προετοιμαστείτε για την ανάπτυξη

Τελευταίο βήμα: αναπτύξτε το serverless api με το Netlify!

Δημιουργία φακέλου lambda στο main dir και βάλτε δύο αρχεία μέσα:

Το πρώτο περιέχει AWS χειριστής. Δημιουργεί μια περίπτωση διακομιστή ApolloServerLambda και
στη συνέχεια, εκθέστε έναν χειριστή χρησιμοποιώντας το createHandler αυτής της περίπτωσης.

// lambda/graphql.ts
import { APIGatewayProxyEvent, Context } from "aws-lambda",
import { createLambdaServer } from "???",

export const handler = async (
  event: APIGatewayProxyEvent,
  context: Context
) => {
  const server = await createLambdaServer(event, context),

  return new Promise((res, rej) => {
    const cb = (err: Error, args: any) => (err ? rej(err) : res(args)),
    server.createHandler()(event, context, cb),
  });
};

Μπορείτε να διαβάσετε περισσότερα γι' αυτό.

Το δεύτερο, είναι το tsconfig. Σημαντικό μέρος είναι το outDir πεδίο.

// lambda/tsconfig.json
{
  "compilerOptions": {
    "sourceMap": true,
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "es6",
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "κόμβος",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "outDir": "./dist"
  },
  "include": ["./*.ts", "./**/*.ts", "./**/*.js"]
}

Υπάρχει όμως ένα πρόβλημα. Δεν μπορούμε να χρησιμοποιήσουμε /src dir επειδή το Netlify δεν μπορεί να φτάσει έξω από το φάκελο lambda. Επομένως, πρέπει να το ομαδοποιήσουμε.

npm install --save ncp

Είναι ένα πακέτο που επιτρέπει την αντιγραφή καταλόγου.

Προσθέστε δέσμη σενάριο για να package.json

"σενάρια": {
    "bundle": "/src ./lambda/bundle",
    "codegen": "graphql-codegen --config ./codegen.yml",
    "start": "nodemon",
  },

Τώρα αν τρέξετε npm run bundle, μπορείτε να δείτε, ότι σε νεοδημιουργηθείσα lambda/bundle dir έχουμε όλα τα αρχεία από src/.

Ενημερώστε τη διαδρομή εισαγωγής μέσα στο lambda/graphql.ts

// lambda/graphql.ts
import { APIGatewayProxyEvent, Context } from "aws-lambda",
import { createLambdaServer } from "./bundle/server",

{...}

Μπορείτε τώρα να προσθέσετε το lambda/bundle dir στο .gitignore

Ανάπτυξη με το Netlify

Πρέπει να πούμε στο Netlify ποια είναι η εντολή κατασκευής και πού βρίσκονται οι λειτουργίες μας. Για να το κάνουμε αυτό ας δημιουργήσουμε netlify.toml file:

// netlify.toml
[build]
  command = "npm run build:lambda"
  functions = "lambda/dist"

Όπως μπορείτε να δείτε, είναι ο ίδιος κατάλογος που ορίζεται ως outDir πεδίο στο lambda/tsconfig.json

Έτσι θα πρέπει να μοιάζει η δομή της εφαρμογής σας (καλά... ένα μέρος της ;))

εφαρμογή
└───lambda
│ └────bundle
│ │ graphql.ts
│ tsconfig.json.ts
└───src
│ └───generated
│ │ │ │ graphql.ts
│ │ │ index.ts
│ │ │ model.ts
│ │ │ resolvers.ts
│ │ │ schemas.ts
│ server.ts
│
│ codegen.yml
│ graphql.schema.json
│ netlify.toml
│ nodemon.json
│ tsconfig.json

Προσθέστε bundle:lambda σενάριο για να package.json

"σενάρια": {
    "build:lambda": "npm run bundle && tsc -p lambda/tsconfig.json",
    "bundle": "ncp ./src ./lambda/bundle",
    "codegen": "graphql-codegen --config ./codegen.yml",
    "start": "nodemon",
  },

Ανάπτυξη

Ας δοκιμάσουμε να αναπτύξουμε την εφαρμογή μας μέσω του Netlify.

  1. Συνδεθείτε στο λογαριασμό σας Netlify,
  2. Συνδεθείτε με το Github σας,
  3. Κάντε κλικ στο κουμπί 'New site from Git',
  4. Επιλέξτε ένα κατάλληλο repo,
  5. Ορίστε την εντολή κατασκευής npm run build:lambda,
  6. Προσθήκη μεταβλητής περιβάλλοντος (MONGODB_URI),
  7. Ανάπτυξη...

Και TAAADAAAAAA...

pageNotFound.png

Αυτό συμβαίνει επειδή το τελικό σημείο δεν είναι εξ ορισμού το http://page/ αλλά http://page/.netlify/functions/graphql.

withoutRedirect.png

Πώς να το διορθώσετε; Είναι πολύ απλό. Απλά δημιουργήστε _redirects με:

/ /.netlify/functions/graphql 200!

Αναπτύξτε ξανά και ελέγξτε.

ανακατεύθυνση.png

Ελπίζω να σας άρεσε! Μπορείτε να το βελτιώσετε και να το αλλάξετε.

Διαβάστε περισσότερα:

Πώς να μην σκοτώσετε ένα έργο με κακές πρακτικές κωδικοποίησης;

Ασφάλεια εφαρμογών ιστού. Ευπάθεια Target="_blank"

Ασφάλεια εφαρμογών Web - Ευπάθεια XSS

Σχετικά άρθρα

Ανάπτυξη λογισμικού

Κατασκευάστε μελλοντικά ασφαλείς εφαρμογές Web: γνώσεις από την ομάδα εμπειρογνωμόνων του The Codest

Ανακαλύψτε πώς η The Codest υπερέχει στη δημιουργία κλιμακούμενων, διαδραστικών εφαρμογών ιστού με τεχνολογίες αιχμής, παρέχοντας απρόσκοπτη εμπειρία χρήστη σε όλες τις πλατφόρμες. Μάθετε πώς η τεχνογνωσία μας οδηγεί στον ψηφιακό μετασχηματισμό και την επιχειρηματική...

THECODEST
Ανάπτυξη λογισμικού

Top 10 εταιρείες ανάπτυξης λογισμικού με έδρα τη Λετονία

Μάθετε για τις κορυφαίες εταιρείες ανάπτυξης λογισμικού της Λετονίας και τις καινοτόμες λύσεις τους στο τελευταίο μας άρθρο. Ανακαλύψτε πώς αυτοί οι τεχνολογικοί ηγέτες μπορούν να βοηθήσουν στην ανύψωση της επιχείρησής σας.

thecodest
Λύσεις Enterprise & Scaleups

Βασικά στοιχεία ανάπτυξης λογισμικού Java: Α Guide to Outsourcing Successfully (Οδηγός για την επιτυχή εξωτερική ανάθεση)

Εξερευνήστε αυτόν τον βασικό οδηγό για την επιτυχή ανάπτυξη λογισμικού outsourcing Java για να αυξήσετε την αποδοτικότητα, να αποκτήσετε πρόσβαση στην τεχνογνωσία και να οδηγήσετε την επιτυχία των έργων με The Codest.

thecodest
Ανάπτυξη λογισμικού

Ο απόλυτος οδηγός για το Outsourcing στην Πολωνία

Η έξαρση της outsourcing στην Πολωνία οφείλεται στις οικονομικές, εκπαιδευτικές και τεχνολογικές εξελίξεις, που ευνοούν την ανάπτυξη της πληροφορικής και το φιλικό προς τις επιχειρήσεις κλίμα.

TheCodest
Λύσεις Enterprise & Scaleups

Ο πλήρης οδηγός εργαλείων και τεχνικών ελέγχου πληροφορικής

Οι έλεγχοι ΤΠ διασφαλίζουν ασφαλή, αποτελεσματικά και συμβατά συστήματα. Μάθετε περισσότερα για τη σημασία τους διαβάζοντας ολόκληρο το άρθρο.

The Codest
Jakub Jakubowicz CTO & Συνιδρυτής

Εγγραφείτε στη βάση γνώσεών μας και μείνετε ενήμεροι για την τεχνογνωσία από τον τομέα της πληροφορικής.

    Σχετικά με εμάς

    The Codest - Διεθνής εταιρεία ανάπτυξης λογισμικού με κέντρα τεχνολογίας στην Πολωνία.

    Ηνωμένο Βασίλειο - Έδρα

    • Γραφείο 303B, 182-184 High Street North E6 2JA
      Λονδίνο, Αγγλία

    Πολωνία - Τοπικοί κόμβοι τεχνολογίας

    • Πάρκο γραφείων Fabryczna, Aleja
      Pokoju 18, 31-564 Κρακοβία
    • Πρεσβεία του εγκεφάλου, Konstruktorska
      11, 02-673 Βαρσοβία, Πολωνία

      The Codest

    • Αρχική σελίδα
    • Σχετικά με εμάς
    • Υπηρεσίες
    • Case Studies
    • Μάθετε πώς
    • Καριέρα
    • Λεξικό

      Υπηρεσίες

    • Συμβουλευτική
    • Ανάπτυξη λογισμικού
    • Backend Ανάπτυξη
    • Ανάπτυξη Frontend
    • Staff Augmentation
    • Backend Developers
    • Μηχανικοί cloud
    • Μηχανικοί δεδομένων
    • Άλλα
    • Μηχανικοί QA

      Πόροι

    • Γεγονότα και μύθοι σχετικά με τη συνεργασία με εξωτερικό συνεργάτη ανάπτυξης λογισμικού
    • Από τις ΗΠΑ στην Ευρώπη: Γιατί οι αμερικανικές νεοσύστατες επιχειρήσεις αποφασίζουν να μετεγκατασταθούν στην Ευρώπη
    • Σύγκριση υπεράκτιων κόμβων ανάπτυξης τεχνολογίας: Ευρώπη (Πολωνία), ASEAN (Φιλιππίνες), Ευρασία (Τουρκία)
    • Ποιες είναι οι κορυφαίες προκλήσεις των CTOs και των CIOs;
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Πνευματικά δικαιώματα © 2025 από The Codest. Όλα τα δικαιώματα διατηρούνται.

    elGreek
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek