前端知识点部分总结

1.怪异盒模型

标准盒模型:在标准模式下,一个块的总宽度 = 内容的width + padding(左右) + border(左右) + margin(左右)

怪异盒模型:一个块的总宽度 = 内容的width + margin(左右)(这里的width包含了padding(左右)和border(左右)的值)

2.vuex状态管理工具

state:仓库中的状态(数据);
getters:状态的衍生状态(数据);
mutation:状态的修改方法;
actions:状态的异步修改方法。

2.1 dispatch与commit区别

两个方法都是传值给VueX的mutation改变state中数据的;

  • commit:同步操作

存储:

this.$store.commit("changeValue")

取值:

this.$store.state.changeValue
  • dispatch:异步操作

    存储:

    this.$store.dispatch("getValue")
    

    取值:

    this.$store.getters.getValue
    

3.继承方法:6种

  • 原型链继承:通过原型将一个引用类型继承另一个引用类型的属性和方法。

    重点:让新实例的原型等于父类的实例。

    特点:1、实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)

    缺点:1、新实例无法向父类构造函数传参。

    ​ 2、继承单一。

    ​ 3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一 个实例的原型属性也会被修改!)

  • 原型式继承:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。object.create()就是这个原理。

  • 借用构造函数继承:在子类构造函数内部调用超类型构造函数,通过使用apply()和call()方法可以在新创建的子类对象上执行构造函数。

  • 组合继承(组合原型链继承和借用构造函数继承)

  • 寄生式继承:就是给原型式继承外面套了个壳子。

  • 寄生组合式继承(常用):在函数内返回对象然后调用

4.CDN

构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络阻塞,提高用户访问响应速度和命中率。

5.浏览器缓存

  • 强缓存:浏览器在加载资源时,会先根据本地缓存资源的header中的信息判断是否命中强缓存。header中的信息是指:expires和cahe-control;

    expries:该字段是http1.0时的规范,值为一个绝对时间的GMT格式的时间字符串;

    cahe-control:主要利用该字段的max-age值判断相对时间。

  • 协商缓存:当强缓存没有命中时,浏览器会发送一个请求到服务器,服务器会根据header中的部分信息来判断是否命中缓存;

    header中的信息:Last-Modify/If-Modify-Since和ETag/If-None-Match;

    Last-Modify/If-Modify-Since:浏览器第一次请求资源时,服务器返回header中会加上Last-Modify,是一个时间标识符,该资源的最后的修改时间;

    缺点:短时间内资源发生改变,Last-Modify不会发生变化;

    ETag/If-None-Match:返回的是一个校验码

  • 总结:浏览器再次访问一个访问过得页面

    ​ 1.看看是否命中强缓存;

    ​ 2.如果未命中,发送请求至服务器检查是否命中协商缓存

    ​ 3.如果命中返回304,使用本地缓存,如果未命中,返回新数据。

6.JSONP跨域

  • 优点:兼容性好;直接访问响应文件
  • 缺点:只支持get请求;JSONP是从其他域中加载代码执行,如果其他域不安全,很可能在响应中夹带一些恶意代码。

7.post与get区别

  • 1.get只接受ASCII字符,post没有限制,允许二进制;
  • 2.get在浏览器回退刷新是无害的,post会再次请求;
  • 3.get请求只能进行url编码,post支持多种编码格式;
  • 4.post相比get更安全。

8.src与href区别

src:外部资源路径;

href:网络资源路径。

9.粘性定位坑

  • 父元素不能设置overflow:hidden;
  • 只在父元素中有效;

10.数组快速排序(ES6)

ES6快捷方法:set

例:

let arr=[1,2,3,4,4,1];
let newarr=new set(arr)

生成一个新数组,数组会自动去重

11、原型及原型链

  1. __proto__constructor属性是对象所独有的,prototype属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__constructor属性。
  2. __proto__属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,一直找,直到__proto__属性的终点null,再往上找就相当于在null上取值,会报错。通过__proto__属性将对象连接起来的这条链路即我们所谓的原型链。
  3. prototype属性的作用就是让该函数所实例化的对象们都可以找到公用的属性和方法,即f1.__proto__ === Foo.prototype
  4. constructor属性的含义就是指向该对象的构造函数,所有函数(此时看成对象了)最终的构造函数都指向Function
  5. Function instanceof Object //true
    Object instanceof Function // true 说明Object 是被Function 构造出来的
    Function instanceof Function // true

12、webpack 中 chunkHash 与 contentHash 区别

