国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Table of Contents
But how much does it cost to expand?
Architecture TL;DR
More detailed description
Generate pages from database
Submit and store data without a server
Optimistic URL routing and serverless back-up scenarios
Supports larger scale
Home Web Front-end CSS Tutorial Static First: Pre-Generated JAMstack Sites with Serverless Rendering as a Fallback

Static First: Pre-Generated JAMstack Sites with Serverless Rendering as a Fallback

Apr 16, 2025 am 11:06 AM

Static First: Pre-Generated JAMstack Sites with Serverless Rendering as a Fallback

JAMstack architecture is gaining increasing attention and it provides an efficient method of building a website.

One of the core principles of JAMstack is pre-rendering. This means generating a series of static resources in advance to enable the service of visitors from CDNs or other optimized static hosting environments at the fastest speed and lowest overhead.

But if we were to pre-generate websites in advance, how could we make them look more dynamic? How to build a website that needs frequent changes? How to handle user-generated content?

In fact, this is the ideal application scenario for serverless functions. JAMstack and serverless are the best partners, they complement each other perfectly.

This article will explore a pattern: in a website that consists almost entirely of user-generated content, using serverless functions as a backup solution for pre-generated pages. We will adopt an optimistic URL routing technique where the 404 page is a serverless function to dynamically add serverless rendering.

Sounds complicated? Maybe. But does it work? Absolutely effective!

You can try the demo website to learn about this use case. However, please try it after reading this article.

You are back? Great, let's dive into it.

The philosophy of this sample website is: let you create a warm message and virtual encouragement message to send to friends. You can write a message, customize the lollipop (or popsicle, for my American friends) and get a URL to share with your recipients. That's it, you've illuminated their day. What better than this?

Traditionally, we would use some server-side scripts to process form submissions, add new lollipops (our user-generated content) to the database and generate a unique URL. We then use more server-side logic to parse requests to these pages, query the database to get the data needed to populate the page view, render with the appropriate template, and return it to the user.

This seems reasonable.

But how much does it cost to expand?

Technical architects and technical supervisors often encounter this problem when evaluating the scope of a project. They need to plan, pay and allocate enough resources to cope with successful situations.

This virtual lollipop website is not an ordinary decoration. Since we all want to send each other positive messages, this site will make me a billionaire! As the news spreads, traffic levels will soar. I'd better have a good strategy to ensure that the server can handle heavy loads. I might add some cache tiers, some load balancers, and I would design my database and database servers so I could share the load without being overwhelmed by the need to create and provide all of these lollipops.

But…I don't know how to do these things.

And I don't know how much it costs to add these infrastructures and keep them running. This is complicated.

That's why I like to simplify my hosting as much as possible with pre-rendering.

Providing static pages is much simpler and less expensive than providing pages dynamically from a web server that requires some logic to generate views for each visitor on demand.

Since we are working on a lot of user-generated content, it still makes sense to use the database, but I won't manage it myself. Instead, I'll choose one of many database options that can be used as a service. I'll interact with it through its API.

I might choose Firebase, MongoDB, or any other number of databases. Chris compiled some of these resources on a great website about serverless resources, which is well worth exploring.

In this case, I choose Fauna as my datastore. Fauna provides a great API for storing and querying data. It is a non-SQL style data store, and it is exactly what I need.

Crucially, Fauna has made it a complete business to provide database services. They have deep domain knowledge that I will never have. By using a database-as-a-service provider like this, I inherited an expert data services team for my project , including high availability infrastructure, capacity and compliance security, skilled support engineers, and extensive documentation.

Rather than do it yourself, use such a third-party service, which is its strengths.

Architecture TL;DR

When dealing with proof of concept, I often find myself graffitiing some logical flows. Here is the doodle I made for this website:

