系统在此应用程序堆栈溢出

by Will Abramson

威尔·艾布拉姆森(Will Abramson)

从部署我的第一个完整堆栈Web应用程序中学到的经验教训 (Lessons learned from deploying my first full-stack web application)

I recently achieved one of my long-term goals: deploying my first full-stack web application.

我最近实现了我的长期目标之一:部署我的第一个完整堆栈Web应用程序。

In this post, I’ll be sharing the lessons I learned from a beginner’s perspective, along with some useful tutorials I followed, key roadblocks that I had to overcome, and mistakes that I made along the way. I want to help other developers understand what’s involved in deploying a web application.

在这篇文章中,我将分享我从初学者的角度学到的教训,以及我遵循的一些有用的教程,必须克服的主要障碍以及一路走来的错误。 我想帮助其他开发人员了解部署Web应用程序涉及的内容。

After spending over six weeks googling, trying, failing, and trying again, I finally managed to deploy my web application. It was comprised of a Node.js backend along with a React frontend to an Amazon Web Services (AWS) EC2 virtual machine.

经过六个多星期的搜寻,尝试,失败和重试之后,我终于设法部署了Web应用程序。 它由Node.js后端以及Amazon Web Services(AWS)EC2虚拟机的React前端组成。

It was quite a challenge but it was truly satisfying, as in the end the application was successfully deployed and is now accessible via a public domain name.

这是一个很大的挑战,但确实令人满意,因为最终该应用程序已成功部署,现在可以通过公共域名访问。

The biggest difficulty for me was finding the information. I didn’t understand what was involved in deployment. So I struggled to find effective answers on the web. I failed to find a single guide for the whole process.

对我来说最大的困难是查找信息。 我不了解部署中涉及的内容。 因此,我很难在网上找到有效的答案。 我没有找到整个过程的单一指南。

Hopefully, I can simplify the deployment learning curve for the next person by bringing all the information I learned into one place.

希望我可以将我学到的所有信息都放在一个地方,从而简化下一个人的部署学习曲线。

So here it goes…

所以就这样...

部署应用程序意味着什么? (What does it mean to deploy an application?)

A web application is split into two parts.

Web应用程序分为两部分。

  • Client side code: This is your frontend UI code. These are static files that don’t change throughout your application’s life. Static files need to exist somewhere so that your users can download and run them in their browser on the client side. I will go into more detail about where that somewhere might be later.

    客户端代码:这是您的前端UI代码。 这些是静态文件,它们在应用程序的整个生命周期中都不会改变。 静态文件必须存在于某个位置,以便您的用户可以在客户端的浏览器中下载并运行它们。 我将在以后更详细地介绍该位置。

  • Server side code: This deals with all the logic of your application. It should be run on a server (machine), commonly a virtual one like an EC2 instance, much like you run it when developing locally.

    服务器端代码:处理您应用程序的所有逻辑。 它应在服务器(机器)上运行,通常是虚拟服务器(如EC2实例),就像在本地开发时运行它一样。

To run your local code, the server must have a copy of it. I just cloned my Github repo onto the server from the command line interface of the server.

要运行您的本地代码,服务器必须具有它的副本。 我只是从服务器的命令行界面将我的Github存储库克隆到服务器上。

You also need to setup your server. This includes:

您还需要设置服务器。 这包括:

  • setting up the machine to be able to access the internet and run your code设置机器以能够访问互联网并运行您的代码
  • exposing the correct ports

    暴露正确的端口

  • listening for HTTP requests (Internet requests)侦听HTTP请求(Internet请求)
  • pointing a custom domain name to the server your application is running from将自定义域名指向应用程序运行所在的服务器

You’ll know it’s working when you can access your application using your custom domain name from any machine on the Internet and all the functionality of your application is working as expected.

当您可以从Internet上的任何计算机上使用自定义域名访问应用程序并且应用程序的所有功能都按预期运行时,您就会知道它正在工作。

So, that’s an overview. But, how do we actually do it?

所以,这是一个概述。 但是,我们实际上该如何做呢?

入门 (Getting started)

You should split up your application and break down the problem. You are deploying two different things: client-side static files and server-side code.

您应该拆分应用程序并解决问题。 您将部署两种不同的内容:客户端静态文件和服务器端代码。

My first mistake was to think of my application as a whole, rather than two separate applications that talk to each other.