1.hash:如果都使用hash的话,因为这是工程级别的,即每次修改任何一个文件,所有文件名的hash至都将改变。所以一旦修改了任何一个文件,整个项目的文件缓存都将失效。

chunkhash的用途随之而来。

2.chunkhash:chunkhash根据不同的入口文件(Entry)进行依赖文件解析、构建对应的chunk,生成对应的哈希值。生产环境里把一些公共库和程序入口文件区分开,单独打包构建,接着我们采用chunkhash的方式生成哈希值,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响。并且webpack4中支持了异步import功能,固,chunkhash也作用于此。

contenthash的用途随之而来。

3.contenthash:针对文件内容级别的,只有你自己模块的内容变了,那么hash值才改变

13 、Promise

promise

      class MyPromise {
        static PENDING = "pending";
        static FULFILLED = "fulfilled";
        static REJECTED = "rejected";
        constructor(excutor) {
          this.status = MyPromise.PENDING;
          this.value = undefined;
          this.reason = undefined;
          this.callbackList = [];
          excutor(this.resolve.bind(this), this.reject.bind(this));
        }
        resolve(value) {
          if (value instanceof MyPromise) {
            value.then(this.resolve.bind(this), this.reject.bind(this));
            return;
          }
          this.value = value;
          this.status = MyPromise.FULFILLED;
          this.callbackList.forEach((cb) => this.handle(cb));
        }
        reject(reason) {
          if (value instanceof MyPromise) {
            value.then(this.resolve.bind(this), this.reject.bind(this));
            return;
          }
          this.value = reason;
          this.status = MyPromise.REJECTED;
          this.callbackList.forEach((cb) => this.handle(cb));
        }
        then(onFulfilled, onRejected) {
          return new MyPromise((nextReslove, nextReject) => {
            this.callbackList.push({
              onFulfilled,
              onRejected,
              nextReslove,
              nextReject,
            });
          });
        }
        handle(callback) {
          const { onFulfilled, onRejected, nextReslove, nextReject } = callback;
          if (this.status === MyPromise.FULFILLED) {
            const nextValue = onFulfilled
              ? onFulfilled(this.value)
              : this.value;
            nextReslove(nextValue);
          } else if (this.status === MyPromise.REJECTED) {
            const nextReason = onRejected
              ? onRejected(this.reason)
              : this.reason;
            nextReject(nextReason);
          } else if (this.status === MyPromise.PENDING) {
            this.callbackList.push(callback);
          }
        }
      }

promise.all

Promise.prototype.all = function(promises) {
  let results = new Array(promises.length);
  let promiseCount = 0;
  let promisesLength = promises.length;
  return new Promise(function(resolve, reject) {
    for (let val of promises) {
      Promise.resolve(val).then(function(res) {
        promiseCount++;
        // results.push(res);
        results[promiseCount] = res;
        // 当所有函数都正确执行了,resolve输出所有返回结果。
        if (promiseCount === promisesLength) {
          return resolve(results);
        }
      }, function(err) {
        return reject(err);
      });
    }
  });
};

14、less 与 sass 区别,技术选型时如何取舍

14.1、Less环境较Sass简单

sass的安装需要安装Ruby环境,Less基于JavaScript,是需要引入Less.js来处理代码输出css到浏览器,也可以在开发环节使用Less,然后编译成css文件,直接放在项目中,有less.app、SimpleLess、CodeKit.app这样的工具,也有在线编辑地址。

14.2、Less使用较Sass简单

LESS 并没有裁剪 CSS 原有的特性,而是在现有 CSS 语法的基础上,为 CSS 加入程序式语言的特性。只要你了解 CSS 基础就可以很容易上手。

14.3、从功能出发,Sass较Less略强大一些

①sass有变量和作用域。

- KaTeX parse error: Undefined control sequence: \- at position 20: …able,like php; \̲-̲ #{variable}like ruby;
- 变量有全局和局部之分,并且有优先级。

②sass有函数的概念;

- @function和@return以及函数参数(还有不定参)可以让你像js开发那样封装你想要的逻辑。
-@mixin类似function但缺少像function的编程逻辑,更多的是提高css代码段的复用性和模块化,这个用的人也是最多的。
-ruby提供了非常丰富的内置原生api。

③进程控制:

-条件:@if @else;
-循环遍历:@for @each @while
-继承:@extend
-引用:@import

④数据结构:

- l i s t 类型 = 数组; − list类型=数组; - list类型=数组;map类型=object;
其余的也有string、number、function等类型

