二刷红宝书 -- 你真的懂script标签吗
📖阅读本文你学习到✨
- 灵活使用
<script>
标签 - 深入理解
async
、defer
、动态加载script
方式 - 行内script和外部script的比较
在日常开发中可能很少在html
里面写script
标签,一般都是vue
react
一把梭。很少看见script的身影
- vue3
<script setup>...</script>
- ts版本
<script setup lang='ts'>...</script>
- ts版本
- vue2中
<script> export default {...}</script>
- 函数式 react
export default function Demo(){... return <></>}
。
但是其实<script>
大有来头,搞不好还可以提高页面加载速度,提高输入延迟 (FID) ,首次绘制(FP)等性能指标
深入理解<script>
元素
script有8大属性可以供开发者可选,分别是async
,src
, crossorigin(CORS)
,defer
,integrity
,charset
,language
,type
。
其中language,charset,type很少使用,现代浏览器也会忽视这些属性,这里就不在赘述,主要围绕剩下的属性展开。
前置知识
-
使用script的方式
- 直接嵌入到网页中即在
html
写script
- 引入外部script文件 即
- 直接嵌入到网页中即在
-
浏览器解析
script
的顺序是按照页面出现的顺序解释,如果使用defer
或者async
属性另论,下面会解释 -
script
中的src
属性可以是外部域文件,同时你需要明白该域是个可信来源,Integerity属性是防范这种问题的一个武器 -
标签位置
- 如果将
script
元素放在页面的head
标签内 ,这就意味着要等head
所有的script
资源下载完全页面才能显示,在此期间浏览器窗口完全空白。 - 解决方法是 将
script
引用放在body
元素中的内容后面, 这样页面会在处理js代码之前完全渲染页面,白屏时间变短 用户替体验效果更好!
- 如果将
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script src="example1.js"></script>
<script src="example2.js"></script>
</head>
<body>
<!-- 这里是页面内容 -->
</body>
</html>
修改版如下
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
</head>
<body>
<!-- 这里是页面内容 -->
<script src="example1.js"></script>
<script src="example2.js"></script>
</body>
</html>
defer
概念
可选参数,表示脚本可以延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效。
主要作用:推迟执行脚本
<script defer>
表示脚本在执行的时候不会改变页面的结构,就相当于告诉浏览器立即下载,但延迟执行
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script defer src="example1.js"></script>
<script defer src="example2.js"></script>
</head>
<body>
<!-- 这里是页面内容 -->
</body>
</html>
<script defer>
执行时机- 因为加上
defer
属性,script
会在浏览器解析完html
标签之后执行 - script不一定会按顺序执行,也不一定会在
DOMContentLoaded
时间之前执行 - 最佳方案是把要推迟执行的脚本放在
body
元素中的内容后面
- 因为加上
- 作用对象
defer
属性只对外部script文件有效
async
概念
可选参数,表示应该立即开始下载脚本,但不能阻止其他页面动作,比如下载资源或等待其他脚本加载。只对外部脚本文件有效
主要作用: 异步执行脚本
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script async src="example1.js"></script>
<script async src="example2.js"></script>
</head>
<body>
<!-- 这里是页面内容 -->
</body>
</html>
- 执行顺序
- 不保证俩个
script
次序执行 - 但是会保证在页面的
load
事件之前进行,但可能会在DOMContentLoaded
之前或之后
- 不保证俩个
- 告诉页面不会使用
document.write
动态加载脚本
JavaScript
可以使用DOM API
,可以通过DOM
中动态添加script
元素同样可以加载制定脚本
let script = document.createElement('script')
script.src = 'demo.js'
document.head.appendChild(script)
- 需要注意的是
- 这种加载默认是异步的,你可以按需改成同步
script.async = false
- 这种方式对浏览器预加载器是不可见的,这会影响在资源获取队列中的优先级,可能会严重影响性能。解决办法是文档头部显示声明它们
- 这种加载默认是异步的,你可以按需改成同步
<link rel='preload' href='demo.js'>
行内代码和外部文件的比较
虽然可以直接在html
中写JavaScript
代码,但是最佳实践是引入外部文件,但也并不是强制性的规则,推荐的理由主要是俩个:
- 可维护性。类似于组件化思想, 把html中需要的
JavaScript
抽离出单独的文件,再按需引入,更容易后期维护 - 缓存。浏览器会更具体定的设置缓存所有外部链接的
JavaScript
文件,这意味着如果来个页面用到相同的文件也只需要下载一次,加载速度更快
参考
《JavaScript 高级程序设计 第四版》
转载自:https://juejin.cn/post/7278973100074762300