我的第一个错误是将我的应用程序视为一个整体,而不是将两个单独的应用程序相互通信。

This added to the complexity and made googling for answers useless. It left me feeling overwhelmed.

这增加了复杂性,并且使搜​​索变得毫无用处。 这让我感到不知所措。

I broke down the problem into these steps. Although each problem can always be broken down further.

我将问题分解为以下步骤。 尽管可以始终将每个问题进一步分解。

  • Setting up your VM and deploying your Backend设置虚拟机并部署后端
  • Deploying your Frontend部署前端
  • Getting the Two Applications Communicating使两个应用程序进行通信
  • Pointing your Domain Name指向您的域名

In the figure below, I’ve attempted to put the complete process in a diagram.

在下图中,我试图将整个过程放在图表中。

设置虚拟机并部署后端 (Setting up your VM and deploying your Backend)

In my case, this was an Express.js server deployed on an amazon EC2 virtual machine. I would’ve explained how to do it, but the tutorial “Creating and Managing a Node.js Server on AWS - Part 1” does a far better job.

就我而言,这是部署在Amazon EC2虚拟机上的Express.js服务器。 我已经解释了如何做到这一点,但是教程“ 在AWS上创建和管理Node.js服务器-第1部分 ”做得更好。

It’s the best tutorial I have come across in this space and covers:

这是我在这个领域遇到的最好的教程,内容包括:

  • Starting an AWS virtual machine启动AWS虚拟机
  • Getting up correct security groups for ports为端口建立正确的安全组
  • Pulling code from GitHub onto the virtual machine将代码从GitHub提取到虚拟机上
  • Running your server运行服务器
  • Using Nginx, a HTTP server, to forward requests from port 80使用Nginx(HTTP服务器)转发来自端口80的请求
  • Using PM2 to persist the process running your server使用PM2保留运行服务器的过程

It was a life saver, and without it I would still probably be stuck. So thank you, Robert Tod.

它可以挽救生命,没有它,我可能仍然会陷入困境。 谢谢罗伯特·托德 ( Robert Tod) 。

You can easily test that your server is running using Postman to send a request to one of your Backend endpoints.

您可以使用Postman向一个后端端点发送请求,轻松测试服务器是否正在运行。

部署前端 (Deploying your Frontend)

So now that you have a server with your backend running (I hope), you need to get your Frontend working. This is really easy when you understand the process.

因此,既然您拥有一台运行后端的服务器(希望如此),则需要使前端工作。 当您了解此过程时,这真的很容易。

Unfortunately, I didn’t for a long time. For example, at the beginning I tried to run my Frontend using npm start.

不幸的是,我没有很长时间了。 例如,在一开始,我尝试使用npm start运行Frontend。

Npm start creates a local development server, serving the files so that they are only accessible using localhost which is not what we want.

Npm start创建一个本地开发服务器,为文件提供服务,以便只能使用不需要的localhost访问文件。

To deploy the Frontend code, you have to store all the files on your virtual machine in a location your web server knows about. The web server lets a client download the code and run it in their browser.

要部署前端代码,您必须将虚拟机上的所有文件存储在Web服务器知道的位置。 Web服务器允许客户端下载代码并在其浏览器中运行。

Apache and Nginx are examples of web servers.

Apache和Nginx是Web服务器的示例。

A web server listens to certain ports, port 80 or more commonly port 443 (secure), and either serves static files (your Frontend code) or passes the request to a different port. For example, we saw a request to the Backend in the Node.js tutorial above.

Web服务器侦听某些端口,端口80或更常见的端口443(安全),并提供静态文件(您的前端代码)或将请求传递到其他端口。 例如,我们在上面的Node.js教程中看到了对后端的请求。

As Frontend code is just a collection of files stored on a web server, we want to make these files as small and optimized as possible. This ensures that the client can download and run them as fast as possible.

由于前端代码只是存储在Web服务器上的文件的集合,因此我们希望使这些文件尽可能小并进行优化。 这样可以确保客户端可以尽快下载并运行它们。

Faster page loads equal happy users.

更快的页面加载速度等于满意的用户。

All your Frontend JavaScript files can be bundled into a single JavaScript file. This is usually done by running npm run build, assuming you have this script defined in your package.json.