14.4、Less与Sass处理机制不一样

前者是通过客户端处理的,后者是通过服务端处理,相比较之下前者解析会比后者慢一点

14.5、关于变量在Less和Sass中的唯一区别就是Less用@,Sass用$。

14.6、 为什么选择使用Sass而不是Less?

1、Sass在市面上有一些成熟的框架,比如说Compass,而且有很多框架也在使用Sass,比如说Foundation。

2、就国外讨论的热度来说,Sass绝对优于LESS。
3、就学习教程来说,Sass的教程要优于LESS。在国内LESS集中的教程是LESS中文官网,而Sass的中文教程,慢慢在国内也较为普遍。

4、Sass也是成熟的CSS预处理器之一,而且有一个稳定,强大的团队在维护。

5、同时还有Scss对sass语法进行了改良,Sass 3就变成了Scss(sassy css)。与原来的语法兼容,只是用{}取代了原来的缩进。

6、bootstrap(Web框架)最新推出的版本4,使用的就是Sass。

15、ES6 Symbol 使用场景

15.1、介绍

symbol 英文意思为 符号、象征、标记、记号,在 js 中更确切的翻译应该为 独一无二的值

const s = Symbol();
console.log(typeof s);  // "symbol"

需要注意的是通过 Symbol 方法创建值的时候不用使用 new 操作符,原因是通过 new 实例化的结果是一个 object 对象,而不是原始类型的 symbol

Symbol.for 方法可以检测上下文中是否已经存在使用该方法且相同参数创建的 symbol 值,如果存在则返回已经存在的值,如果不存在则新建。

const s1 = Symbol.for('foo');
const s2 = Symbol.for('foo');
console.log(s1 === s2); // true

Symbol.keyFor 方法返回一个使用 Symbol.for 方法创建的 symbol 值的 key

const foo = Symbol.for("foo");
const key = Symbol.keyFor(foo);
console.log(key) // "foo"

15.2、使用场景

1.消除魔法字符

if (type === 'basic') {
    return <div>basic tab</div>
}
 
if (type === 'super') {
    return <div>super tab</div>
}
// 改造后  上面代码中字符串 basic、super 就是与业务代码无关的魔法字符,接下来使用 Symbol 对这块代码进行改造

const tabTypes = {
    basic: Symbol(),
    super: Symbol(),
}
 
if (type === tabTypes.basic) {
    return <div>basic tab</div>
}
 
if (type === tabTypes.super) {
    return <div>super tab</div>
}

2、作为对象属性 当一个复杂对象中含有多个属性的时候,很容易将某个属性名覆盖掉,利用 Symbol 值作为属性名可以很好的避免这一现象。
node库中的realpathSync方法就是用的此办法

const name = Symbol('name');
const obj = {
    [name]: 'ClickPaas',
}

3、模拟类的私有方法:ES6 中的类是没有 private 关键字来声明类的私有方法和私有变量的,但是我们可以利用 Symbol 的唯一性来模拟。

const speak = Symbol();
class Person {
    [speak]() {
        ...
    }
}

16、generator 有什么应用场景

1. 延迟执行:generator调用后,其状态是挂起的,通过调用next()来让其继续执行,从而达到延迟执行的效果:

2. 无限长的序列:由于generator是延迟执行的,因此你可以使用generator创建一个无限长的序列:

3.异步流程控制

17、async await 如何实现的

async

async function getConstant() {
    return 1
}
//原理
function  getConstant() {
	return Promise.resolve().then(()=>{
		return 1
	})
    
}

**await **

//大家可以看看这个执行顺序,都知道是1,2,3
async function test(){
	 a = 1
    await console.log(1)
    b = 2 
    await console.log(2)
    c = 3
    await console.log(3)
    return 4
}
//原理
function test(){
	return Promise.resolve().then(()=>{
		a=1
		return console.log(1) //return返回的也是promise
	}).then(()=>{
		c=2
		return console.log(2)
	}).then(()=>{
		 c = 3
    return console.log(3)
	}).then(()=>{
		return 4
	})
}

18、tcp 与 udp 的区别

1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接

2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付

3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

5、TCP首部开销20字节;UDP的首部开销小,只有8个字节

6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

