提供靜態檔案

除了處理動態要求以外,應用程式通常需要提供 JavaScript、圖片和 CSS 等靜態檔案。彈性環境中的應用程式可以直接提供靜態檔案,也可以透過 Cloud Storage 等 Google Cloud 選項或第三方內容傳遞聯播網 (CDN) 提供靜態檔案。

從 Cloud Storage 提供檔案

您可以將動態網頁應用程式的靜態資產託管於 Cloud Storage。使用 Cloud Storage (而不直接從應用程式提供檔案) 的優點如下:

  • Cloud Storage 在本質上就是當成內容傳遞聯播網使用。根據預設,凡是可公開讀取的物件在全域 Cloud Storage 網路中都能夠快取,因此不需要特別進行設定。
  • 無須向 Cloud Storage 提供靜態資產,因此可減輕應用程式的負載。這種做法可能有助大幅降低應用程式的執行成本,實際情況視您擁有的靜態資產數量以及存取的頻率而定。
  • 如果使用 Cloud Storage 存取內容,頻寬費用通常較低。

您可以使用 Google Cloud CLICloud Storage API 將資產上傳至 Cloud Storage。

Google Cloud 用戶端程式庫提供慣用的 Cloud Storage 用戶端,讓您使用 App Engine 應用程式中的 Cloud Storage 儲存及擷取資料。

從 Cloud Storage 值區提供資產的範例

本範例會使用 gcloud CLI 建立 Cloud Storage bucket 並上傳靜態資產:

  1. 建立值區。用專案 ID 來當做值區的名稱是很常見的做法,但您不一定採用這種命名方式。值區名稱不得重複。

    gcloud storage buckets create gs://<var>your-bucket-name</var>
    
  2. 設定 IAM 政策,將讀取存取權授予值區中的項目。

    gcloud storage buckets add-iam-policy-binding gs://<var>your-bucket-name</var> --member=allUsers --role=roles/storage.objectViewer
    
  3. 將項目上傳到值區。使用 rsync 指令通常可以最快速且最輕鬆地上傳及更新資產。您也可以使用 cp

    gcloud storage rsync ./static gs://<var>your-bucket-name</var>/static --recursive
    

您現在可以透過 https://storage.googleapis.com/<var>your-bucket-name</var>/static/... 來存取靜態資產。

如要進一步瞭解如何使用 Cloud Storage 來提供靜態資產,包括從自訂網域名稱提供資產的方式,請參閱如何託管靜態網站

透過其他 Google Cloud 服務提供檔案

您也可以選擇使用 Cloud CDN 或其他 Google Cloud 儲存空間服務。

直接透過應用程式提供檔案

一般而言,從應用程式提供檔案相當簡單,不過請考量下列幾項缺點:

  • 要求提供靜態檔案時,所使用的資源也可能會用於動態要求。
  • 端看您所採用的設定,從應用程式提供檔案可能會導致回應延遲,而這也會影響建立新執行個體以處理負載的時機。

透過應用程式提供靜態檔案的範例

Go

以下範例說明如何透過應用程式提供靜態檔案。您可以在 app.yaml 檔案中指定執行階段版本和作業系統,即可針對任何支援的 Go 版本使用本指南中的範例應用程式。

您可以使用標準的 http.FileServerhttp.ServeFile,直接透過應用程式提供檔案。


// Package static demonstrates a static file handler for App Engine flexible environment.
package main

import (
	"fmt"
	"net/http"

	"google.golang.org/appengine"
)

func main() {
	// Serve static files from "static" directory.
	http.Handle("/static/", http.FileServer(http.Dir(".")))

	http.HandleFunc("/", homepageHandler)
	appengine.Main()
}

const homepage = `<!doctype html>
<html>
<head>
  <title>Static Files</title>
  <link rel="stylesheet" type="text/css" href="/static/main.css">
</head>
<body>
  <p>This is a static file serving example.</p>
</body>
</html>`

func homepageHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, homepage)
}

Java

以下範例示範如何透過應用程式提供靜態檔案。您可以在 app.yaml 檔案中指定執行階段版本和作業系統,即可針對任何支援的 Java 版本使用本指南中的範例應用程式。

Java 執行階段的 Servlet 容器會使用應用程式的部署描述元 (即 web.xml 檔案),將網址對應至 Servlet,包括靜態資產在內。如果您未指定 web.xml,系統會使用預設值,將所有項目對應至預設 servlet。

在這個範例中,./src/main/webapp/index.html 是指從 /stylesheets/styles.css 提供的樣式表單。

<!doctype html>
<html>
<head>
<title>Static Files</title>
<link rel="stylesheet" type="text/css" href="/stylesheets/styles.css">
</head>
<body>
  <p>This is a static file serving example.</p>
</body>
</html>

styles.css 檔案位於 ./src/main/webapp/stylesheets/styles.css

body {
  font-family: Verdana, Helvetica, sans-serif;
  background-color: #CCCCFF;
}

您可以在 web.xml 檔案中明確設定靜態檔案的處理方式。舉例來說,如果您想為所有含有 .jpg 副檔名的檔案對應要求:

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.jpg</url-pattern>
</servlet-mapping>

如果您使用 Play 之類的網路架構,請參閱靜態資產的架構說明文件。

Node.js

以下範例示範如何透過應用程式提供靜態檔案。您可以在 app.yaml 檔案中指定執行階段版本和作業系統,即可針對任何支援的 Node.js 版本使用本指南中的範例應用程式。

大多數的網路架構都包含提供靜態檔案的支援。在本範例中,應用程式會使用 express.static 中介軟體,從 ./public 目錄提供檔案至 /static 網址。

'use strict';

const express = require('express');
const app = express();

app.set('view engine', 'pug');

// Use the built-in express middleware for serving static files from './public'
app.use('/static', express.static('public'));

app.get('/', (req, res) => {
  res.render('index');
});

