在服务器端渲染 javascript。好主意还是坏主意?

发布于 2024-09-01 14:37:28 字数 1294 浏览 3 评论 0原文

现在是社区 wiki!

我想首先澄清:这不是与服务器端 Javascript 或运行 Javascript 服务器端相关的问题。这是一个关于从服务器端代码呈现 Javascript 代码(将在客户端执行)的问题。

话虽如此,还是以下面的 ASP.net 代码为例:

hlRemoveCategory.Attributes.Add("onclick", "return confirm('Are you sure you want to delete this?');")

这是在服务器端规定客户端 onclick 事件。

与在客户端编写 Javascript 相反:

$('a[rel=remove]').bind('click', function(event) {
    return confirm('Are you sure you want to delete this?');
}

现在我想问的问题是从服务器端代码渲染 javascript 有什么好处?或者反之亦然?

我个人更喜欢将客户端 UI/行为连接到 HTML 元素的第二种方式,原因如下:

  • 服务器端已经完成了它需要做的事情,包括数据验证、事件委托等; 服务器端所看到的事件
  • 不一定与客户端上的过程相同。即,客户端有更多的事件(只需查看自定义事件);在
  • 事件期间,客户端和服务器端发生的事情可能是完全不相关和解耦的;并且
  • 客户端发生的事情都发生在客户端,服务器不需要知道。服务器应该处理并运行提供给他们的内容,在发生客户端事件时,该过程如何发挥作用并不真正由他们决定;等等。

这些显然是我的想法。我想知道其他人的想法以及是否有关于此主题的任何讨论。

从这个论点分支的主题可以达到:

  • 代码管理:从服务器端渲染所有内容是否更容易?
  • 关注点分离:如果客户端逻辑与服务器端逻辑分离是不是更容易?
  • 效率:编码和运行哪个更高效?

归根结底,我正在努力让我的团队转向第二种方法。队里有很多老家伙都害怕这种变化。我只是想用正确的事实和统计数据说服他们。

让我知道你的想法。

更新1:看来我们所有参与这篇文章的人都有共同的想法;很高兴知道还有其他人有同样的想法。现在去说服大家;)谢谢大家。

Now a community wiki!

I want to make it clear first: This isn't a question in relation to server-side Javascript or running Javascript server side. This is a question regarding rendering of Javascript code (which will be executed on the client-side) from server-side code.

Having said that, take a look at below ASP.net code for example:

hlRemoveCategory.Attributes.Add("onclick", "return confirm('Are you sure you want to delete this?');")

This is prescribing the client-side onclick event on the server-side.

As oppose to writing Javascript on the client-side:

$('a[rel=remove]').bind('click', function(event) {
    return confirm('Are you sure you want to delete this?');
}

Now the question I want to ask is: What is the benefit of rendering javascript from the server-side code? Or the vice-versa?

I personally prefer the second way of hooking up client-side UI/behaviour to HTML elements for the following reasons:

  • Server-side does what ever it needs to already, including data-validation, event delegation and etc; and
  • What server-side sees as an event is not necessarily the same process on the client-side. i.e., there are plenty more events on client-side (just look at custom events); and
  • What happens on client-side and on server-side, during an event, could be completely irrelevant and decoupled; and
  • What ever happens on client-side happens on client-side, there is no need for the server to know. Server should process and run what is given to them, how the process comes to life is not really up to them to decide in the event of the client-side events; and so on and so forth.

These are my thoughts obviously. I want to know what others think and if there has been any discussions on this topic.

Topics branching from this argument can reach:

  • Code management: is it easier to render everything from server-side?
  • Separation of concern: is it easier if client-side logic is separated to server-side logic?
  • Efficiency: which is more efficient both in terms of coding and running?

At the end of the day, I am trying to move my team to go towards the second approach. There are lot of old guys in this team who are afraid of this change. I just wish to convince them with the right facts and stats.

Let me know your thoughts.

UPDATE1: It looks like all of us who have participated in this post have common thought; Good to know that there are others who think alike. Now to go convince the guys ;) Thanks everyone.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

森林散布 2024-09-08 14:37:28

您的第二个示例远远优于第一个示例。 JavaScript 是你的行为层,应该与你的语义标记(内容)和 CSS(表示)分开。这是更好的架构有很多原因:

  • 鼓励渐进增强。正如您提到的,后端代码应该在没有 JS 的情况下正常工作。您不能依赖您的客户提供可用的 JS。这样,您无需 JS 即可构建一次,然后可以增强使用 JS 的体验(例如,通过添加客户端验证和服务器端验证,以便客户端可以获得即时反馈)
  • 。通常会减少下载大小。单独的 JS 文件中的一个可重用选择器可以在页面之间缓存和共享,而不是每个元素上的处理程序。
  • 您所有的 JS 都集中在一个可重复使用的地方。例如,如果您的代码打开一个弹出窗口,并且您决定更改窗口的尺寸,您将在 JS 文件的代码中更改一次,而不是必须在每个单独的内联处理程序上更改它。

