升级webpack 5实战

升级webpack 5实战

一、背景

本次对公司项目进行webpack的升级 , 原有版本是webpack4.42.1, 本次升级目标是webpack5.28.0,已经是很新的版本了。目标,升级Webpack5,应用长效缓存,提升构建速度。

二、步骤

按照官网升级文档

“vue-loader”: “^15.9.6”,

“terser-webpack-plugin”: “^5.1.1”,

“style-loader”: “^2.0.0”,

“mini-css-extract-plugin”: “^1.4.0”,

“less-loader”: “^8.0.0”,

“html-webpack-plugin”: “^5.3.1”,

“file-loader”: “^6.2.0”,

“css-loader”: “^5.2.0”,

“compression-webpack-plugin”: “^7.1.2”,

“babel-loader”: “^8.2.2”,

“postcss-loader”: “^5.2.0”,

vite初体验

Vite —— 一种新的、更快地 web 开发工具。

vite 是什么

vite —— 一个由 vue 作者尤雨溪开发的 web 开发工具,它具有以下特点:

  1. 1.快速的冷启动
  2. 2.即时的模块热更新
  3. 3.真正的按需编译

Vite介绍

Vite,一个基于浏览器原生 ES imports 的开发服务器。利用浏览器去解析 imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用。同时不仅有 Vue 文件支持,还搞定了热更新,而且热更新的速度不会随着模块增多而变慢。针对生产环境则可以把同一份代码用 rollup 打包。

reduce的原生写法

reduce

特点: reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
源码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
Array.prototype.myReduceRight = function(func, init) {
var prev = init,
len = this.length,
k = len - 1;
if(init === undefined) {
prev = this[k];
k = len - 2;
}
for(k; k >= 0; k --) {
prev = func(prev, this[k], k);
}
return prev;
}

map的原生写法

map

特点:
map处理return出来的值,把值放在一个新的数组,默认返回undefined。
浅拷贝,会改变原数组。
浅度map实现

1
2
3
4
5
6
7
8
Array.prototype.myMap = function(func) {
var len = this.length,
newArr = [];
for(var i = 0; i < len; i++) {
newArr.push(func(this[i], i));
}
return newArr;
}

filter的原生写法

filter

作用: filter筛选数组,筛选出新的数组。
特点: 筛选的值由return来决定,会放在一个新的数组中返回。

源码实现

1
2
3
4
5
6
7
8
9
10
Array.prototype.myFilter = function(func) {
var len = this.length,
newArr = [];
for(var i = 0; i < len; i++) {
if(func(this[i], i)) {
newArr.push(this[i]);
}
}
return newArr;
}

forEach的原生写法

forEach

作用: 循环遍历数组
特点:
不改变原数组,返回值为undefined。
改变不了数组的遍历(return/break不好使,会报错)

源码实现

1
2
3
4
5
6
Array.prototype.myForEach = function(func) {
var len = this.length;
for(var i = 0; i < len; i++) {
func(this[i], i);
}
}

Vue组件间的通信方式

方法一、props/$emit

父组件 A 通过 props 的方式向子组件 B 传递,B to A 通过在 B 组件中 $emit, A 组件中 v-on 的方式实现。

  1. 父组件向子组件传值
    接下来我们通过一个例子,说明父组件如何向子组件传递值:在子组件 Users.vue 中如何获取父组件 App.vue 中的数据 users:[“王小虎”,”张三”,”李四”]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//App.vue父组件
<template>
<div id="app">
<users v-bind:users="users"></users>//前者自定义名称便于子组件调用,后者要传递数据名
</div>
</template>
<script>

import Users from "./components/Users"

export default {
name: 'App',
data(){
return{
users:["王小虎","张三","李四"]
}
},
components:{
"users":Users
}
}

【fetch跨域请求】cors

当使用fetch 发起跨域请求时,CORS(跨域资源共享Cross-origin resource sharing)

请求fetch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const body = {name:"Good boy"};
fetch("http://leheavengame.com/API",{
headers:{
'content-type':'application/json'
}
method:'POST',
body: JSON.stringify(body)
}).then(response =>
response.json().then(json => ({ json, response }))
).then(({ json, response }) => {
if (!response.ok) {
return Promise.reject(json);
}
return json;
}).then(
response => response,
error => error
);

实用的跨域方法

同源策略

同源策略/SOP(Same origin policy)是一种约定,由 Netscape 公司 1995 年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS、CSRF 等攻击。所谓同源是指 “协议 + 域名 + 端口” 三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源。

什么是跨域?

当协议、域名、端口号,有一个或多个不同时,有希望可以访问并获取数据的现象称为跨域访问,同源策略限制下 cookie、localStorage、dom、ajax、IndexDB 都是不支持跨域的。

假设 cookie 支持了跨域,http 协议无状态,当用户访问了一个银行网站登录后,银行网站的服务器给返回了一个 sessionId,当通过当前浏览器再访问一个恶意网站,如果 cookie 支持跨域,恶意网站将获取 sessionId 并访问银行网站,出现安全性问题;IndexDB、localStorage 等数据存储在不同域的页面切换时是获取不到的;假设 dom 元素可以跨域,在自己的页面写入一个 iframe 内部嵌入的地址是 www.baidu.com, 当在百度页面登录账号密码时就可以在自己的页面获取百度的数据信息,这显然是不合理的。

这就是为什么 cookie、localStorage、dom、ajax、IndexDB 会受到同源策略会限制,下面还有一点对跨域理解的误区:

误区:同源策略限制下,访问不到后台服务器的数据,或访问到后台服务器的数据后没有返回;

正确:同源策略限制下,可以访问到后台服务器的数据,后台服务器会正常返回数据,而被浏览器给拦截了。

js判断是否可以打开本地软件

js 判断是否安装插件

需求:点击一个按钮,然后打开本地的软件。类似一些网站打开 qq 一样。但是后来遇到一个问题,如果本地没有安装这个指定的软件,则无法打开。所以需要判断当前的电脑是否已经安装指定软件,如果已安装,则打开软件;否则,弹出模态框,提示下载并安装软件。如果本地安装了插件,当尝试使用插件打开时,window后触发blur事件;如果无法打开插件,则什么都不会发生。

根据这个原理,进行一个简单的封装。(其实也不算是封装,只是简单的把其中的原理展现出来而已)

这里使用的是es5代码,主要是为了兼任低版本的浏览器,可以在理解其中的原理后,移植到相应的项目或者框架。


:D 一言句子获取中...