延迟加载 JavaScript 和内联 JavaScript
我注意到在我的网站(用于工作)的 中,有很多
和
标记。还有更多的 JavaScript/CSS 文件仅针对特定页面加载(我们使用 CodeIgniter,并且文件路径传递到标头视图)。
我正在考虑使用条件/异步加载器(例如 yepnope.js、head.js 等),但我注意到这样做有一个小问题。
在我们看来,存在内联 JavaScript,有些使用 $(function(){})
,有些使用 $(document).ready(function(){})
,并且有些只是有代码(使用 jQuery)不在 ready
块中。
如果不编辑每个视图文件以将其代码包装在函数中并在加载 JS 文件时调用该函数,是否有办法延迟内联代码,直到异步加载 JavaScript?
I noticed in the <head>
of my site (for work), there are a lot of <link rel="stylesheet" type="text/css" href="" />
and <script type="text/javascript" src="">
tags. There are even more JavaScript/CSS files that are only loaded for specific pages (we're using CodeIgniter, and the file paths are passed to the header view).
I was considering using a conditional/asynchronous loader (eg. yepnope.js, head.js, etc.), but I noticed a small problem with doing this.
In our views, there is inline JavaScript, some uses $(function(){})
some uses $(document).ready(function(){})
, and some just has code (using jQuery) that's not in a ready
block.
Without editing EVERY view file to wrap its code in a function and calling that when the JS files are loaded, is there a way to delay the inline code until the JavaScript is asynchronously loaded?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
你实际上可以延迟加载内联 javascript:
1-将内联脚本中的类型参数更改为:text/delayscript
FROM
To
为脚本标签提供自定义 Mime 类型 text/delayscript 强制浏览器忽略其内容(请注意,完全忽略它将默认为 text/javascript) 。
2-延迟加载所有内联脚本
一旦 Heads.js(或您可能正在使用的其他框架)确认它延迟加载了所有外部 JS,您就可以获取所有自定义脚本标签的内容并将它们注入页面中:
为了更加优雅,您实际上可以将内联脚本保留在 DOM 树中的原始层次结构中,而不是像我上面所建议的那样将所有内容都塞在一个脚本中,方法是将标记的内联脚本标记替换为具有以下内容的新标记: mime 类型文本/javascript:
You can actually lazyload inline javascript:
1- Change the type parameter in the inline script to: text/delayscript
FROM
To
Giving the script tag a custom Mime type text/delayscript forces the browser to ignore its content (Please note that leaving it out entirely will default to text/javascript).
2- Lazy load all inline scripts
Once heads.js (Or an other framework you might be using) confirms that it lazy loaded all your external JS, you can then grab the content of all your custom script tags and inject them in the page:
To be even more graceful, you can actually keep the inline scripts in their original hierarchy in the DOM tree instead of jamming all their content in one script, as I have suggested above, by replacing the marked inline script tag by a new one that has mime type text/javascript:
您必须考虑将内联代码移至“外部”并将其包含在
You have to consider moving inline code "outside" and include it with
HTML5 引入了新的
异步
具有已定义src
的脚本的参数。您可以将其直接添加到任何
元素上:
但是:请记住,它不适用于内联脚本!
如果您的某些页面混合了外部脚本和内联脚本,如果您异步加载外部脚本,则意味着内联脚本实际上将在异步脚本之前执行...这可能会产生不良影响。
例如,如果您有以下配置:
HTML5 introduced a new
async
parameter for scripts having a definedsrc
.You can add it directly on any
<script>
element :BUT : keep in mind that it will not work on inline scripts!
And if your some of your pages mix either external and inline scripts, if you load the external asynchronously, it means that the inline scripts will actually be executed before the asynchronous ones... Which can have unwanted effects.
For instance, if you have the following configuration :
首先,我建议您非常仔细地分析客户端脚本的加载,不仅是第一次 JavaScript 加载,还包括第二次加载相同的 JavaScript 文件或在另一个页面上加载。如果 Web 服务器在脚本上正确设置了 ETag,或者如果您使用 HTTP 的其他缓存选项(请参阅 缓存教程了解详细信息)对于 JavaScript 文件来说,不会加载文件本身,只会进行缓存重新验证。因此,您所描述的问题可能并不像看起来那么重要。
如果您决定动态加载一些脚本,您可以使用 jQuery.getScript 并放置所有依赖项
success
回调中的代码。如果您需要加载一两个 JavaScript 文件,这种方式会非常有效,但如果您需要加载具有更复杂依赖关系的 JavaScript 文件列表,那么实现可能就不那么容易了。在这种情况下,您可以在内部使用
document.writeln
。在内部使用该方法几乎没有任何缺点(请参阅此处了解细节)。
First of all I would recommend you to analyse the loading of the scripts on the client side very carefully and not only for the first JavaScript loading, but on the loading of the same JavaScript files at the second time or its loading on another page. If the ETag are correctly set on the scripts by the web server or if you use other caching options of HTTP (see the caching tutorial for details) for the JavaScripts files than no loading of the files itself will take place and only the cache revalidation will be done. So it can be that the problem which you describes is not so important like it looks like.
If you do decide to load some scripts dynamically you can use jQuery.getScript and place all dependent code inside of the
success
callback. If you need to load one or two JavaScript files the way will work very good, but if you need to load a list of JavaScript files with more complex dependency the implementation could be not so easy. In the case you can usedocument.writeln
inside of<head>
. The usage of the method inside of<head>
has almost no disadvantages (see here for details).根据您的设置,您可能需要查看 www.cloudflare.com 上的服务。他们当前的测试版功能称为火箭装载机,正是这样做的,包括内联脚本。
这是一项免费服务。尝试一下;)
另外,您还可以在顶部获得免费的缓存代理:)
Depending on your setup, you might want to look into the service from www.cloudflare.com. Their current beta functionality called rocket loader, does exactly that, including the inline scripts.
It's a free service. try it out ;)
Plus you get a free caching proxy on top :)
创建内联函数而不是内联脚本。然后在 javascript 文件的末尾,调用该函数(如果存在)。
在串联的 jquery+etc 异步 javascript 文件中:
您必须进行一些改组,以确保每页只有一个 inline_script,或者如果您多次调用它,则使用某种缓存将它们放在一起。
尽管这个问题已经很老了,但在当今时代这仍然是一个有趣的问题,异步脚本=非常棒
Instead of inline scripts, create inline functions. Then at the end of your javascript file, call the function if it exists.
Inside your concatenated jquery+etc async javascript file:
You'll have to do some shuffling to make sure you only have one inline_script per page, or use some kind of caching to put them together if you call it more than once.
It's still a fun problem in the current age even though this question is old, async scripts = pretty awesome
看看如何使用 headjs。这是一个很好的轻量级库,可以为您完成这一切。
Have a look at using headjs. It is a nice lightweight library that will do this all for you.