19、手写防抖,节流函数

  1. 防抖函数
    function debounce(func, wait) {
      let timeout;
      return function () {
        const context = this;
        const args = [...arguments];
        if (timeout) clearTimeout(timeout);
        timeout = setTimeout(() => {
          func.apply(context, args)//改变this的指向,或者写成箭头函数传入this,此时指针指向上下文
        }, wait);
      }
    }
    

    2.节流函数

    function throttle(fn,wait){
        var timer = null;
        return function(){
            var context = this;
            var args = arguments;
            if(!timer){
                timer = setTimeout(function(){
                    fn.apply(context,args);
                    timer = null;
                },wait)
            }
        }
    }
    

20、什么是 event loop

Event Loop是一个程序结构,用于等待和发送消息和事件

简单说,就是在程序中设置两个线程:一个负责程序本身的运行,称为"主线程";另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为"Event Loop线程"(可以译为"消息线程")

21、TCP三次握手

1.第一次握手:客户主动(active open)去connect服务器,并且发送SYN 假设序列号为J,
服务器是被动打开(passive open)

2.第二次握手:服务器在收到SYN后,它会发送一个SYN以及一个ACK(应答)给客户,
ACK的序列号是 J+1表示是给SYN J的应答,新发送的SYN K 序列号是K

3.第三次握手:客户在收到新SYN K, ACK J+1 后,也回应ACK K+1 以表示收到了,
然后两边就可以开始数据发送数据了

22、字符串转换为 Unicode 编码

charCodeAt(index) 方法可返回指定位置的字符的 Unicode 编码。

index 必需。表示字符串中某个位置的数字,即字符在字符串中的下标。

返回在指定的位置的字符的 Unicode 编码。Number

23、BFC

23.1.定义

BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。

23.2.BFC的布局规则

  • 内部的Box会在垂直方向,一个接一个地放置。
  • Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。
  • 每个盒子(块盒与行盒)的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
  • BFC的区域不会与float box重叠。
  • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
  • 计算BFC的高度时,浮动元素也参与计算。

23.3.如何创建BFC

  • float的值不是none。
  • position的值不是static或者relative。
  • display的值是inline-block、table-cell、flex、table-caption或者inline-flex
  • overflow的值不是visible

23.4.BFC的作用

  1. 利用BFC避免margin重叠。
  2. 自适应两栏布局
  3. 清除浮动。

23.5.总结

BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。

因为BFC内部的元素和外部的元素绝对不会互相影响,因此, 当BFC外部存在浮动时,它不应该影响BFC内部Box的布局,BFC会通过变窄,而不与浮动有重叠。同样的,当BFC内部有浮动时,为了不影响外部元素的布局,BFC计算高度时会包括浮动的高度。避免margin重叠也是这样的一个道理。

24、重排与重绘

24.1.重排与重绘

浏览器下载完页面所有的资源后,就要开始构建DOM树,与此同时还会构建渲染树(Render Tree)

渲染树:其实在构建渲染树之前,和DOM树同期会构建Style Tree。DOM树与Style Tree合并为渲染树

重排:当DOM的变化引发了元素几何属性的变化,比如改变元素的宽高元素的位置,导致浏览器不得不重新计算元素的几何属性,并重新构建渲染树。

重绘:完成重排后,要将重新构建的渲染树渲染到屏幕上。

总结:重排负责元素的几何属性更新,重绘负责元素的样式更新。而且,重排必然带来重绘,但是重绘未必带来重排。

24.2. 重排触发机制绘

重排发生的根本原理就是元素的几何属性发生了改变

  • 添加或删除可见的DOM元素
  • 元素位置改变
  • 元素本身的尺寸发生改变
  • 内容改变
  • 页面渲染器初始化
  • 浏览器窗口大小发生改变

24.3.如何进行性能优化

24.3.1.最小化重绘和重排

既然重排&重绘是会影响页面的性能,尤其是糟糕的JS代码更会将重排带来的性能问题放大。既然如此,我们首先想到的就是减少重排重绘.

减少重排的方法就是切换类名而不是使用内联样式的cssText方法

24.3.2.批量修改DOM

批量修改DOM元素的核心思想是:

  • 让该元素脱离文档流
  • 对其进行多重改变
  • 将元素带回文档中

优化方式:

  • 隐藏元素,进行修改后,然后再显示该元素
  • 使用文档片段创建一个子树,然后再拷贝到文档中
  • 将原始元素拷贝到一个独立的节点中,操作这个节点,然后覆盖原始元素
24.3.3. 缓存布局信息
offsetTop, offsetLeft,...
scrollTop, scrollLeft, ...
clientTop, clientLeft, ...

这些属性,都是需要实时回馈给用户的几何属性或者是布局属性,不能再依靠浏览器的优化

