六、前端运行环境

169 阅读4分钟

1.JS上线之后在什么哪里运行?

1.运行环境即浏览器 (server端有nodejs)
2.下载网页代码,渲染出页面,期间会执行若干JS
3.保证代码在浏览器中: 稳定高效

2.网页是如何加载并渲染出来的

1.加载资源的形式

html代码
媒体文件,图片视频
JavaScript,css

2.加载资源的过程

1.DNS(Domid name server)解析: `域名`变为----> `IP地址`
2.浏览器根据IP地址向服务器发起http请求
3.服务器处理http请求,并返回给浏览器

3.渲染页面的过程

1.根据HTML代码生成DOM Tree
2.根据CSS 代码生成CSSOM
3.将DOM Tree 和 CSSOM 整合行程 Render Tree(渲染树)
4.遇到script则暂停渲染,优先加载并执行JS代码,完成再继续
5.直至吧Render Tree 渲染完成

3.网页加载和渲染的示例

为什么把css放在head中呢?

  • 很简单,在执行渲染DOM的时候突然跳出来一个css样式,你本来的css样式就是默认,如果突然插入css样式文件,突然变成40px,会发生什么,这就是问题所在

为什么把js放在最后?

  • 为了让用户先看到页面加载出来
示例一    // 根据html生成Dom树
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>webpack</title>
    </head>
    <body>p</body>
</html>

示例二    // 页面加载完要先执行css,css存放在head中先执行 
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>webpack</title>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <div>test</div>
    </body>
</html>

示例三  // 请把js放到最后执行 因为js会阻塞渲染过程,导致后续DOM无法加载,页面显示不全
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>webpack</title>
    </head>
    <body>
        <div>test</div>
        <script src="./index.js"></script>
        <div>test</div>
    </body>
</html>

示例四  // 渲染DOM之后 再渲染图片,并且不会停止
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>webpack</title>
    </head>
    <body>
        <div>test</div>
        <p><img src="./1.png" /></>
        <div>test</div>
    </body>
</html>

4.网页加载和渲染相关的面试题

window.onloaddDOMContentLoaded的区别?
    window.onload 资源全部加载完之后才能执行,包括图片
    DOMContentLoaded DOM 渲染完成即可,图片可能还没有下载

5.前端性能优化有哪些方式

性能优化原则

  • 多使用内存,缓存或其他方法
  • 减少CPU计算量,减少网络加载耗时
  • 适用于所有编程的性能优化--------空间换时间
1.让加载更快
    减少资源体积: 压缩代码
    减少访问次数: 合并代码,SSR服务端渲染,缓存
    使用更快的网络: CDN
2.让渲染更快
    CSS放在head中, JS放在boay最下面
    尽早开始执行JS,用DOMContentLoaded 触发
    懒加载(图片懒加载,上滑加载更多)
    对DOM查询进行缓存
    频繁DOM操作,合并到一起插入DOM结构
    节流throttle 防抖debounce

6.前端性能优化的示例

![图片转存失败,建议将图片保存下来直接上传
        资源合并
    <script src="a.js"></script>
    <script src="b.js"></script>
    <script src="c.js"></script>
    <script src="assign.js"></script>  // 与其请求三次资源,不如合并为一个
缓存
    1.在webpack配置时候,静态资源加hash后缀,根据文件内容计算hash
    2.文件内容不变,hash不变,url就不变
    3.url和文件不变,则会自动触发http缓存机制,返回304 
CDN 
    像一些css,js使用cdn, 可以大大提高访问速度
SSR
    服务端渲染: 将网页和数据一起渲染一起加载
    非SSR(前后端分离): 先加载网页,再加载数据,再渲染数据

7.手写防抖 debounce

  • 监听一个输入框的,文字变化后触发change事件
  • 直接用keyup 事件,则会频繁触发change事件
  • 防抖: 用户输入结束或者暂停的时候,才会触发change时间
<input id="input1" type="text">
<script>
    const input = document.getElementById('input1')
    let timer = null;
    input.addEventListener('keyup', () => {
        if (timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(() => {
            // 模拟触发 change事件
            console.log(input.value)
            // 清空定时器
            timer = null
        }, 500)
    })
</script>

// 封装之后再使用
const debounce = (fn, delay = 500) => {
    // timer 是在闭包中的
    let timer = null;
    // 闭包场景: 1.函数做为返回值  2.函数作为参数
    return () => {
        if (timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(() => {
            fn.apply(this, arguments)
            timer = null
        }, delay)
    }
}
// 使用  不传delay 默认500ms
input.addEventListener('keyup', debounce(() => {
console.log(input.value);
}))

8.手写节流 throttle

  • 拖拽一个元素时候,要随时拿到该元素被拖拽的位置
  • 直接用drag事件,则会触发频繁,很容易导致卡顿
  • 节流: 无论拖拽速度多快,都会每隔100ms触发一次
<style>
    #div1 {
        width: 200px;
        height: 200px;
        background-color: #ccc;
        font-size: 24px;
    }
</style>

<div id="div1" draggable="true">拖拽</div>
<script>
    const div1 = document.getElementById("div1");
    let timer = null;
    div1.addEventListener('drag', (e) => {
        if (timer) {
            return
        }
        timer = setTimeout(() => {
            console.log(e.offsetX, e.offsetY);
            timer = null;
        }, 1000)
    })
    const throttle = (fn, delay = 1000) => {
        let timer = null;
        return () => {
            if (timer) {
                return
            }
            timer = setTimeout(() => {
                fn.apply(this, arguments)
                timer = null
            }, delay)
        }
    }
    div1.addEventListener('drag', throttle((e) => {
        console.log(e.offsetX, e.offsetY);
    }))
</script>

9.如何预防 xss 攻击

  • 常见的web前端攻击方式有哪些?
  • 1.XSS跨站请求攻击
  • 2.XSRF跨站请求伪造
比如一个博客网站,发表一篇博客,其中嵌入<script> 脚本
1.脚本内容: 获取cookie,发送到我的服务器(服务器配合跨域)
2.发布这篇博客,有人查看它,我轻松收割访问者的cookie

解决方法:
1.替换特殊字符,比如< 变为&lt; >变为&gt;
2.<script> 变为&lt;script&gt; 直接显示,不会做为脚本执行
3.前端显示的时候替换,后端存储的时候替换

10.如何预防 xsrf攻击

1.使用POST接口
2.增加验证,例如密码,短信验证登录,指纹等安全措施