还有很多其他参数和原因,但它们应该让您开始...

另外,从您的示例来看,您的文档中似乎有一个可以删除内容的正常链接。这也是一个不好的做法。任何删除或更新内容的操作都应该在 POST(而不是 GET)请求上完成。所以应该是提交表单的结果。否则,例如,Googlebot 可能会通过抓取您的页面来意外删除您的所有内容(并且搜索引擎机器人不会执行 JS,因此您的警报不会有帮助)

Your second example is vastly superior to the first example. Javascript is your behaviour layer and should be separate from your semantic markup (content) and CSS (presentation). There are a number of reasons this is better architecture:

  • Encourages progressive enhancement. As you mentioned, the backend code should work correctly in the absence of JS. You cannot rely on your clients having JS available. This way you build it once without JS and then can enhance the experience for those with JS (e.g. by adding clientside validation as well as serverside validation so that the client can get instant feedback)
  • Cleaner markup. Normally reduced download size. One reusable selector in a separate JS file that can be cached and shared between pages vs. a handler on each element.
  • All of your JS in one re-used place. e.g. if your code was opening a popup window and you decided to change the dimensions of the window you would change it once in the code in the JS file vs. having to change it on every individual inline handler.

There are lots of other arguments and reasons but they should get you started...

Also, from your example it appears that you have a normal link in your document which can delete content. This would also be a bad practice. Anything that deletes or updates content should be done on a POST (not GET) request. So it should be the result of submitting a form. Otherwise e.g. googlebot could accidentally delete all of your content by just crawling your page (and search engine robots don't execute JS so your alert wouldn't help there)

地狱即天堂 2024-09-08 14:37:28

我能想到的两个最大的区别是:

  • 如果javascript位于单独的js文件中,您将失去客户端缓存,
  • 如果您需要更改javascript,则必须重新编译(将其推断为发布产品后会发生的情况:如果必须重新编译,则需要重新分发二进制文件而不仅仅是修改后的 js 文件)
  • 如果 javascript 位于单独的文件中,则使用 VS 调试器会更容易;您可以在该文件中设置一个断点,如果您正在生成代码服务器端,则必须使用运行文档功能,找到生成的代码,然后添加断点,并且每次重新启动时都必须手动添加该断点- 运行您的应用程序。接下来,如果代码位于单独的文件中,那么您只需调整 javascript 代码,F5 浏览器页面,即可继续调试,而无需停止并重新启动调试器。

应该提到的是,有时您必须从服务器插入 js 代码 - 例如,如果您的大部分代码位于单独的 js 文件中,并且您需要将控件标识插入到页面中以便该代码可以使用。如果可能的话,尽量避免这种情况。

The two biggest differences i can think of up front are:

  • you lose the client side caching you would get if the javascript was in a separate js file
  • if you need to change your javascript, you have to recompile (extrapolate this to what happens after you have released your product: if you have to recompile then you need to redistribute binaries instead of just a modified js file)
  • it is easier to use the VS debugger if the javascript is in a separate file; you can just set a break point in that file, if you are generating the code server side then you have to use the running documents feature, find your generated code and then add the breakpoint, and that breakpoint has to be manually added everytime you re-run your app. Following on from that, if the code is in a separate file, then you can just make your tweak to the javascript code, F5 your browser page, and keep on debugging without having to stop and restart the debugger.

It should be mentioned that sometimes you have to insert js code from the server - for example if the bulk of your code is in a separate js file and you need to insert control identities in to the page for that code to work with. Just try to avoid that situation if possible.

秋风の叶未落 2024-09-08 14:37:28

看起来你已经知道该怎么做了。在服务器端渲染它是一个坏主意。

简单的推理是你的 Javascript 既存在于服务器端页面上,也存在于单独的 Javascript 文件中(假设你正在使用 Javascript)。当一切都无处不在时,修复问题可能会成为调试噩梦。

除了服务器端脚本生成的内容之外,如果您没有使用任何其他 Javascript,它可能会很好且易于管理(忘记不引人注目的运动所说的内容)。

其次,如果页面上有 100 个链接,您将在 100 个地方重复相同的代码。重复是另一个维护和调试的噩梦。您可以使用一个事件处理程序和一个属性来处理所有页面上的所有链接。这甚至不需要再考虑一下。

分离 HTML 和 Javascript,甚至 CSS 并不容易,特别是如果您想要一些 AJAX 或 UI 的优点。为了实现完全分离,我们必须转向桌面应用程序模型,其中所有前端代码都是使用 Javascript 在客户端以编程方式生成,并且所有与服务器仅限于纯粹的数据交换。

大多数上游通信(客户端到服务器)已经只是数据交换,而不是下游通信。许多服务器端脚本生成 HTML,将其与数据合并然后将其返回。只要服务器负责生成 HTML 视图就可以了。但是,当精美的 Javascript 加入并开始将行附加到表中,并通过精确复制现有的 HTML 结构来添加注释的 div 时,我们就创建了两个生成标记的点。

