如何在AppEngine Standard和nodejs中提供静态文件

时间:2018-06-16 14:39:40

标签: node.js google-app-engine server static app.yaml

documentation表示您必须更新app.yaml - 就像您对AppEngine中的任何语言一样。它稍后还说明对于本地开发,您可能希望服务器也响应静态请求。但是,当我更新我非常简单的app.yaml时:

runtime: nodejs8

handlers:
  - url: /apiEndPoint
    script: auto

  - url: /.*
    static_dir: public

似乎所有请求仍然最终进入我的脚本 - 这将在prod实例中返回404,因为这些文件将不会被上传。我可以强制他们上传,然后我的nodejs服务器响应静态请求 - 但我认为这个app.yaml的想法是配置它,以便静态文件在我的应用程序逻辑之外提供?

3 个答案:

答案 0 :(得分:2)

所以要明确 - 可以在生产Nodejs Standard AppEngine 中托管静态文件,而不需要使用JS服务器。但是,对于本地开发,您必须找到一种在计算机上运行时在本地提供这些文件的方法。出于这个原因,你将处理程序放在Express中,用于静态文件,因为app.yaml处理程序是第一次通过,因此永远不会在生产中触及它。

如果你想要肯定Express.js没有在生产中提供静态文件,你可以这样做:

// Production instances automatically have this environment variable.
const isLocal = (process.env.NODE_ENV !== "production");

if(isLocal) {
  app.use(express.static('public'));
}

答案 1 :(得分:1)

静态文件在部署期间上传,但与应用程序代码不在同一位置。它们已上传到Google的基础上专门用于直接提供静态内容的基础设施。这可以通过增加部署命令的日志详细程度来确认。

当请求网址与其中一个静态处理程序匹配时,它应该定向到此专用基础设施,它不应该到达您的应用程序代码。通过实际部署确认相对容易。

至于本地开发,我并不完全确定Node.Js服务器的行为(实际上,文档似乎建议使用Express来处理静态文件),但是Python本身就是静态的文件完全基于17:28:25,571 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-3) MSC000001: Failed to start service jboss.deployment.unit."Restaurant-1.1-SNAPSHOT.war".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."Restaurant-1.1-SNAPSHOT.war".WeldStartService: Failed to start service at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: org.jboss.weld.exceptions.WeldException: WELD-001524: Unable to load proxy class for bean Managed Bean [class com.naigoapps.restaurant.model.dao.RestaurantTableDao] with qualifiers [@Any @Default] with class class com.naigoapps.restaurant.model.dao.RestaurantTableDao using classloader ModuleClassLoader for Module "deployment.Restaurant-1.1-SNAPSHOT.war:main" from Service Module Loader at org.jboss.weld.bean.proxy.ProxyFactory.getProxyClass(ProxyFactory.java:371) at org.jboss.weld.injection.producer.SubclassedComponentInstantiator.createEnhancedSubclass(SubclassedComponentInstantiator.java:114) at org.jboss.weld.injection.producer.SubclassedComponentInstantiator.initEnhancedSubclass(SubclassedComponentInstantiator.java:86) at org.jboss.weld.injection.producer.SubclassedComponentInstantiator.<init>(SubclassedComponentInstantiator.java:79) at org.jboss.weld.injection.producer.SubclassedComponentInstantiator.forInterceptedDecoratedBean(SubclassedComponentInstantiator.java:63) at org.jboss.weld.injection.producer.BeanInjectionTarget.initializeAfterBeanDiscovery(BeanInjectionTarget.java:121) at org.jboss.weld.injection.producer.InjectionTargetInitializationContext.initialize(InjectionTargetInitializationContext.java:42) at org.jboss.weld.injection.producer.InjectionTargetService.initialize(InjectionTargetService.java:63) at org.jboss.weld.bootstrap.WeldStartup.deployBeans(WeldStartup.java:433) at org.jboss.weld.bootstrap.WeldBootstrap.deployBeans(WeldBootstrap.java:83) at org.jboss.as.weld.WeldStartService.start(WeldStartService.java:95) at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1948) at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1881) ... 3 more Caused by: org.jboss.weld.exceptions.WeldException: Method already exists. Method: getTargetClass Parameters:[] Return Type: Ljava/lang/Class; at org.jboss.weld.bean.proxy.InterceptedSubclassFactory.addSpecialMethods(InterceptedSubclassFactory.java:386) at org.jboss.weld.bean.proxy.InterceptedSubclassFactory.addMethods(InterceptedSubclassFactory.java:116) at org.jboss.weld.bean.proxy.ProxyFactory.createProxyClass(ProxyFactory.java:469) at org.jboss.weld.bean.proxy.ProxyFactory.getProxyClass(ProxyFactory.java:364) ... 15 more Caused by: org.jboss.classfilewriter.DuplicateMemberException: Method already exists. Method: getTargetClass Parameters:[] Return Type: Ljava/lang/Class; at org.jboss.classfilewriter.ClassFile.addMethod(ClassFile.java:133) at org.jboss.classfilewriter.ClassFile.addMethod(ClassFile.java:148) at org.jboss.weld.bean.proxy.InterceptedSubclassFactory.addSpecialMethods(InterceptedSubclassFactory.java:378) ... 18 more 静态处理程序配置,无需点击任何应用程序代码。可能是因为仍然非常新的Node.JS标准环境支持。

答案 2 :(得分:0)

您需要使用gcloud app deploy在应用程序代码中部署要提供的静态文件。

您的app.yaml文件说:

  • 任何与/apiEndPoint相匹配的请求都将被路由到您的Node.js应用
  • 任何其他请求URL都将从您的public文件夹提供一个静态文件,并且不会到达您的应用程序(一旦部署)。

例如:/index.html将投放public/index.html,如果尚未部署此文件,则它将返回404页面。