解决方法:

div.style.left = 1 + div.offsetLeft + 'px';
div.style.top = 1 + div.offsetTop + 'px';

每次都会访问div的offsetLeft,造成浏览器强制刷新渲染队列以获取最新的offsetLeft值。更好的办法就是,将这个值保存下来,避免重复取值。

优化后:

current = div.offsetLeft;
div.style.left = 1 + ++current + 'px';
div.style.top = 1 + ++current + 'px';

25、判断this(按优先级排序)

1.new绑定

函数是否在new中调用?如果是的话this绑定的是新创建的对象。

var bar = new foo();

2.显示绑定

函数是否通过call、apply或者硬绑定调用?如果是的话,this绑定的是指定的对象。

var bar = foo.call(obj2)

3.隐世绑定

函数是否在某个上下文对象中调用?如果是的话,this绑定的是那个上下文对象。

var bar = obj1.foo()

4.默认绑定

如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到全局对象。

var bar = foo()

26、obj.a与obj[‘a’]的区别

属性访问:.操作符要求属性名满足标识符的命名规范;

键访问:[‘a’]语法可以接受任意UTF-8/Unicode字符串作为属性名。

27、array、set、map区别

1.array:数组对象,是使用单独的变量名来存储一系列的值。
2.Set: ES6 提供了新的数据结构。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成 Set 数据结构。
3.ES6 提供了新的数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 结构提供了“值—值”的对应。

28、从浏览器输入url后都经历了什么

  1. 如果地址栏中输入的是一个域名,浏览器会先使用自己的DNS缓存进行域名解析,转为IP地址,如果缓存中不存在,则会请求使用上层DNS(操作系统的DNS),操作系统会先查询本地HOST文件,如果HOST文件中不存在则会使用网络设置的DNS进行域名解析,本地域名服务器会向 根域名服务器发送一个请求。如果根域名服务器也不存在该域名时,本地域名会向顶级域名服务器(TLD)发送一个请求,即根域名服务器–>顶级域名服务器–>权威域名服务器依次类推下去。最终得到域名对应的IP地址。

  2. 获得IP地址后,浏览器按照IP地址进行连接(tcp连接),连接成功之后按照http协议的格式(请求行,请求头,请求头)发送http请求,服务器会返回响应报文(响应行,响应头,响应体),浏览器收到响应报文后,会根据响应头中的Content-Type字段来决定如何进行下一步处理,对于普通的网页Content-Type值是text/html,浏览器就会在页面中打开本次请求响应体中的数据。

  3. 在打开页面时,浏览器首先对html文本进行解析,创建DOM树,然后将每个节点渲染到页面上,其中如果出现了附带资源的标签(例如img,script等),浏览器会再次按照这些资源的src发送请求,当请求完成之后将请求内容插入到页面中,其中script标签资源是同步加载的,其他资源是异步加载的。

29、为什么bind需要判断是否为new创建的调用

因为new内部同样更改了this指向,这时如果通过bind强制更改this指向,可能会导致new出来的对象的原型链被切断;

30、meta标签的作用

  1. 搜索引擎优化(SEO)
  2. 定义页面使用语言
  3. 自动刷新并指向新的页面
  4. 实现网页转换时的动态效果
  5. 控制页面缓冲
  6. 网页定级评价
  7. 控制网页显示的窗口
    常用的有http-equiv属性和name属性

31、正则的exec

如果 exec() 找到了匹配的文本,则返回一个结果数组。否则,返回 null。
当 RegExpObject 是一个全局正则表达式时,exec() 的行为就稍微复杂一些。它会在 RegExpObject 的 lastIndex 属性指定的字符处开始检索字符串 string。当 exec() 找到了与表达式相匹配的文本时,在匹配后,它将把 RegExpObject 的 lastIndex 属性设置为匹配文本的最后一个字符的下一个位置。
重要事项:如果在一个字符串中完成了一次模式匹配之后要开始检索新的字符串,就必须手动地把 lastIndex 属性重置为 0。

32、最大数

Number 下分别有两个常量 MAX_VALUE 和 MAX_SAFE_INTEGER。
MAX_VALUE 表示在 JavaScript 里所能表示的最大数值,MAX_SAFE_INTEGER 表示在 JavaScript 中最大的安全整数,他们的值分别如下:

Number.MAX_VALUE // 1.7976931348623157e+308
Number.MAX_SAFE_INTEGER // 9007199254740991

33、webpack相关

基于node平台运行···默认采用common.js

module-rules

