小达不刘
0%

打包原理

(1)读取入口文件,如项目中的main.js;

(2)由入口文件,解析模块所依赖的文件或包,生成ATS树;

(3)对模块代码进行处理:根据@babel工具转换ATS树(es6转es5、polyfill等);

(4)递归所有模块

(5)生成浏览器可运行的代码

打包优化

1.自带优化

a)tree-shaking:依赖关系解析(不用的不打包),只在production环境下执行

阅读全文 »

常用plugin

使用plugin丰富的自定义API,可以控制webpack编译流程的每个环节,实现对webpack的自定义功能扩展。
plugin是一个具有 apply方法的 js对象。apply方法会被 webpack的 compiler(编译器)对象调用,并且 compiler 对象可在整个 compilation(编译)生命周期内访问。

  • define-plugin:webpack模块自带的, DefinePlugin 允许在 编译时
    创建配置的全局常量,这在需要区分开发模式与生产模式进行不同的操作时,非常有用。
    例如,如果想在开发构建中进行日志记录,而不在生产构建中进行,就可以定义一个全局常量去判断是否记录日志。
  • copy-webpack-plugin:将个别文件或整个目录复制到构建目录。
  • postcss-namespace: css命名
  • BannerPlugin:对所有的文件打包后添加一个版权声明
  • uglifyjs-webpack-plugin:对 JS 进行压缩混淆
  • HtmlWebpackPlugin:可以根据模板自动生成 html 代码,并将打包生成的js,和css文件,插入到该html中
  • Hot Module Replacement:在每次修改代码保存后,浏览器会自动刷新,实时预览修改后的效果
  • extract-text-webpack-plugin:将 js 文件和 css 文件分别单独打包,不混在一个文件中
  • optimize-css-assets-webpack-plugin 不同组件中重复的 css 可以快速去重
  • html-withimg-loader 页面中经常会用到img标签,img引用的图片地址也需要一个loader来帮我们处理好
  • clean-webpack-plugin:在我们每次npm run build的时候都会在dist目录下创建很多打好的包,如果积累过多可能也会混乱,所以应该在每次打包之前将dist目录下的文件都清空,然后再把打好包的文件放进去
1
2
3
4
5
6
7
8
9
let CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
plugins: [
// 打包前先清空
new CleanWebpackPlugin('dist')
]
}

阅读全文 »

常用loader

loader: webpack本身只能打包Javascript文件,对于其他资源例如 css,图片,或者其他的语法集比如jsx,是没有办法加载的。 这就需要对应的loader将资源转化,加载进来。

样式

  • css-loader : 解析css文件中代码
  • style-loader : 将css模块作为样式导出到DOM中
  • less-loader : 加载和转义less文件
  • sass-loader : 加载和转义sass/scss文件
  • postcss-loader: 自动添加css的兼容前缀

脚本转换编译

  • script-loader : 在全局上下文中执行一次javascript文件,不需要解析
  • babel-loader : 加载ES6 代码后使用Babel转义为ES5后浏览器才能解析

Files文件

  • url-loader : 多数用于加载图片资源,超过文件大小显示则返回data URL
  • raw-loader : 加载文件原始内容(utf-8格式)

加载框架

阅读全文 »

背景:一种类似于微服务的架构,它将微服务的理念应用于浏览器端,适用于巨石应用拆分为多个小型系统、多个单体应用整合等应用场景,并且各个前端应用可以独立运行、独立开发、独立部署。

主应用

主应用为基座,接入所有子应用

配置

注册所有子应用

子应用

配置

需要在入口暴露生命周期接口

阅读全文 »

遵循规范

require 是 AMD规范引入方式
import是es6的一个语法标准,如果要兼容浏览器的话必须转化成es5的语法

调用时间

require是运行时调用,所以require理论上可以运用在代码的任何地方(虽然这么说但是还是一般放开头)
import是编译时调用,所以必须放在文件开头

本质

require是赋值过程,其实require的结果就是对象、数字、字符串、函数等,再把require的结果赋值给某个变量
import是解构过程,但是目前所有的引擎都还没有实现import,我们在node中使用babel支持ES6,也仅仅是将ES6转码为ES5再执行,import语法会被转码为require

require / exports :
遵循 CommonJS/AMD,只能在运行时确定模块的依赖关系及输入/输出的变量,无法进行静态优化。
用法只有以下三种简单的写法:

1
2
3
const fs = require('fs')
exports.fs = fs
module.exports = fs

import / export:
遵循 ES6 规范,支持编译时静态分析,便于JS引入宏和类型检验。动态绑定。
写法就比较多种多样:

阅读全文 »

CommonJS

每个文件就是一个模块,内部定义的变量是属于这个模块的,不会对外暴露,也就是不会污染全局变量。
node和webpack都对commonjs原生支持。

核心思想是通过require方法同步加载所依赖的其他模块,然后通过exports或者module.exports来导出需要暴露的接口.

浏览器不兼容CommonJs,原因是浏览器缺少module,export,require,global四个环境变量,如需使用要用工具转换。

commonJs采用同步加载不同模块文件,适用于服务端。因为模块文件都存放在服务器的各个硬盘上没读取加载时间快,适合服务端,不适用浏览器。

