Open cristinazhou opened 1 year ago
2022.10.14
2022.10.16
1、路由的实现方式 Hash和History区别 2、微前端 3、项目迭代 CICD 流程
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。 Docker 技术的三大核心概念,分别是:
镜像(Image) 容器(Container) 仓库(Repository) 持续不是指“一直在进行”,而是“随时可进行”,一般来说包括这几个方面:
引入 CI/CD 以后,整个流程变成: 1、提交代码,push 到 git 远程仓库 2、git hook 触发 jenkins 的构建 job (自动) 3、 jenkins job 中拉取项目代码,运行 npm run build,如果失败,发送邮件通知相关人。(自动) 4、 jenkins job 中执行测试服务器的部署脚本 (自动) CI/CD 的关键在于自动化,使用脚本来自动化构建、部署,而 Webhook 则起到了中间桥梁的作用。
Webhook 简单来说就是一种反向 API 机制,是在特定情况下触发的一种 API,类似于触发器。 Github 的 Webhook: TRAVIS CI Travis CI 提供的是持续集成服务(Continuous Integration,简称 CI)。 它绑定 Github 上面的项目,只要有新的代码,就会自动抓取。 提供一个运行环境,完成构建,还能部署到服务器。 这些行为都可以在项目根目录的 .travis.yml 配置文件里面指定。
2022.10.20
ps: 最近有需求要赶,学习上有一点偷懒……
2022.10.21
1、mvc 设计思想, cocos 游戏开发基于mvc软件架构模式 2、js 内存机制 复习 浅谈JS内存机制 以下内容均是该文章的摘要 原始类型的数据是存放在栈中,引用类型的数据存放在堆中 ?
摘要: V8把数字分成两种类型:smi 和 heapNumber smi是范围为 :-2³¹ 到 2³¹-1的整数,在栈中直接存值;除了smi,其余数字类型都是heapNumber,需要另外开辟堆空间进行储存,变量保存其引用。 bigInt、string、symbol这些内存大小不固定的类型在栈中也是保存其堆内存的引用。同时我们在栈中可以声明很大的string,如果string存放在栈中明显也不合理。
js 垃圾回收
JS 把堆空间分成新生代和老生代两个区域,新生代中存放的是生存时间短的对象,通常只支持 1~8M 的容量;老生代中存放的生存时间长的对象,一些大的数据也会被直接分配到老生区中。而针对这两个区域,JS 存在两个垃圾回收器:主垃圾处理器和副垃圾处理器。这里先说说垃圾回收一般都有相同的执行流程:
副垃圾回收器
副垃圾回收器主要是采用 Scavenge 算法进行新生区的垃圾回收,它把新生区划分为两个区域:对象区域和空闲区域,新加入的对象都会存放到对象区域,当对象区域快被写满时,会对对象区域进行垃圾标记,把存活对象复制并有序排列至空闲区域,完成后让这两个区域角色互转,由此便能无限循环进行垃圾回收。同时存在对象晋升策略,也就是经过两次垃圾回收依然还存活的对象,会被移动到老生区中。
主垃圾回收器
由于老生区空间大,数据大,所以不适用 Scavenge 算法,主要是采用标记-整理算法,其工作流程是从一组根元素开始,递归遍历这组根元素,在这个遍历过程中,能到达的元素称为活动对象,没有到达的元素就可以判断为垃圾数据。接着让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。垃圾回收工作是需要占用主线程的,必须暂停JS脚本执行等待垃圾回收完成后恢复,这种行为称为全停顿。 由于老生代内存大,全停顿对性能的影响非常大,所以出现了增量标记的策略进行老生区的垃圾回收。
// 测试代码 const [test, setTest] = useState(null); useEffect(() => { (async () => { // 这里表达一个异步操作如:xhr、fetch、promise等等 await sleep(3000); const obj = new TestObj(); setTest(obj); })(); }, []); // 如果把代码改成这样,就不会造成内存泄漏: const [test, setTest] = useState(null); useEffect(() => { let unMounted = false; (async () => { await sleep(3000); if (unMounted) return; const obj = new TestObj(); setTest(obj); })(); return () => { unMounted = true; }; }, []);
2022.10.22
基础知识复习 es5 中类和 es6的class有什么区别 ?
- class类必须使用new调用,不能直接执行
- class类不存在变量提升
- class类无法遍历它的实例原型链上的属性和方法
- new.target 属性,es6为new命令引入了一个new.target 属性,它会返回new命令作用于的那个构造函数。如果不是通过new调用或Reflect.construct()调用的,new.target 会返回undefined。
- class 类有static静态方法 ,只能通过类调用,不会出现在实例上
2022.10.23 webpack-dev-server 的原理
“start”: “webpack serve --open” 这里webpack会基于webpack.config.js 里的配置创建一个compiler, 然后基于compiler和devServer相关配置生成一个webpackDevServer实例,该实例会启用一个express服务来帮我们监听静态资源变化并更新。 更新: 因为webpack-dev-server 使用的是webpack的watch模式进行的编译,当我们更新了代码后,webpack是能够监听到代码的变化,代码变化后,webpack会再次将项目 代码进行打包编译,编译完成后,就会触发done钩子函数。 初始化时,在done钩子上挂载了回调,setupHooks里的websocketServer 对客户端进行消息广播,通知客户端项目代码有更新。
this.compiler.hooks.done.tap('webpack-dev-server', (status) => { if(this.webSocketServer) { this.sendStatus(this.webSocketServer.clients, this.getStatus(status)) this.stats = stats; }
})
> 2、当客户端接收到websocket广播的消息后,会触发reloadApp方法(webpack打包时注入进去的),reloadApp会根据广播消息里更新类型选择是页面跟心liveReload还是模块更新hotReload。
3、客户端更新页面时,回去请求类似c390bbe00370dd079a6.hot-update.json, main.c390bbe00370dd079a6.hot-update.json这样两个文件,这两个文件是webapck使用了HotModuleReplacementPlugin编译时,每次增量编译就是多产出阿玲哥文件,分别描述chunk更新的mainfest文件和更新过后的chunk文件。
4、拿到这两个增量文件后,再去请求express服务器去获取最新编译打包的bundle.js
5、根据更新类型,选择是两个增量文件和bundle.js比对局部更新还是页面更新。
项目复习:
脚手架项目:
> 功能:
> 1. 用户输入命令,准备创建项目。
> 2. 脚手架解析用户命令,并弹出交互语句,询问用户创建项目需要哪些功能。
> 3. 用户选择自己需要的功能。
> 4. 脚手架根据用户的选择创建 package.json 文件,并添加对应的依赖项。
> 5. 脚手架根据用户的选择渲染项目模板,生成文件(例如 index.html、main.js、App.vue 等文件)。
> 6. 执行 npm install 命令安装依赖。
知识点
1、vue3 composition api 与 options api 对比 2、websocket 相关(心跳机制) 3、redux middleware怎么应用的 Redux通关简洁攻略
export default function applyMiddleware(...middlewares) { return (createStore) =>{(...chain)(store.dispatch)
// 替换掉dispath,返回
return {
// 初始化store,拿到dispatch
const store = createStore(reducer, preloadedState)
// 不允许在middlware中调用dispath
let dispatch: Dispatch = () => {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.'
)
}
const middlewareAPI: MiddlewareAPI = { getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args) }
// 把api注入middlware
const chain = middlewares.map(middleware => middleware(middlewareAPI)) // 重点理解 // compose后传入dispatch,生成一个新的经过层层包装的dispath调用链 dispatch = compose
...store,
dispatch
}
} }
export default function compose(...funcs) { if (funcs.length === 0) { return (arg) => arg } if (funcs.length === 1) { return funcs[0] } // 简单直接的compose return funcs.reduce( (a, b) => (...args: any) => a(b(...args)) ) }
1、快排 (原地排序) 2、洗牌算法 3、url 解析