您所有的前端JavaScript文件都可以捆绑到一个JavaScript文件中。 假设您在package.json中定义了此脚本,通常可以通过运行npm run build来完成。

You can read more about bundling code here.

您可以在此处阅读有关捆绑代码的更多信息。

Basically, bundling your application removes anything that isn’t essential. This includes shortening names and placing all JavaScript code in one file. It will also compile your code into the correct JavaScript version. This is so all web browsers can understand and run it (for example, converting TypeScript to JavaScript).

基本上,捆绑您的应用程序会删除所有不必要的内容。 这包括缩短名称并将所有JavaScript代码放在一个文件中。 它还会将您的代码编译为正确JavaScript版本。 这样所有的Web浏览器都可以理解和运行它(例如,将TypeScript转换为JavaScript)。

When your code is bundled, you just have to copy the files into your web server. Then configure your web server to serve files stored at that location.

捆绑代码后,只需要将文件复制到Web服务器中。 然后配置您的Web服务器以提供存储在该位置的文件。

Here is a good article on deploying static files to an Nginx web server.Hopefully, if all is going well (which it never does), your Frontend code is now working.

这是一篇关于将静态文件部署到Nginx Web服务器上的好文章 。希望一切顺利(从未实现),您的Frontend代码现在可以正常工作了。

Visit the public DNS for the virtual machine to verify that the static information from the site loads.

访问虚拟机的公共DNS,以验证是否从站点加载了静态信息。

使两个应用程序进行通信 (Getting the Two Applications Communicating)

So I had both my applications running individually, but something wasn’t right. I couldn’t get rid of a network request error.

所以我让我的两个应用程序都单独运行,但是有些不对劲。 我无法摆脱网络请求错误。

This was the most frustrating point for me. I was so close, but I ran into some setbacks that ended up taking weeks to solve.

这是我最沮丧的一点。 我是如此亲密,但遇到了一些挫折,最终需要花费数周的时间才能解决。

Cross-Origin Resource Sharing (CORS) is a mechanism that allows communication between different IP addresses or ports. You want your Backend to be allowed to send data back to your Frontend.

跨域资源共享(CORS)是一种允许不同IP地址或端口之间进行通信的机制。 您希望允许后端将数据发送回前端。

To enable this, your Frontend must include the correct headers when requesting resources. This can be done in two ways:

为此,您的前端在请求资源时必须包含正确的标头。 这可以通过两种方式完成:

  • The headers can be added in Nginx although it takes some figuring out. You can start here.

    头文件可以在Nginx中添加,尽管需要花一些时间。 你可以从这里开始。

  • You can use the cors npm module to include the headers.

    您可以使用cors npm模块包含标头。

A great way to test this if it is working is by looking within the network tab of your browser’s developer tools. This shows all the requests your application is making. If you select a request you can see where the request went to and what headers it included.

测试此功能是否正常的一种好方法是在浏览器开发人员工具的“网络”标签中查看。 这显示了您的应用程序提出的所有请求。 如果选择一个请求,则可以看到该请求的去向及其包含的标题。

Once you have the right request headers being sent with your request, you have to make sure the requests are going to the correct place. This should be the address and port of your EC2 Backend server and not the address and port of your local Backend server like mine was.

将正确的请求标头与请求一起发送后,必须确保将请求发送到正确的位置。 这应该是EC2后端服务器的地址和端口,而不是像我的一样的本地后端服务器的地址和端口。

Your Frontend communicates with your Backend using HTTP requests. Somewhere in your Frontend, code you will tell it where your Backend is located.

您的前端使用HTTP请求与后端进行通信。 在您的前端的某个地方,通过代码可以告诉您后端的位置。

const networkInterface = createNetworkInterface({uri: ‘http://0.0.0.0:5000/graphql',
});

Mine looked like this, which clearly was not going to be correct for my production server.

我的看起来像这样,显然对于我的生产服务器来说是不正确的。

Annoyingly this made my application seem like it worked when I first navigated to it on my local machine, as my local server was running and able to return the required information.

令人烦恼的是,当我的本地服务器正在运行并且能够返回所需的信息时,当我第一次在本地计算机上导航到它时,我的应用程序似乎可以正常工作。

To fix this, you can simply change the URI defined, but that means having to change it back every time you do further development, which is not the best approach (I know because I did it).