And some explanations:

  1. Users create a new lollipop by filling in a normal HTML form.
  2. New content is saved in the database, and its submission triggers new site generation and deployment.
  3. Once the site is deployed, the new lollipop will be accessible via a unique URL. It will be a static page that is quickly served from the CDN without relying on database queries or servers.
  4. No new lollipop will be accessible as a static page until site generation is complete. An unsuccessful request to the lollipop page will fall back to a page that dynamically generates the lollipop page through the dynamic query database API.

This approach first assumes static/pre-generated resources and then falls back to dynamic rendering when the static view is unavailable, which is called "static first", as described by Unilever's Markus Schork, which I like the statement.

More detailed description

You can dig directly into the website's code (it's open source and you can explore as much as you like), or we can discuss it further.

Do you want to dig deeper and explore the implementation of this example? OK, I will explain in more detail:

  • Get data from the database to generate each page
  • Publish data to database API using serverless functions
  • Trigger a complete site regeneration
  • Render on demand when pages have not been generated

Generate pages from database

Later, we will discuss how to publish data to the database, but first, let's assume there are already some entries in the database. We are going to generate a website that contains the pages for each entry.

Static website generators are very good at this. They process the data, apply it to the template, and output HTML files ready to serve. We can use any generator for this example. I chose Eleventy because it is relatively simple and site generation is fast.

To provide Eleventy with some data, we have many options. One way is to provide some JavaScript that returns structured data. This is great for querying database APIs.

Our Eleventy data file will look like this:

 <code>// 設(shè)置與Fauna 數(shù)據(jù)庫的連接。 // 使用環(huán)境變量進(jìn)行身份驗(yàn)證// 并訪問數(shù)據(jù)庫。 const faunadb = require('faunadb'); const q = faunadb.query; const client = new faunadb.Client({ secret: process.env.FAUNADB_SERVER_SECRET }); module.exports = () => { return new Promise((resolve, reject) => { // 獲取最新的100,000 個(gè)條目(為了我們的示例) client.query( q.Paginate(q.Match(q.Ref("indexes/all_lollies")),{size:100000}) ).then((response) => { // 獲取每個(gè)條目的所有數(shù)據(jù)const lollies = response.data; const getAllDataQuery = lollies.map((ref) => { return q.Get(ref); }); return client.query(getAllDataQuery).then((ret) => { // 將數(shù)據(jù)發(fā)送回Eleventy 以用于站點(diǎn)構(gòu)建resolve(ret); }); }).catch((error) => { console.log("error", error); reject(error); }); }) }</code>

I named this file lollies.js and it will make all the data it returns available for Eleventy in a collection named lollies .

We can now use that data in our templates. If you want to view the code that takes that data and generates a page for each project, you can view it in the code repository.

Submit and store data without a server

When we create a new lollipop page, we need to capture the user content into the database so that we can use it to populate the page of the given URL in the future. To do this, we use traditional HTML forms to publish data to the appropriate form handler.

The form looks like this (or see the full code in the repository):

<code></code>

does not have a web server in our hosting scheme, so we need to design a place to handle HTTP posting requests submitted from this form. This is the perfect use case for serverless functions. I'm using Netlify Functions for this. You can use AWS Lambda, Google Cloud, or Azure Functions if you prefer, but I like the simplicity of the Netlify Functions workflow, and the fact that it keeps my serverless API and my UI in the same code repository.

It is a good habit to avoid leaking backend implementation details to the frontend. Clear separation helps make things easier to transplant and tidy. Check out the action properties of the form element above. It publishes the data to a path called /new on my website, which doesn't really hint at which service it will communicate with.

We can route it to any service we like using redirects. I'm sending it to the serverless function I'll configure in this project, but it can be easily customized to send data somewhere else if we want. Netlify provides us with a simple and highly optimized redirection engine that directs our traffic at the CDN level so users can route to the right location very quickly.

The following redirect rule (located in the netlify.toml file of my project) proxies the request for /new to a serverless function called newLolly.js hosted by Netlify Functions.

 <code># 將“new”URL 解析為函數(shù)[[redirects]] from = "/new" to = "/.netlify/functions/newLolly" status = 200</code>

