每个开发工具公司和团队似乎都假设初级开发人员熟悉这些术语。
当我开始编码时,我到处都看到它们:Nuxt 是一个 SSR 框架,你可以使用 Gatsby 进行 SSG,如果你在 next.config.js 中设置这个或那个标志,你可以启用 SPA 模式。
什么鬼?
作为第一步,这里有一个术语表 - 尽管它不会帮助您理解详细信息:
接下来,让我们为黑暗带来一些光明。
最初,网站是您从服务器请求的 HTML 文件。
你的浏览器会询问服务器,“嘿,你能把那个/about页面递给我吗?”服务器将响应一个 about.html 文件。您的浏览器知道如何解析所述文件并呈现一个漂亮的网站,例如这个。
我们将这样的服务器称为静态网络服务器。开发人员手动编写 HTML 和 CSS(可能还有一点 JS),将其保存为文件,将其放入文件夹中,然后服务器根据请求交付它。没有特定于用户的内容,只有每个人都可以访问的通用、静态(不变)内容。
app.get('/about', async (_, res) => { const file = fs.readFileSync('./about.html').toString(); res.set('Content-Type', 'text/html'); res.status(200).send(file); })
然而,静态网站很无聊。
如果用户能够与网站互动,那么对用户来说会更有趣。因此,开发人员使之成为可能:只需一点 JS,她就可以单击按钮、展开导航栏或过滤搜索结果。网络变得互动起来。
这也意味着 /search-results.html 页面将包含不同的元素,具体取决于用户作为搜索参数发送的内容。
因此,用户将在搜索栏中输入内容,按 Enter 键,然后将带有搜索参数的请求发送到服务器。接下来,服务器将从数据库中获取搜索结果,将其转换为有效的 HTML,并创建完整的 /search-results.html 文件。用户收到了结果文件作为响应。
(为了简化创建特定于请求的 HTML,开发人员发明了 HTML 模板语言,例如 Handlebars。)
app.get('/search-results', async (req, res) => { const searchParams = req.query.q; const results = await search(searchParams); let htmlList = '<ul>'; for (const result of results) { htmlList += `<li>${result.title}</li>`; } htmlList += '</ul>'; const template = fs.readFileSync('./search-results.html').toString(); const fullPage = embedIntoTemplate(htmlList, template); res.set('Content-Type', 'text/html'); res.status(200).send(fullPage); });
在很长一段时间里,我发现这个术语渲染非常令人困惑。
在其原始含义中,渲染描述了计算机创建人类可处理的图像。例如,在视频游戏中,渲染指的是每秒创建 60 个图像的过程,用户可以将其作为引人入胜的 3D 体验来消费。我想知道,已经听说过服务器端渲染,它是如何工作的 - 服务器如何渲染图像供用户查看?
但事实证明,我意识到这有点太晚了,服务器端或客户端渲染上下文中的“渲染”意味着不同的事情。
在浏览器上下文中,“渲染”保持其原始含义。浏览器确实渲染图像供用户查看(网站)。为此,需要一个最终结果的蓝图。该蓝图以 HTML 和 CSS 文件的形式出现。浏览器将解释这些文件并从中派生出模型表示形式,即文档对象模型 (DOM),然后可以渲染和操作该模型。
让我们将其映射到建筑物和架构上,以便我们可以更好地理解它:有一个房子的蓝图(HTML 和 CSS),建筑师将其转换为他办公桌上的小型物理模型(DOM),这样他可以操纵它,当每个人都同意结果时,建筑工人会查看模型并将其“渲染”成实际的建筑物(用户看到的图像)。
但是,当我们在服务器上下文中谈论“渲染”时,我们谈论的是创建,而不是解析 HTML 和 CSS 文件。首先完成此操作,以便浏览器可以接收要解释的文件。
转向客户端渲染,当我们谈论“渲染”时,我们指的是操作 DOM(浏览器通过解释 HTML 和 CSS 文件创建的模型)。然后浏览器将 DOM 转换为人类可见的图像。
随着 Facebook 等平台的兴起,开发者需要更多、更快的交互性。
在交互式网络应用程序中处理按钮点击需要时间 - 必须创建 HTML 文件,必须通过网络发送它,并且用户的浏览器必须呈现它。
All that hassle while the browser could already manipulate the website without requesting anything from the server. It just needed the proper instructions — in the form of JavaScript.
So that's where devs placed their chips.
Large JavaScript files were written and sent to the users. If the user clicked on a button, the browser would insert an HTML component; if the user clicked a "show more" button below a post, the text would be expanded — without fetching anything.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="root"></div> <script> document.addEventListener('DOMContentLoaded', () => { const root = document.getElementById('root'); root.innerHTML = ` <h1>Home</h1> <button>About</button> `; const btn = document.querySelector('button'); btn.addEventListener('click', () => { root.innerHTML = ` <h1>About</h1> `; }); }); </script> </body> </html>
Though the code snippet suggests the opposite, developers didn't write vanilla JavaScript.
Ginormous web apps like Facebook had so much interactivity and duplicate components (such as the infamous Like-button) that writing plain JS became cumbersome. Developers needed tools that made it simpler to deal with all the rendering, so around 2010, frameworks like Ember.js, Backbone.js, and Angular.js were born.
Of them, Angular.js was the one that brought Single Page Applications (SPAs) into the mainstream.
An SPA is the same as Client-Side Rendering, but it is taken a step further. The conventional page navigation, where a click on a link would fetch and render another HTML document, was taken over by JavaScript. A click on a link would now fire a JS function that replaced the page's contents with other, already preloaded content.
For this to work properly, devs needed to bypass existing browser mechanisms.
For example, if you click on a
Devs invented all kinds of hacks to bypass this and other mechanisms, but discussing those hacks is outside the scope of this post.
So what were the issues with that approach?
SEO and Performance.
First, if you look closely at the above HTML file, you'll barely see any content in the
tags (except for the script). The content was stored in JS and only rendered once the browser executed the