要解决此问题,您可以简单地更改定义的URI,但这意味着每次进行进一步开发时都必须将其改回来,这不是最好的方法(我知道是因为我这样做了)。

A more sophisticated solution is to include both URIs and use environment variables to select the appropriate one.

一种更复杂的解决方案是同时包含URI和使用环境变量来选择适当的解决方案。

const networkInterface = createNetworkInterface({   uri: process.env.NODE_ENV === 'production' ?      'http://thecommunitymind.com/graphql' : 'http://0.0.0.0:5000/graphql',
});

Simple but effective. Just make sure you set your NODE_ENV to production when using it for your production server.

简单但有效。 只需确保将NODE_ENV用于生产服务器时将其设置为生产即可。

We’re almost there. In fact, your deployment might work now.

我们快到了。 实际上,您的部署现在可以工作了。

But I had one last problem to overcome.

但是我还有最后一个需要克服的问题。

Even though my CORS setup was correct, the required headers were not being included consistently and were only getting added sometimes. For some POST requests, the CORS headers were not always present. Very odd!

即使我的CORS设置正确,所需的标头也未始终包括在内,有时只是添加而已。 对于某些POST请求,并不总是存在CORS标头。 很奇怪!

This error lead me on a frustrating goose chase trying to fix my CORS setup in Nginx, when actually it had nothing to do with CORS.

这个错误使我陷入了令人沮丧的追赶中,试图在Nginx中修复我的CORS设置,而实际上与CORS无关。

Actually, I didn’t even need to do anything with CORS in Nginx, because I was using the CORS npm module.

实际上,我甚至不需要在Nginx中对CORS做任何事情,因为我正在使用CORS npm模块。

The error was due to two other issues:

该错误是由于其他两个问题引起的:

  • My database was included as an sqlite file in the Backend and我的数据库作为sqlite文件包含在后端中,并且
  • My process manager, PM2, was watching for file changes

    我的流程经理PM2正在监视文件更改

So writing to the database file on a POST request caused PM2 to restart the server. This was leading to the correct headers not getting picked up which resulted in misleading errors.

因此,根据POST请求写入数据库文件会导致PM2重新启动服务器。 这导致未提取正确的标头,从而导致误导性错误。

A great tip and one I wish I had known earlier is to check your server logs on your EC2 instance. Whether you’re using PM2 or something else there will always be a way to check your logs. Just Google it!

我希望早些时候知道的一个很好的技巧是检查EC2实例上的服务器日志。 无论您使用的是PM2还是其他产品,总会有一种检查日志的方法。 只是谷歌而已!

These logs provided the key to solve my issue.

这些日志提供了解决我的问题的关键。

I simply had to turn off the watch ability of PM2. Bingo. And finally, it worked.

我只需要关闭PM2的监视功能即可。 答对了。 最后,它奏效了。

指向您的域名 (Pointing your Domain Name)

This is the icing on the cake. You want a nice clean URL for your newly deployed application.

这是锦上添花。 您希望为新部署的应用程序提供一个简洁的URL。

I bought my domain name through Amazon and used Route 53 to point it to the correct EC2 instance. This was a surprisingly painless experience.

我通过亚马逊购买了域名,并使用Route 53将其指向正确的EC2实例。 这是一个令人惊讶的无痛体验。

Amazon’s tutorial was quite sufficient.

亚马逊的教程就足够了。

摘要 (Summary)

I hope this post has helped you understand the web application deployment process and ultimately get your amazing project online — whatever that may be.

我希望这篇文章能帮助您了解Web应用程序的部署过程,并最终使您的惊人项目联机(无论可能如何)。

At least you should have a better idea of what to Google for!

至少您应该对Google有了更好的了解!

Good Luck.

祝好运。

翻译自: https://www.freecodecamp.org/news/lessons-learned-from-deploying-my-first-full-stack-web-application-34f94ec0a286/

系统在此应用程序堆栈溢出