Let's look at that serverless function:

  • Store new data into the database,
  • Create a new URL for the new page and
  • Redirect users to the newly created page so they can see the results.

First, we will need various utilities to parse form data, connect to the Fauna database and create a short, easy-to-read ID for the new lollipop.

 <code>const faunadb = require('faunadb'); // 用于訪問FaunaDB const shortid = require('shortid'); // 生成短唯一URL const querystring = require('querystring'); // 幫助我們解析表單數(shù)據(jù)// 首先,我們使用我們的數(shù)據(jù)庫設(shè)置一個(gè)新的連接。 // 環(huán)境變量幫助我們安全地連接// 到正確的數(shù)據(jù)庫。 const q = faunadb.query const client = new faunadb.Client({ secret: process.env.FAUNADB_SERVER_SECRET })</code>

Now, we will add some code to the request to handle serverless functions. The handler function will parse the request to get the required data from the form submission, then generate a unique ID for the new lollipop, and then create it into the database as a new record.

 <code>// 處理對(duì)無服務(wù)器函數(shù)的請(qǐng)求exports.handler = (event, context, callback) => { // 獲取表單數(shù)據(jù)const data = querystring.parse(event.body); // 添加一個(gè)唯一的路徑ID。并記下它- 我們稍后會(huì)將用戶發(fā)送到它c(diǎn)onst uniquePath = shortid.generate(); data.lollyPath = uniquePath; // 組裝準(zhǔn)備發(fā)送到數(shù)據(jù)庫的數(shù)據(jù)const lolly = { data: data }; // 在fauna db 中創(chuàng)建棒棒糖條目client.query(q.Create(q.Ref('classes/lollies'), lolly)) .then((response) => { // 成功!將用戶重定向到此新棒棒糖頁面的唯一URL return callback(null, { statusCode: 302, headers: { Location: `/lolly/${uniquePath}`, } }); }).catch((error) => { console.log('error', error); // 錯(cuò)誤!返回帶有statusCode 400 的錯(cuò)誤return callback(null, { statusCode: 400, body: JSON.stringify(error) }); }); }</code>

Let's check our progress. We have a way to create new lollipop pages in the database. We also have an automatic build that generates a page for each of our lollipops.

To ensure that there is a complete set of pre-generated pages for each lollipop, we should trigger the rebuild every time a new entry is successfully added to the database. This is very easy to do. Thanks to our static website generator, our build has been automated. We only need one way to trigger it. With Netlify, we can define any number of build hooks. They are webhooks and if they receive HTTP POST requests, they will rebuild and deploy our site. This is one I created in Netlify's site management console:

To regenerate the site, including the pages of each lollipop recorded in the database, we can issue an HTTP POST request to this build hook immediately after saving the new data to the database.

Here is the code that does this:

 <code>const axios = require('axios'); // 簡化發(fā)出HTTP POST 請(qǐng)求// 觸發(fā)新的構(gòu)建以永久凍結(jié)此棒棒糖axios.post('https://api.netlify.com/build_hooks/5d46fa20da4a1b70XXXXXXXXX') .then(function (response) { // 在無服務(wù)器函數(shù)的日志中報(bào)告console.log(response); }) .catch(function (error) { // 描述無服務(wù)器函數(shù)日志中的任何錯(cuò)誤console.log(error); });</code>

You can see it in the full code, which has been added to the successful handler for database insertion.

This is all good if we are willing to wait for the build and deployment to complete before we share the URL of the new lollipop with the recipient. But we are not patient and we immediately want to share it when we get a new URL for the lollipop we just created.

Unfortunately, if we access the URL before the site completes the regeneration to include the new page, we will get a 404. But it's a pleasure to take advantage of this 404.

Optimistic URL routing and serverless back-up scenarios

Using a custom 404 routing, we have the option to send each failed request to the lollipop page to a page that can directly look up lollipop data in the database. We can do this in client JavaScript if we want, but a better way is to dynamically generate a page ready to view from the serverless function.