// Start the server
const PORT = parseInt(process.env.PORT) || 8080;
app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}`);
  console.log('Press Ctrl+C to quit.');
});

視圖參照 /static/main.css

doctype html
html(lang="en")
  head
    title Static Files
    meta(charset='utf-8')
    link(rel="stylesheet", href="/static/main.css")
  body
    p This is a static file serving example.

樣式表單本身位於 ./public/css,並由 /static/main.css 提供服務。

body {
  font-family: Verdana, Helvetica, sans-serif;
  background-color: #CCCCFF;
}

其他 Node.js 架構 (例如 HapiKoaSails) 通常支援從應用程式直接提供靜態檔案。如要進一步瞭解如何設定及使用靜態內容,請參閱專屬的說明文件。

PHP

PHP 執行階段會執行 nginx 來提供您的應用程式,而系統已將 nginx 設定為提供專案目錄中的靜態檔案。您必須在 app.yaml 檔案中指定 document_root 來宣告文件的根目錄。您可以在 app.yaml 檔案中指定執行階段版本和作業系統,即可使用本指南中的範例應用程式,適用於任何支援的 PHP 版本。

runtime: php
env: flex

runtime_config:
  document_root: web
  operating_system: ubuntu22
  runtime_version: 8.3

build_env_variables:
  NGINX_SERVES_STATIC_FILES: true

Python

以下範例說明如何透過應用程式提供靜態檔案。您可以在 app.yaml 檔案中指定執行階段版本和作業系統,即可針對任何支援的 Python 版本使用本指南中的範例應用程式。

大多數的網路架構都包含提供靜態檔案的支援。在本範例中,應用程式會使用 Flask 的內建能力,從 /static 網址位置提供 ./static 目錄中的檔案。

此應用程式包括一個可轉譯範本的視圖。Flask 會自動提供 ./static 目錄中的所有內容,不需要額外設定。

import logging

from flask import Flask, render_template


app = Flask(__name__)


@app.route("/")
def hello():
    """Renders and serves a static HTML template page.

    Returns:
        A string containing the rendered HTML page.
    """
    return render_template("index.html")


@app.errorhandler(500)
def server_error(e):
    """Serves a formatted message on-error.

    Returns:
        The error message and a code 500 status.
    """
    logging.exception("An error occurred during a request.")
    return (
        f"An internal error occurred: <pre>{e}</pre><br>See logs for full stacktrace.",
        500,
    )


if __name__ == "__main__":
    # This is used when running locally. Gunicorn is used to run the
    # application on Google App Engine. See entrypoint in app.yaml.
    app.run(host="127.0.0.1", port=8080, debug=True)

檢視畫面算繪的範本包含位於 /static/main.css 的樣式表單。

<!doctype html>
<html>
<head>
  <title>Static Files</title>
  <!--
  Flask automatically makes files in the 'static' directory available via
  '/static'.
  -->
  <link rel="stylesheet" type="text/css" href="/static/main.css">
</head>
<body>
  <p>This is a static file serving example.</p>
</body>
</html>

樣式表單位於 ./static/main.css

body {
  font-family: Verdana, Helvetica, sans-serif;
  background-color: #CCCCFF;
}

一般來說,其他 Python 架構 (例如 DjangoPyramidBottle) 都支援直接從應用程式提供靜態檔案。如要進一步瞭解如何設定及使用靜態內容,請參閱專屬的說明文件。

Ruby

大多數的網路架構都支援提供靜態檔案。以下範例說明如何透過應用程式提供靜態檔案。您可以在 app.yaml 檔案中指定執行階段版本和作業系統,即可將本指南中的範例應用程式用於任何支援的 Ruby 版本。

Sinatra

根據預設,Sinatra 網路架構會從 ./public 目錄提供檔案。這個應用程式包含參照 /application.css 的檢視畫面。

body {
  font-family: Verdana, Helvetica, sans-serif;
  background-color: #CCCCFF;
}

樣式表單位於 ./public/application.css,由 /application.css 提供服務。

Ruby on Rails

根據預設,Ruby on Rails 網路架構會從 ./public 目錄提供檔案。靜態 JavaScript 和 CSS 檔案也可以透過 Rails 資產管道產生。

這些範例應用程式包含版面配置檢視區塊,其中包含所有應用程式樣式表單。

doctype html
html
  head
    title Serving Static Files
    link rel="stylesheet" href="/application.css"
    script src="/application.js"
  body
    p This is a static file serving example.

樣式表本身是位於 ./public/application.css.css 檔案。

body {
  font-family: Verdana, Helvetica, sans-serif;
  background-color: #CCCCFF;
}

根據預設,Rails 應用程式在實際工作環境中執行時,不會產生或提供靜態資產。

Ruby 執行階段會在部署期間執行 rake assets:precompile 來產生靜態資產,並設定 RAILS_SERVE_STATIC_FILES 環境變數,藉此在實際工作環境中啟用提供靜態檔案的功能。

.NET

以下範例說明如何透過應用程式提供靜態檔案。您可以在 app.yaml 檔案中指定執行階段版本和作業系統,即可針對任何支援的 .NET 版本使用本指南中的範例應用程式。

<html>
<head>
    <meta charset="utf-8" />
    <title>Hello Static World</title>
</head>
<body>
    <p>This is a static html document.</p>
    <p><img src="trees.jpg" /></p>
</body>
</html>

如要啟用靜態檔案服務功能,請新增:

app.UseDefaultFiles();
app.UseStaticFiles();

從第三方內容傳遞聯播網提供

您可以使用任何外部第三方 CDN 來提供靜態檔案以及快取動態要求,但應用程式的延遲時間和成本可能會隨之增加。

建議您使用支援 CDN 互連網路的第三方 CDN,以獲得更好的效能。