1
2
3
4
5
6
7
8
9
10
//index.js
var module = require('module.js);
module.aa('hello');

// module.js
module.exports = {
aa: function () {
console.log(str);
}
}

AMD

异步加载模块,允许指定回调函数,等模块异步加载完成后即可调用回调函数。

AMD核心思想就是通过define定义一个模块,然后使用require来加载一个模块

阅读全文 »

什么是模块化

将一个复杂的程序依据一定的规则规范封装成几个块文件,并进行组合在一起。
内部数据与实现是私有的,只是向外暴露一些接口方法与外部其他模块通信。

模块化的进程

1.全局function模式-把不同的功能封装成不同的全局函数

2.命名空间模式-基于简单的对象封装,
劣势:数据不安全,外部可以直接修改模块内部的数据;所有成员都暴露在外;

1
2
3
4
5
6
7
8
let obj = {
data: '',
func1: () => {},
func2: () => () {},
}

obj.data = 'aaa';
obj.func1();

3.匿名函数自执行方式(闭包)
向window对象上添加全局属性,也有的把这种方法叫做添加命名空间,目的是向外暴露接口,其实这种方式很好,方法是私有的,只能通过外部接口来小左,但是多个模块有依赖关系的时候就不好办了。

1
2
3
4
5
6
7
8
9
10
11
12
<script type="text/javascript>
(function(win) {
function func1() {
// ...
}
function func2() {
// ...
}
// 向外暴露方法,es6的写法
win.myMethods = {func1, func2};
})(window)
</script>

4.匿名函数的模式增加:向入口传入依赖的模块

阅读全文 »

官方文档: https://vuex.vuejs.org/zh/

1 vuex概述

组件之间共享数据的方式

  • 父->子:v-bind
  • 子->父:v-on
  • 兄弟之间共享数据:EventBus
    只适用于小范围共享。

vuex是一个状态管理模式,适用于多个组件共享同一状态时的场景,这里状态也可以理解为数据变量。

使用vuex好处:

  • 能够在vuex中集中管理共享的数据,易于开发和后期维护
  • 能够高效地实现组件之间的数据共享,提高开发效率
  • 存储在vuex中的数据都是响应式的,能够实时保持数据与页面的同步

2 vuex核心概念

阅读全文 »

若想系统学习Promise可以阅读:阮一峰大神写的Promise对象,此篇记录常用用法。

Promise并行请求

  • getA和getB并行执行,然后输出结果。如果有一个错误,就抛出错误
  • 每一个promise都必须返回resolve结果才正确
  • 每一个promise都不处理错误
  • 参考:https://www.jianshu.com/p/dbda3053da20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 每一个promise都必须返回resolve结果才正确
* 每一个promise都不处理错误
*/

const getA = new Promise((resolve, reject) => {
//模拟异步任务
setTimeout(function(){
resolve(2);
}, 1000)
})
.then(result => result)


const getB = new Promise((resolve, reject) => {
setTimeout(function(){
// resolve(3);
reject('Error in getB');
}, 1000)
})
.then(result => result)


Promise.all([getA, getB]).then(data=>{
console.log(data)
})
.catch(e => console.log(e));
  • getA和getB并行执行,然后输出结果。总是返回resolve结果
  • 每一个promise自己处理错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* 每一个promise自己处理错误
*/

const getA = new Promise((resolve, reject) => {
//模拟异步任务
setTimeout(function(){
resolve(2);
}, 1000)
})
.then(result => result)
.catch(e=>{

})


const getB = new Promise((resolve, reject) => {
setTimeout(function(){
// resolve(3);
reject('Error in getB');
}, 1000)
})
.then(result => result)
.catch(e=>e)


Promise.all([getA, getB]).then(data=>{
console.log(data)
})
.catch(e => console.log(e));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
let tasks = [];
for (let i = 1; i <= 5; i++) {
tasks.push(i);
};
/*
* @params : func:你封装的方法 params: 参数的数组
*/
let getDataBind = (func, params) => {
return params.map( item => {
return func.call(null, item) //传参
})
}
/*
@params : page_no 页码
getDate 可以换成你自己需要重复操作的方法,同理
*/
let getData = (page_no) => {
let saveListData = JSON.parse(localStorage.getItem(this.props.saveListData));
let params = {
page_no:page_no,
...saveListData.loadParams
}
return new Promise(resolve => {
get(this.props.sortUrl, params, this, false).then(function (data) {
resolve(data.result;);
});
})
}
Promise.all(this.getDataBind(this.getData, arrPage))
.then( resultArr => {
resultArr = resultArr.flat();//拉平数组
console.log(resultArr) //这里就获取到所有页的数据了
});
//

阅读全文 »

若想系统学习Promise可以阅读:阮一峰大神写的Promise对象,此篇记录常用用法。

Promise顺序请求

方法1——连续使用then链式调用
方法2——使用promise构建队列
方法3——使用async、await实现类似同步编程,async函数内部实现同步
参考:https://www.jianshu.com/p/dbda3053da20

方法1:链式调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
function getA(){
return new Promise(function(resolve, reject){
setTimeout(function(){
resolve(2);
}, 1000);
});
}

function getB(){
return new Promise(function(resolve, reject){
setTimeout(function(){
resolve(3);
}, 1000);
});
}

function addAB(a,b){
return a+b
}

function getResult(){
var obj={};
Promise.resolve().then(function(){
return getA()
})
.then(function(a){
obj.a=a;
})
.then(function(){
return getB()
})
.then(function(b){
obj.b=b;
return obj;
})
.then(function(obj){
return addAB(obj['a'],obj['b'])
})
.then(data=>{
console.log(data)
})
.catch(e => console.log(e));
}
getResult();

方法2:(TODO)

方法3:(TODO)

阅读全文 »