The method is as follows:

First, we need to tell all requests that want to access the lollipop page (these requests return empty) to go to our serverless function instead. We do this by adding another rule to the Netlify redirect configuration:

 <code># 未找到的棒棒糖應(yīng)該直接代理到API [[redirects]] from = "/lolly/*" to = "/.netlify/functions/showLolly?id=:splat" status = 302</code>

This rule is applied only if the request for the lollipop page does not find a static page ready to serve. It creates a temporary redirect (HTTP 302) to our serverless function, which looks like this:

 <code>const faunadb = require('faunadb'); // 用于訪問FaunaDB const pageTemplate = require('./lollyTemplate.js'); // JS 模板文字// 設(shè)置和授權(quán)Fauna DB 客戶端const q = faunadb.query; const client = new faunadb.Client({ secret: process.env.FAUNADB_SERVER_SECRET }); exports.handler = (event, context, callback) => { // 從請(qǐng)求中獲取棒棒糖ID const path = event.queryStringParameters.id.replace("/", ""); // 在DB 中查找棒棒糖數(shù)據(jù)client.query( q.Get(q.Match(q.Index("lolly_by_path"), path)) ).then((response) => { // 如果找到,則返回視圖return callback(null, { statusCode: 200, body: pageTemplate(response.data) }); }).catch((error) => { // 未找到或發(fā)生錯(cuò)誤,將悲傷的用戶發(fā)送到通用錯(cuò)誤頁面console.log('Error:', error); return callback(null, { body: JSON.stringify(error), statusCode: 301, headers: { Location: `/melted/index.html`, } }); }); }</code>

If a request for any other page (not inside the /lolly/ path of the site) returns a 404, we will not send that request to our serverless function to check for lollipops. We can send users directly to the 404 page. Our netlify.toml configuration allows us to define any number of 404 routing levels by adding more fallback rules to the file. The first successful match in the file will be adopted.

 <code># 未找到的棒棒糖應(yīng)該直接代理到API [[redirects]] from = "/lolly/*" to = "/.netlify/functions/showLolly?id=:splat" status = 302 # 真正的404 可以直接轉(zhuǎn)到這里: [[redirects]] from = "/*" to = "/melted/index.html" status = 404</code>

We're done! We now have a "static first" site that will try to render content dynamically using serverless functions if the URL has not been generated with a static file.

Very fast!

Supports larger scale

