内联脚本_通过数据的异步内联脚本:URI

内联脚本

内联脚本

Inline scripts are synchronous. "Well, duh!" you may say. That's a feature, not a bug. Because accessing a variable after an inline script should succeed. And that's fine. But not great.

内联脚本是同步的。 “好吧,du!” 你可以这样说。 这是一个功能,而不是错误。 因为在内联脚本之后访问变量应该成功。 很好。 但不是很好。

When is this bad? Well, inline scripts cause stylesheets to be blocking. Wait, what? Steve explained it 10 years ago, and it's still relevant today. Allow me to demonstrate.

什么时候不好? 好吧,内联脚本会导致样式表被阻塞。 等一下史蒂夫(Steve)于10年前进行了解释,直到今天仍然有用。 请允许我示范。

基线 (The baseline)

Say we have:

说我们有:

  • CSS1 artificially delayed to take 5 seconds to load

    人为延迟CSS1加载需要5秒
  • External async JS1 that loads fine and prints to the console

    外部异步JS1,可以正常加载并打印到控制台
  • CSS2 that takes 10 seconds to load

    加载CSS2需要10秒
  • External async JS2

    外部异步JS2
  <link rel="stylesheet" href="css1.css.php" type="text/css" />
  <script src="js1.js" async></script>
  <link rel="stylesheet" href="css2.css.php" type="text/css"/>
  <script src="js2.js" async></script>

What we have is a waterfall like this:

我们拥有的是这样的瀑布:

... and in the console (where we log DOMContentLoaded and onload too) you see that even though CSS takes forever to load, it only blocks onload. The external JS execution is just fine.

...并且在控制台(我们也记录DOMContentLoadedonload的控制台)中,您可以看到,即使CSS永远需要加载,它也只会阻止onload 。 外部JS执行就可以了。

The test file is here

测试文件在这里

添加内联脚本(Add inline scripts)

Now what happens when you add an inline script after each external JS? Code:

现在,当在每个外部JS之后添加内联脚本时会发生什么? 码:

  <link rel="stylesheet" href="css1.css.php" type="text/css" />
  <script src="js1.js" async></script>
  <script>console.log('inline script 1 ' + (+new Date - start));</script>
  <link rel="stylesheet" href="css2.css.php" type="text/css"/>
  <script src="js2.js" async></script>
  <script>console.log('inline script 2 ' + (+new Date - start));</script>

Test page

测试页

Now the first external async JS runs fine, but then the inline script and the second external JS are delayed by the slowness of the first CSS file. That's not good. The second inline script is blocked by the second even slower CSS. (And if there were more external JS files they'd be blocked too). DOMContentLoaded is blocked too.

现在,第一个外部异步JS运行良好,但是内联脚本和第二个外部JS由于第一个CSS文件的缓慢而延迟。 这不好。 第二个内联脚本被第二个甚至更慢CSS阻止。 (如果还有更多外部JS文件,它们也会被阻止)。 DOMContentLoaded也被阻止。

external script 1 87
inline script 1 5184
external script 2 5186
inline script 2 10208
DOMContentLoaded 10216
onload 10227

There's a good reason why browsers do this, e.g. the inline script may request layout info and for that to work, the CSS must be downloaded and applied. But it's less than perfect.

浏览器这样做是有充分的理由的,例如,内联脚本可能会请求布局信息,并且要使其正常工作,必须下载并应用CSS。 但这还不完美。

动机 (Motivation)

Why is this an issue? Can you just ditch inline scripts, if they make your execution slower. Well that's not always an option. Maybe you need some work that only the server can do (or it's better done by the server) and then made available on the client side. Maybe you want to add a third-party snippet to the page, social buttons, analytics and such. Do you add these at the top before any links? That means potentially slowing down your app's scripts. Do you move them to the very bottom? Maybe better, if that's even an option, but they still block. No matter what comes between a link and an inline script, the blocking behavior still exists.

为什么这是一个问题? 如果它们使您的执行速度变慢,您是否可以抛弃内联脚本。 嗯,这并不总是一种选择。 也许您需要做一些只有服务器才能完成的工作(或者最好由服务器来完成),然后再在客户端进行。 也许您想向页面,社交按钮,分析等添加第三方代码段。 您是否将这些添加在任何link之前的顶部? 这意味着可能会减慢您应用程序的脚本。 您将它们移到最底端吗? 也许更好,即使那是一个选择,但它们仍然会阻塞。 无论link和内联script之间是什么,阻止行为仍然存在。

So how do you prevent the inline scripts from blocking?

那么如何防止内联脚本阻塞?

外化 (Externalize)

If only there was a way to make an inline script appear external to the browser... But yes - make the src point to a data: URI. Doesn't need to be base64-encoded either.

如果只有一种方法可以使内联脚本显示在浏览器外部...但是,是的-使src指向data: URI。 也不需要进行base64编码。

So you take this:

因此,您可以这样做:

<script>console.log('inline script 1 ' + (+new Date - start));</script>

... and turn it into this:

...并将其转换为:

<script async src="data:text/javascript,console.log%28%27inline%20script%201%20%27%20%2B%20%28%2Bnew%20Date%20-%20start%29%29%3B"></script>

Test page

测试页

And voila! No more blocking! Sync becomes async! Everybody dance!

瞧! 不再受阻! 同步变得异步! 大家跳舞!

inline script 1 2
inline script 2 4
DOMContentLoaded 10
external script 1 271
external script 2 277
onload 10270

Looks weird, but hey, it works! And there days learning from view:source is almost impossible anyway.

看起来很奇怪,但是,嘿! 而且,有很多天从视图中学习:无论如何,几乎不可能获得源代码。

笔记 (Notes)

I tested this hack in Chrome (Mac/PC), Firefox (Mac/PC), Safari (Mac), Edge (PC). Works everywhere except Edge. Oh well, at least it behaves as if nothing was changed, so it doesn't hurt Edge.

我在Chrome(Mac / PC),Firefox(Mac / PC),Safari(Mac),Edge(PC)中测试了这种黑客攻击。 除了Edge,其他任何地方都可以使用。 哦,好吧,至少它的行为就像什么都没有改变一样,因此不会损害Edge。

Couple of alternative approaches that didn't work for me were:

几种对我不起作用的替代方法是:

  • adding defer to the inline script. Steve suggests in his post that it used to work in Firefox 3.1 and some old IE. Not anymore though.

    defer添加到内联脚本中。 史蒂夫(Steve)在他的帖子中建议它曾经在Firefox 3.1和某些旧版IE中运行。 虽然没有了。

  • adding async to the inline script - it's not allowed, but didn't hurt to try

    async联脚本添加async -不允许,但尝试时不会受到伤害

Thank you all for reading and go externalize!

谢谢大家阅读并外在化!

Tell your friends about this post on Facebook and Twitter

FacebookTwitter上告诉您的朋友有关此帖子的信息

翻译自: https://www.phpied.com/asynchronous-inline-scripts-via-data-urls/

内联脚本

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值