$(".comments").append($("<div>", {
    "id": "123",
    "class": "comment",
    "html": "I would argue this is still bad practice..."
}));

也许这不是一场大噩梦(取决于规模),但它也可能是一个严重的问题。现在,如果我们更改注释的结构,则需要在两个位置进行更改 - 最初生成内容的服务器端脚本和模板,以及在页面加载后动态添加注释的 Javascript 端。

第二个例子是关于使用拖拽的应用程序。如果您可以在页面周围拖动 div,则需要将它们从常规页面流中取出,并使用精确坐标进行绝对或相对定位。现在,由于我们无法预先为所有可能的坐标创建类(尝试这样做是愚蠢的),所以我们基本上直接在元素中注入样式。我们的 HTML 看起来像:

..

我们已经搞砸了我们美丽的语义页面,但这是必须要做的。

撇开语义和行为分离不谈,我想说基本上可以归结为重复。您是否不必要地重复代码?多个层处理相同的逻辑吗?是否可以将所有内容都推入单个层,或者减少所有重复。

Looks like you already know what to do. Rendering it on the server side is a bad idea.

The simple reasoning being you're Javascript lives both on the server side pages as well as in separate Javascript files (assuming you are using Javascript at all). It can become a debugging nightmare to fix things when everything is everywhere.

Were you not using any other Javascript besides what the server side scripts generate, it would probably be fine and manageable (forget what the unobtrusive movement says).

Secondly, if you have 100 links on the page, you will be repeating that same code in 100 places. Repetition is another maintenance and debugging nightmare. You can handle all links on all pages with one event handler and one attribute. That doesn't even need a second thought.

<Rant>

It's not easy to separate HTML and Javascript, and even CSS especially if you want some AJAX or UI goodness. To have total separation we would have to move to a desktop application model where all the front-end code is generated on the client side programmatically using Javascript, and all interaction with the server gets limited to pure data exchange.

Most upstream communication (client to server) is already just data exchange, but not the downstream communications. Many server-side scripts generate HTML, merge it with data and spit it back. That is fine as long as the server stays in command of generating the HTML views. But when fancy Javascript comes onboard and starts appending rows to tables, and div's for comments by replicating the existing HTML structure exactly, then we have created two points at which the markup gets generated.

$(".comments").append($("<div>", {
    "id": "123",
    "class": "comment",
    "html": "I would argue this is still bad practice..."
}));

Maybe this is not as big a nightmare (depending on the scale), but it can be a serious problem too. Now if we change the structure of the comments, the change needs to be done at two places - the server side script and templates where content is initially generated, and the Javascript side which dynamically adds comments after page load.

A second example is about applications that use drag and drag. If you can drag div's around the page, they would need to be taken off the regular page flow, and positioned absolutely or relatively with precise coordinates. Now since we cannot create classes beforehand for all possible coordinates (and that would be stupid to attempt), we basically inject styles directly in the element. Our HTML then looks like:

<div style="position: absolute; top: 100px; left: 250px;">..</div>

We have screwed up our beautiful semantic pages, but it had to be done.

</Rant>

Semantic, and behavioral separation aside, I would say is basically boils down to repetition. Are you repeating the code unnecessarily. Are multiple layers handling the same logic. Is it possible to shove all of it into a single layer, or cut down on all repetition.

触ぅ动初心 2024-09-08 14:37:28

您和回答该问题的其他人已经列出了为什么最好不要让服务器端代码将内部事件属性吐入文档的原因。

硬币的另一面是这样做快速并且简单(至少在短期内)。

IMO,这并没有抵消这种方法的缺点,但这是一个原因。

You and the other people answering the question have already listed reasons why it is better not to having the server side code spit intrinsic event attributes into documents.

The flip side of the coin is that doing so is quick and simple (at least in the short term).

IMO, this doesn't come close to outweighing the cons of the approach, but it is a reason.

简单 2024-09-08 14:37:28

对于您示例中的代码来说,这并不重要。该代码不使用仅在服务器端可用的任何信息,因此在客户端代码中绑定事件同样容易。

有时您想要使用服务器端可用的一些信息来决定是否应添加事件,或者为事件创建代码,例如:

if (categoryCanBeDeleted) {
  hlRemoveCategory.Attributes.Add(
    "onclick",
    "return confirm('Are you sure you want to delete the " + categoryType + "?');"
  );
}

如果您要在客户端执行此操作,则必须以某种方式将此信息放入页面中,以便客户端代码也可以访问它。

For the code in your example it doesn't really matter. The code isn't using any information that is only available at the server side, so it's just as easy to bind the event in client side code.

Sometimes you want to use some information that is available at the server side to decide whether the event should be added or not, or to create the code for the event, for example:

if (categoryCanBeDeleted) {
  hlRemoveCategory.Attributes.Add(
    "onclick",
    "return confirm('Are you sure you want to delete the " + categoryType + "?');"
  );
}

If you would do this at the client side, you have to put this information into the page somehow so that the client side code also has access to it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文