The technique of triggering a build to regenerate lollipop pages every time a new entry is created may not always be the best. While automation of builds means redeployment of sites is very simple, we may want to start limiting and optimizing things when we start to become very popular. (It's just a matter of time, right?)

It doesn't matter. Here are some things to consider when we are creating a lot of pages and adding content more frequently in the database:

  • Instead of triggering a rebuild for each new entry, we can rebuild the site into a scheduled job. Maybe this can happen hourly or once a day.
  • If built once a day, we may decide to generate pages only for new lollipops submitted in the past day and cache the pages generated every day for future use. This logic in the build will help us support a large number of lollipop pages without making the build too long. But I won't talk about in-build cache here. If you are curious, you can ask in the Netlify Community Forum.

By combining static pre-generated resources with serverless back-up solutions that provide dynamic rendering, we can meet a surprisingly wide range of use cases – while avoiding the need to configure and maintain a large number of dynamic infrastructure.

What other use cases can you use this "static first" approach to meet?

The above is the detailed content of Static First: Pre-Generated JAMstack Sites with Serverless Rendering as a Fallback. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

What is 'render-blocking CSS'? What is 'render-blocking CSS'? Jun 24, 2025 am 12:42 AM

CSS blocks page rendering because browsers view inline and external CSS as key resources by default, especially with imported stylesheets, header large amounts of inline CSS, and unoptimized media query styles. 1. Extract critical CSS and embed it into HTML; 2. Delay loading non-critical CSS through JavaScript; 3. Use media attributes to optimize loading such as print styles; 4. Compress and merge CSS to reduce requests. It is recommended to use tools to extract key CSS, combine rel="preload" asynchronous loading, and use media delayed loading reasonably to avoid excessive splitting and complex script control.

External vs. Internal CSS: What's the Best Approach? External vs. Internal CSS: What's the Best Approach? Jun 20, 2025 am 12:45 AM

ThebestapproachforCSSdependsontheproject'sspecificneeds.Forlargerprojects,externalCSSisbetterduetomaintainabilityandreusability;forsmallerprojectsorsingle-pageapplications,internalCSSmightbemoresuitable.It'scrucialtobalanceprojectsize,performanceneed

What is Autoprefixer and how does it work? What is Autoprefixer and how does it work? Jul 02, 2025 am 01:15 AM

Autoprefixer is a tool that automatically adds vendor prefixes to CSS attributes based on the target browser scope. 1. It solves the problem of manually maintaining prefixes with errors; 2. Work through the PostCSS plug-in form, parse CSS, analyze attributes that need to be prefixed, and generate code according to configuration; 3. The usage steps include installing plug-ins, setting browserslist, and enabling them in the build process; 4. Notes include not manually adding prefixes, keeping configuration updates, prefixes not all attributes, and it is recommended to use them with the preprocessor.

CSS Case Sensitivity: Understanding What Matters CSS Case Sensitivity: Understanding What Matters Jun 20, 2025 am 12:09 AM

CSSismostlycase-insensitive,butURLsandfontfamilynamesarecase-sensitive.1)Propertiesandvalueslikecolor:red;arenotcase-sensitive.2)URLsmustmatchtheserver'scase,e.g.,/images/Logo.png.3)Fontfamilynameslike'OpenSans'mustbeexact.

What is the conic-gradient() function? What is the conic-gradient() function? Jul 01, 2025 am 01:16 AM

Theconic-gradient()functioninCSScreatescirculargradientsthatrotatecolorstopsaroundacentralpoint.1.Itisidealforpiecharts,progressindicators,colorwheels,anddecorativebackgrounds.2.Itworksbydefiningcolorstopsatspecificangles,optionallystartingfromadefin

CSS tutorial for creating a sticky header or footer CSS tutorial for creating a sticky header or footer Jul 02, 2025 am 01:04 AM

TocreatestickyheadersandfooterswithCSS,useposition:stickyforheaderswithtopvalueandz-index,ensuringparentcontainersdon’trestrictit.1.Forstickyheaders:setposition:sticky,top:0,z-index,andbackgroundcolor.2.Forstickyfooters,betteruseposition:fixedwithbot

What is the scope of a CSS Custom Property? What is the scope of a CSS Custom Property? Jun 25, 2025 am 12:16 AM

The scope of CSS custom properties depends on the context of their declaration, global variables are usually defined in :root, while local variables are defined within a specific selector for componentization and isolation of styles. For example, variables defined in the .card class are only available for elements that match the class and their children. Best practices include: 1. Use: root to define global variables such as topic color; 2. Define local variables inside the component to implement encapsulation; 3. Avoid repeatedly declaring the same variable; 4. Pay attention to the coverage problems that may be caused by selector specificity. Additionally, CSS variables are case sensitive and should be defined before use to avoid errors. If the variable is undefined or the reference fails, the fallback value or default value initial will be used. Debug can be done through the browser developer

Unlock the Potential of CSS Animations: A Deep Dive Unlock the Potential of CSS Animations: A Deep Dive Jun 20, 2025 am 12:14 AM

CSSanimationsenhancewebpagesbyimprovinguserexperienceandsitefunctionality.1)Usetransitionsforsmoothstylechanges,asinthebuttoncolorexample.2)Employkeyframesfordetailedanimations,likethebouncingball.3)Ensureperformancebykeepinganimationssimpleandusingt

See all articles