系统在此应用程序堆栈溢出_从部署我的第一个完整堆栈Web应用程序中学到的经验教训...相关推荐

  1. java递归堆栈溢出_【java】递归次数过多导致堆栈溢出

    在写一个算法中,由于递归调用次数过多,堆栈溢出. 堆栈的大小是系统控制的,无法改变. 如果递归调用出现问题,可以考虑采取循环的方式来解决,将需要的数据在关键的调用点保存下来使用.简单的说,就是用自己的 ...

  2. jquery 堆栈溢出_带有jQuery和CSS3的漂亮照片堆栈库

    jquery 堆栈溢出 View demo 查看演示Download Source 下载源 In this tutorial we are going to create a nice and fre ...

  3. java pattern堆栈溢出_我的正则表达式导致Java中的堆栈溢出;我错过了什么?

    我试图使用Scanner的正则表达式来匹配文件中的字符串.正则表达式适用于该行以外的所有内容: DNA="ITTTAITATIATYAAAYIYI[....]ITYTYITTIYAIAIYI ...

  4. sas模拟试验构建线性模型_在sas上构建一个有角度的Web应用程序

    sas模拟试验构建线性模型 The SAS platform is unparalleled in its capability to deliver analytics across the wor ...

  5. 闪亮蔚蓝_在R中构建第一个闪亮的Web应用

    闪亮蔚蓝 数据科学 (DATA SCIENCE) Do you want to make your R code publicly available for others to use? If yo ...

  6. jpa jsf_完整的Web应用程序Tomcat JSF Primefaces JPA Hibernate –第1部分

    jpa jsf 我们创建了这篇文章,将展示如何使用以下工具创建完整的Web应用程序:Tomcat7,带有Primefaces的JSF2(Facelets和Libraries)(具有AutoComple ...

  7. 完整的Web应用程序Tomcat JSF Primefaces JPA Hibernate –第1部分

    我们创建了这篇文章,将展示如何使用以下工具创建完整的Web应用程序:Tomcat7,带有Primefaces的JSF2(Facelets和Libraries)(具有AutoComplete),JPA ...

  8. Rxjs 响应式编程-第四章 构建完整的Web应用程序

    Rxjs 响应式编程-第一章:响应式 Rxjs 响应式编程-第二章:序列的深入研究 Rxjs 响应式编程-第三章: 构建并发程序 Rxjs 响应式编程-第四章 构建完整的Web应用程序 Rxjs 响应 ...

  9. 系统在此应用程序堆栈溢出_部署第一个完整堆栈应用程序之前需要考虑的三件事

    系统在此应用程序堆栈溢出 Building a full stack app is no small endeavor, and deploying it comes with its own hos ...

最新文章

  1. C++:随笔3--复杂的数据结构
  2. 【译】 Stealing the funds of all HTC EXODUS 1 users (HTC 区块链钱包安全漏洞分析)
  3. VTK:图片之CannyEdgeDetector
  4. 电脑中linux系统在哪里设置密码,linux添加一个root级别账户并设置密码linux操作系统 -电脑资料...
  5. 林超贤携彭于晏带《紧急救援》再度征战2020春节档
  6. Idea中的maven灰色
  7. java什么叫用例_BigInteger的.isProbablePrime()的可能用例是什么?
  8. 【雕爷学编程】Arduino动手做(84)---DS1307时钟模块
  9. 【洛谷试炼场】普及练习场——字符串处理
  10. 华为管理学案例分析_华为案例分析——管理学作业.ppt
  11. Revel框架的搭建与部署教程
  12. Android Studio模拟器AndroidWifi连接成功但无法访问网络问题
  13. 模型可视化工具Netron手把手教学
  14. 计算机视觉学习路线—计算机视觉入门必读的20本书
  15. Android——Cocosd2d-x手机游戏开发学习思路
  16. memcached与redis技术的对比试验
  17. 列表找房(十)02-渲染列表模板
  18. 如何在一个服务器上建立两个(多个)网站
  19. 创建maven或者Gradle项目的时候GroupId和ArtifactId以及Version是什么意思?
  20. Python复健练习:爬取58同城房产月租及户型加密字体

热门文章

  1. 8597 石子划分问题 dpdp,只考虑第一次即可
  2. 1.2 如何在visual studio 中建立C#程序
  3. 5-python学习——条件语句
  4. 公共的Controler,是给非授权的用户访问
  5. 第十篇: Timer 控件
  6. 事实上着就是MAYA4.5完全手册插件篇的内容
  7. 获取对象属性(key)
  8. 2018年阿里云NoSQL数据库大事盘点
  9. 【跃迁之路】【651天】程序员高效学习方法论探索系列(实验阶段408-2018.11.24)...
  10. pdf 字体和图片抽取