use数组中loader执行顺序:从右到左,从下到上

  module: {
    rules: [
      {
        //   匹配规则
        test: /\.css$/,
        use: [
          // use数组中loader执行顺序:从右到左,从下到上
          // 创建一个style标签,将js中的样式资源插入html,添加到header中生鲜
          "style-loader",
          // 将css文件变成一个commonjs模块加载到js中,字符串的形式
          "css-loader",
        ],
      },
    ],
  },

性能优化

  • 开发环境性能优化
  • 生产环境性能优化
开发环境性能优化
  • 优化打包构建速度
    • HMR功能(热加载)
  • 优化代码调试功能
    • source-map(打包速度)
生产环境性能优化
  • 优化打包构建速度

    • oneOf
    • babel缓存(针对js代码)
    • dll(对于第三方库只打包一次)
    • externals(让某些库不被打包,dll一样,针对cdn链接进来的)
    • 多进程打包
  • 优化代码运行的性能

    • 缓存(hash-chunkhash-contenthash,文件缓存)
    • tree-shaking(优化代码性能,删除无用代码)
      1.必须开启es6模块化 2. 开启production环境
    • code split(代码分割)
    • 懒加载、预加载
      预加载技术比懒加载要好
      预加载兼容性不好,大部分还是使用懒加载
    • PWA(离线可访问,需要借助服务端)

source-map

source-map: 一种提供源代码到构建后代码映射技术(如果构建后代码出错了,通过映射关系追踪到源代码)
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source
内联和外联区别:1.外部生成文件,内联没有 2.内联构建速度更快
source-map:外部
错误代码准确信息 和 源代码的错误位置

inline_source-map: 内联
只生成一个内联source-map
错误代码准确信息 和 源代码的错误位置

hidden-source-map :外部 (隐藏源代码)
错误代码错误原因,但是没有错误位置
不能追踪源代码错误,只能提示到构建后代码错误位置

eval-source-map:内联
每一个文件都生成对应的source-map,都在eval
错误代码准确信息 和 源代码的错误位置

nosources-source-map: 外部(全部隐藏代码)
错误代码准确信息 没有任何源代码的错误

cheap-source-map:外部
错误代码准确信息 和 源代码的错误位置
只能精确到行
cheap_module-source-map:外部

开发环境:速度快,调试友好

  1. 速度快(eval>inline>cheap>…)
    eval-cheap-souce-map
    eval-source-map
  2. 调试友好
    eval-source-map
    cheap-module-source-map
    cheap-source-map

–> eval-source-map

生产环境:源代码要不要隐藏?调试要不要更友好
内联会让代码体积非常大,一般不考虑内联
nosources-source-map 全部隐藏
hidden-source-map 只隐藏源代码,会提示构建后代码错误信息
–> source-map / cheap-module-source-map
react和vue框架都是选用前两种

tree_shaking(去除无用代码)

前提:1.必须使用es6模块化 2.开启production环境
作用:减小代码体积

code split

一、多入口

   // 代码分割
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  // 单入口
  // entry:'./src/js/index.js'
  entry: {
    // 多入口:有几个入口,最终输出就有几个bundle
    main: "./src/js/index.js",
    test: "./src/js/test.js",
  },
  output: {
    // [name]取文件名
    filename: "js/[name].[hash:10].js",
    path: resolve(__dirname, "build"),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
  ],
  mode: "production",
};

二、optimization

// 代码分割
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  // 单入口
  entry: "./src/js/index.js",
  output: {
    // [name]取文件名
    filename: "js/[name].[hash:10].js",
    path: resolve(__dirname, "build"),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
  ],
  // 1.可以将node—modules中代码单独打包成一个chunk
  // 2.自动分析多入口chunk中,有没有公共的文件,如有,会打包成单独的一个chunk(公用),注:单入口不可以
  optimization: {
    splitChunks: {
      chunks: "all",
    },
  },
  mode: "production",
};

externals

// 使用cdn链接可以使用externals优化打包
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "built.js",
    path: resolve(__dirname, "build"),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
  ],
  mode: "production",
  externals: {
    // 拒绝jquery被打包进来
    jquery: "jQuery",
  },
};

34、XSS过滤用户输入内容

    function escape(str) {
      if (!str) return ''
      str = str.replace(/&/g, '&')
      str = str.replace(/</g, '<')
      str = str.replace(/>/g, '>')
      str = str.replace(/"/g, '"')
      str = str.replace(/'/g, '&#39;')
      return str
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vagabondYear

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值