微派网络一面

详细介绍你觉得最有挑战性的项目

就司机招募

8.手撕: 拼手气抢红包,输入总金额以及红包数目

要求:-每个人都能分到红包-红包金额随机-每个人分得的金额尽可能差别不大

 function generateRandomRedPacket(totalAmount, num) {
            const result = [];
            let remainingAmount = totalAmount;
            let remainingNum = num;
            for (let i = 1; i < num; i++) {
                const min = 0.01; 
                const max = remainingAmount / remainingNum * 2;
                const amount = Math.random() * (max - min) + min; 
                remainingAmount -= amount; 
                remainingNum--; 
                result.push(parseFloat(amount.toFixed(2))); 
            }
            result.push(parseFloat(remainingAmount.toFixed(2)));
            return result;
        }
​
        // 示例用法
        const totalAmount = 100; // 总金额
        const num = 10; // 红包数目
        const redPackets = generateRandomRedPacket(totalAmount, num);
        console.log(redPackets);

手写:缓冲池!!!!!!!!!!!

有一个缓冲池,最多可以并发执行五个进程,且可以实现每完成一个进程就执行下一个进程 当时没有理解题目意思,结果用Promise.all来实现了,虽然可以完成并发,但是不能实现每完成一个进程就执行下一个,因为并没有把进程存下来,也就是没有实现缓冲的效果。

 // 模拟要执行的任务,这里用 setTimeout 来模拟异步任务
        function simulateTask(taskId) {
            return new Promise(resolve => {
                setTimeout(() => {
                    console.log('Task', taskId, 'completed');
                    resolve();
                }, Math.random() * 1000); // 模拟随机执行时间
            });
        }
        const tasks = Array.from({ length: 20 }, (_, i) => i + 1); // 假设有 20 个任务
        console.log(tasks);
        const maxConcurrency = 5;
        const buffer = [];
        async function executeTasks() {
            for (const taskId of tasks) {
                buffer.push(taskId);         
                while (buffer.length > 0 && buffer.length <= maxConcurrency) {
                    const currentTaskId = buffer.shift(); // 从缓冲池中取出一个任务
                    await simulateTask(currentTaskId); // 执行任务
                }
            }
        }
        executeTasks();

style中的scoped是怎么实现的,作用

用于实现样式的局部作用域。该属性的作用是将当前标签下的样式私有化,仅对当前组件起作用

scoped 属性的实现原理是通过给每个被编译的(样式规则)css选择器添加一个唯一的属性选择器,这个属性选择器会基于当前组件的生成一个唯一标识符。 具体来说,当 Vue 编译带有 scoped 属性的样式时,在编译时

当前组件和子组件的最外层的dom节点添加一个不重复的data自定义属性(例如: data-v-5558831a)来 唯一 标识这个dom 元素; 在每个css选择器中添加一个当前组件的data属性选择器(例如:[data-v-5558831a])来私有化样式 使得组件中的样式互不干扰;实现一个样式的局部作用域。

<templete> <div class='test'>hello!</div> </templete>

<style scoped> .test{color:red;} </style>

那么在编译后,样式规则将会变成类似于以下的形式:

缺点

虽然这样做保证样式只对当前组件起作用,不造成全局污染,但是于此同时 在我们使用第三方插件(eg:vant)的时候,想要修改其中的样式时—>若是我们写在带有scoped的style中时,默认会在选择器上加一个属性,这样就修改不到子元素的身上(无法修改子组件的样式);

如何改变呢?

script标签中的defer属性

async: 异步加载对应的javascript脚本,不阻塞HTML页面的渲染,当对应的javascript加载完成后,如果此时HTML页面还未加载完成,那么会阻塞页面的渲染,等javascript执行完成后再继续HTML页面的加载。

defer: 异步加载对应的javascript脚本,不阻塞HTML页面的渲染,当对应的javascript加载完成后,如果此时HTML页面还未加载完成,那么不会阻塞页面的渲染,等HTML页面加载完成后再接着执行加载完成的javascript脚本。

协商缓存与命中缓存的区别

返回的http状态码(200和304)

在 HTTP 缓存机制中,有两种常见的缓存控制方式:强缓存和协商缓存

1.强缓存:

  • 强缓存是通过在响应头中设置 Cache-Control 和 Expires 字段来实现的。

  • 当浏览器发起请求时,会先检查本地缓存,如果缓存未过期(根据 Expires 或 Cache-Control 中的 max-age 判断),浏览器将直接使用本地缓存,不再向服务器发起请求,从而加快页面加载速度。

  • 如果缓存过期,浏览器会向服务器发起请求,服务器会根据请求头中的 If-Modified-Since 或 If-None-Match 来验证缓存是否仍然有效,如果有效,则返回 304 Not Modified,浏览器继续使用本地缓存;如果无效,则返回新的资源内容。

2.协商缓存(HTTP 提升缓存):

  • 协商缓存是通过在响应头中设置 Last-Modified 和 ETag 字段来实现的。

  • 当浏览器发起请求时,会先检查本地缓存,如果缓存未过期,浏览器会向服务器发起请求,但不会传递实际的资源内容,而是传递一个表示上次修改时间或者实体标签的值(If-Modified-Since 或 If-None-Match)。

  • 服务器收到请求后,会根据传递的值判断资源是否发生了变化,如果资源未发生变化,则返回 304 Not Modified,浏览器继续使用本地缓存;如果资源发生了变化,则返回新的资源内容。

比于强缓存,协商缓存更加灵活,可以在资源更新时进行有效的缓存控制,避免了每次都需要重新下载资源的情况。

但都可以有效地减少网络请求次数和加快页面加载速度。

DOM节点怎么触发事件的?

DOM节点通过触发事件来响应用户的交互或者其他操作。

1.选择 DOM 节点:首先,需要选择要触发事件的 DOM 节点。这可以通过 JavaScript 中的 document.querySelector、document.getElementById 等方法来实现,或者直接通过 HTML 中的事件属性来指定。

2并直接调用了它的 `click()` 方法,从而触发了点击事件。
​
// 选择要触发事件的 DOM 节点 var button = document.getElementById('myButton'); // 触发点击事件 button.click();
2.或者给他绑定一个点击事件 然后出发他的点击事件
// 选择要触发事件的 DOM 节点
var button = document.getElementById('myButton');
​
// 定义点击事件的处理函数
function handleClick(event) {
    console.log('Button clicked!');
    console.log('Event details:', event);
}
​
// 绑定点击事件
button.addEventListener('click', handleClick);
2.创建事件对象:接下来,需要创建一个事件对象。在 JavaScript 中,可以使用 Event 对象或者其子类(如 MouseEvent、KeyboardEvent 等)来创建一个特定类型的事件对象。
3.初始化事件对象:在创建事件对象后,可能需要初始化一些相关属性,例如事件的类型、是否冒泡、是否可以取消等。
4.触发事件:一旦创建并初始化了事件对象,就可以通过调用 DOM 节点的 dispatchEvent 方法来触发事件。该方法接受一个事件对象作为参数,然后触发相应的事件。
// 选择要触发事件的 DOM 节点
var button = document.getElementById('myButton');
​
// 创建点击事件对象
var clickEvent = new MouseEvent('click', {
    bubbles: true,
    cancelable: true,
    view: window
});
​
// 触发点击事件
button.dispatchEvent(clickEvent);

在这个示例中,首先选中了一个 ID 为 myButton 的按钮元素,然后创建了一个点击事件对象,并通过 dispatchEvent 方法触发了该点击事件。 需要注意的是,触发事件并不一定会导致实际的用户交互行为,例如点击事件的触发并不会模拟用户的点击动作,而是触发与点击事件相关的监听器函数。

3.react fiber 架构的改动产生了哪些影响

从架构角度来看,Fiber 是对 React核心算法(即调和过程)的重写

从编码角度来看,FiberReact内部所定义的一种数据结构,它是 Fiber树结构的节点单位,也就是 React 16 新架构下的虚拟DOM

提高 React 应用的性能和响应性,尤其是在处理大量动态内容时。

react中,主要做了以下的操作:

  • 为每个增加了优先级,优先级高的任务可以中断低优先级的任务。然后再重新执行优先级低的任务

  • 增加了异步任务,调用requestIdleCallback api,浏览器空闲的时候执行

  • dom diff树变成了链表,一个dom对应两个fiber链表,一个用于当前渲染任务,另一个用于跟踪需要更新的组件,这都是为找到被中断的任务,重新执行,还可以实现实现渐进式渲染和更高效的任务调度

  • 在React的协调过程中,Virtual DOM Diff算法用于比较前后两个Virtual DOM树的差异,并生成一组需要更新、创建或删除的操作指令。这个算法的核心目标是在最小化操作的同时,实现高效的更新。 为了实现高效的更新,React引入了Fiber架构Fiber把协调工作拆分为较小的任务单元,并为每个任务单元(也被称为“Fiber”)建立一个链表结构。每个Fiber节点都代表了组件树中的一个组件。 当组件开始协调过程时,React会创建两个Fiber链表——一个用于当前渲染任务,另一个用于跟踪需要更新的组件(被称为“工作链表”或“提交链表”)。 生成这些链表的目的是为了找到被中断的任务,并在下一次渲染时恢复它们。

    当应用程序执行到某个时间片结束时,React会暂停协调过程,并检查是否有更高优先级的任务需要执行。如果是,则React会丢弃当前任务链表,并使用工作链表来重新协调。 通过将协调工作拆分成小的任务单元、建立Fiber链表并跟踪需要更新的组件,React可以实现更细粒度的任务切换和调度,从而提高渲染性能和响应性。 需要注意的是,生成两个Fiber链表并不是专门为了找到被中断的任务,而是为了实现渐进式渲染和更高效的任务调度。在React的更新过程中,协调工作是根据需要进行的,而不是特定于中断任务的情况。

=========================

  1. 增强的渲染性能和用户体验 Fiber 引入了对渲染任务的分片和优先级分配,使得 React 可以在渲染过程中根据任务的优先级暂停、继续或中止渲染任务。这意味着 React 可以在繁忙的更新过程中保持应用的响应性,提升了用户体验。

  2. 更灵活的渲染调度 通过引入了一个新的协调引擎,Fiber 使得 React 可以更灵活地调度更新任务,使开发者能够控制哪些更新应该优先处理,哪些可以延后处理。这种能力对于优化大型应用的性能非常关键。

  3. 支持增量渲染 Fiber 架构允许 React 将渲染工作拆分成多个小任务,这些小任务可以插入到主线程的空闲时段执行,而不是一次性完成。这种增量渲染减少了页面的卡顿现象,尤其是在复杂更新时。

  4. 更好的错误处理 Fiber 架构引入了错误边界,允许开发者更好地处理 JavaScript 错误,捕获组件树中的错误,防止整个应用崩溃,并能够渲染备用 UI 来提升用户体验。

  5. 改进的组件生命周期方法 为了配合新的渲染策略,Fiber 引入了新的生命周期方法(如 getDerivedStateFromProps 和 getSnapshotBeforeUpdate),并废弃了一些旧的生命周期方法(如 componentWillMount,componentWillReceiveProps,componentWillUpdate)。这些更改就是让我们采用更安全和更可预测的方式来编写组件。

  6. 支持并发模式和Suspense 虽然并发模式和 Suspense 不是 Fiber 架构独有的特性,但 Fiber 为这些高级功能的实现提供了基础。并发模式允许 React 在渲染过程中执行多个任务,而 Suspense 提供了一种新的方式来处理组件的异步加载,从而进一步改善了应用的响应性和用户体验。

4.vue为什么用vDom

DOM是很慢的,其元素非常庞大,页面的性能问题,大部分都是由DOM操作引起的

真实的DOM节点,哪怕一个最简单的div也包含着很多属性,

所以,dom的操作是很昂贵的,频繁操作还是会出现页面卡顿,影响用户的体验

虚拟 DOM 是一个轻量级的 Js对象树,它与实际的 DOM 结构是一一对应的,但只是在内存中存在,并不直接操作浏览器中的 DOM。

1.性能优化: 虚拟 DOM 允许 Vue 在内存中进行对比和计算,然后批量更新到真实 DOM 中,从而减少了频繁的 DOM 操作,实现了一个性能优化的效果。

2.跨平台兼容性: Vue 的虚拟 DOM 可以在不同平台上运行,包括浏览器、服务器端渲染(SSR)、原生应用等。通过统一的虚拟 DOM 抽象层,Vue 可以在不同环境中保持一致的开发体验和性能表现。

3.更简洁的代码逻辑: 使用虚拟 DOM 可以将视图更新抽象为纯粹的 JS操作,而不用直接操作 DOM。这使得代码更加简洁、可维护性更高,并且可以方便地应用函数式编程的思想。

4.方便的状态管理: 虚拟 DOM 允许 Vue 在组件状态发生变化时快速计算出需要更新的部分,从而实现更高效的状态管理和更新策略。

很多人认为虚拟 DOM 最大的优势是 diff 算法,减少 JavaScript 操作真实 DOM 的带来的性能消耗。虽然这一个虚拟 DOM 带来的一个优势,但并不是全部。虚拟 DOM 最大的优势在于抽象了原本的渲染过程,实现了跨平台的能力,而不仅仅局限于浏览器的 DOM,可以是安卓和 IOS 的原生组件,可以是小程序啥的

比如说:

data里面定义count ; methods里面定义方法 。

比如说:有一个计数器组件,其中 count 是一个数据属性,用于存储当前计数值。increment 方法用于增加 count 的值。当点击按钮时,会调用 increment 方法来增加计数值。 Vue.js会在内部将数据状态与DOM元素进行绑定,并通过虚拟DOM的机制进行比对,只更新需要更新的部分。这使得状态管理变得更加方便,我们只需要关注数据状态的变化,而不需要直接操作DOM。当 count 的值发生变化时,Vue会自动更新页面上与 count 相关的部分,而不需要我们手动操作DOM元素。

假设有一个计数器组件,点击按钮时会增加计数值,并且在页面上显示。使用虚拟DOM,你可以这样处理:

《template》
  《div》
    《p》Count: {{ count }}《/p》
    《button @click="increment"&gt;Increment《/button》
  《/div》
《/template》
​
《script》
export default {
  data() {
    return {
      count: 0
    };
  },
  methods: {
    increment() {
      this.count++;
    }
  }
};
《/script》

#

函数式组件和类组件的优缺点?

函数式组件代码简单,无状态组件,可以更好地性能优化。useEffect代替生命周期,usestate状态管理

类组件有状态和生命周期,兼容性比较好,可以实现复杂逻辑

函数式组件: 优点:

1.写法简洁: 函数式组件通常比类组件更加简洁明了,代码量更少,易于理解和维护。 2.性能优化: 函数式组件本身没有生命周期和状态,因此在某些情况下可以更好地进行性能优化,例如使用 React 的 memo 函数进行组件的浅比较,避免不必要的重新渲染。 3.适合无状态组件: 对于只依赖于 props 输入并返回 JSX 的简单组件,函数式组件是更为合适的选择。

缺点:

4.缺少生命周期和状态: 函数式组件在某些场景下不能使用生命周期方法和状态,这使得它们不适合处理复杂的交互逻辑或需要管理状态的组件。 5.难以实现复杂逻辑: 对于复杂的组件逻辑,函数式组件可能会导致代码结构变得复杂,可读性和维护性降低。

类组件: 优点:

1.有状态和生命周期: 类组件可以通过继承 React.Component 类来拥有状态和生命周期方法,使得它们更适合处理复杂的交互逻辑和状态管理。 2.更多功能: 类组件可以使用 React 的所有特性,包括生命周期方法、状态、实例方法等,提供了更多的功能和灵活性。 3.较好的兼容性: 由于类组件是 React 早期的主要编写方式,因此在某些场景下,特别是在需要使用旧版生命周期或混合使用 Hooks 和类组件时,类组件具有更好的兼容性。

缺点:

1.代码冗余: 类组件的代码通常会比函数式组件更冗长,因为需要定义类和方法,这使得代码看起来更加臃肿。 2.学习曲线:类组件可能有较高的学习曲线,因为需要理解类和面向对象编程的概念。

====================

对于简单的无状态组件,函数式组件是一个不错的选择;

而对于复杂的交互逻辑和状态管理,类组件可能更合适。

同时,随着 React Hooks 的出现和普及,函数式组件的使用已经得到了进一步推广,而 Hooks 也在一定程度上弥补了函数式组件的一些不足之处。

编写形式:

状态管理

hooks出来之前,函数组件就是无状态组件,不能保管组件的状态,不像类组件中调用setState

如果想要管理state状态,可以使用useState

在使用hooks情况下,一般如果函数组件调用state,则需要创建一个类组件或者state提升到你的父组件中,然后通过props对象传递到子组件

#生命周期

在函数组件中,并不存在生命周期,这是因为这些生命周期钩子都来自于继承的React.Component

所以,如果用到生命周期,就只能使用类组件

但是函数组件使用useEffect也能够完成替代生命周期的作用,这里给出一个简单的例子:

上述简单的例子对应类组件中的componentDidMount生命周期

如果在useEffect回调函数中return一个函数,则return函数会在组件卸载的时候执行,正如componentWillUnmount

ES module和common JS规范的区别?

import编译时解析 ,不会污染全局作用域,支持静态分析,现代浏览器原生支持。

1.语法区别:

ES module: 使用 import 和 export 关键字来导入和导出模块。 // 导入模块 import { func } from './module.js';

// 导出模块 export function func() { /* function body */ }

2.CommonJS: 使用 require() 来导入模块,使用 module.exports 或 exports 导出模块。 // 导入模块 const module = require('./module.js');

// 导出模块 module.exports = { func };

3.加载时机:

ES module: import在编译时静态解析模块依赖关系。 CommonJS: require在运行时动态加载模块。

4.作用域:

ES module: 模块中的变量是在模块级别作用域中,import不会污染全局作用域。 CommonJS: 模块中的变量是在模块级别作用域中,require但会污染全局作用域。

5.循环依赖处理:

ES module: 支持静态分析,可以处理循环依赖。 CommonJS: 不支持静态分析,处理循环依赖会有问题。

(例如模块A引用了模块B,而模块B又引用了模块A。这种情况下,如果没有正确处理循环依赖,可能会导致模块加载和执行时的一些问题。)

6.浏览器支持:

ES module: import现代浏览器原生支持。 CommonJS: require主要用于 Node.js 环境。

总的来说,ES module 更适合于现代 JavaScript 开发,因为它具有更好的性能和可靠性,并且能够在浏览器和 Node.js 环境中使用。而 CommonJS 主要用于 Node.js,不过也可以通过工具转换成适用于浏览器的代码。

HTTP2.0和HTTP1.x的区别?

2.0就是为了解决1.0高延迟,效率低的缺点

  • Http1.0

HTTP1.0默认使用 Connection:cloose,浏览器每次请求都需要与服务器建立一个 TCP 连接,服务器处理完成后立即断开 TCP 连接(无连接),服务器不跟踪每个客户端也不记录过去的请求(无状态)。

Http1.1 keep-alive(长连接),避免了连接建立和释放的开销,减少服务器压力,可以同时并行多个请求,不需要一个接一个的等待响应;通过 Content-Length 字段来判断当前请求的数据是否已经全部接受。不允许同时存在两个并行的响应。

但是他也有缺点,就是高延迟,效率低

Http2.0 基于SPDY,目标是在用户和网站直接只用一个连接。

(1)二进制传输

http2.0将请求和响应数据分割为更小的帧,并采用二进制格式进行传输和解析相比于 HTTP/1.x 的文本协议,具有更高效的解析速度和容错性。多个帧之间可以乱序发送。

(2)Header压缩

Http2.0开发了专门的“HPACK”算法,大大压缩了Header信息。减少了数据传输时的带宽占用和网络延迟。这尤其对包含大量重复头部信息的请求(如请求多个图片或脚本文件)的性能提升效果显著。

在HTTP/1.0中,通信使用纯文本格式,这意味着每个HTTP请求和响应都会包含大量的文本数据,其中包括头部信息和正文内容。头部信息包含有关请求或响应的元数据,如请求方法、URL、状态码、内容类型等。虽然纯文本格式容易理解和调试,但它也存在一些缺点,其中之一就是头部信息的重复传输会导致不必要的网络带宽消耗和延迟。为了解决这个问题,HTTP/2引入了头部压缩技术,可以显著减少头部信息的大小,从而提高通信效率。

(3)多路复用

多路复用是指在同一个 TCP 连接上同时发送和接收多个请求和响应

。这样一来,就不再需要为每个请求建立新的连接,而是可以复用现有的连接,减少了连接的开销和延迟,提高了网络通信的效率。

很好的解决了浏览器限制同一个域名下的请求数量的问题

多路复用技术可以只通过一个TCP链接就可以传输所有的请求数据,允许在同一个 TCP 连接上同时发送多个请求和响应,而无需按顺序进行等待和响应。这提高了资源利用率,减少了延迟,特别是在高延迟和高丢包率的网络环境下。

(4)服务端推送

允许服务器在客户端请求之前主动推送资源给客户端。这样可以减少客户端发起的请求次数,提高页面加载速度。(例如,浏览器在刚请求html的时候就提前把可能会用到的JS,CSS文件发送给客户端,减少等待延迟,这被称为“服务端推送”)

总的来说,HTTP/2.0 相对于 HTTP/1.x 在性能和效率上有明显的提升,尤其是在高延迟和高丢包率的网络环境下,能够更好地提供快速和可靠的网络传输服务。

————————————————

HTTP2.0缺点

(1)TCP以及TCP+TLS建立连接的延迟(握手延迟)

(2)HTTP/2.0 虽然支持多路复用,允许多个请求在同一个 TCP 连接上并行传输,但是在遇到任何一个数据包丢失时,整个 TCP 连接的数据都会受到影响,直到丢失的包被重新传输成功,这就是所谓的队头阻塞。

因为HTTP2.0存在这些缺点,所以出现了HTTP3.0。

二进制传真 头部压缩 谁快 他俩的作用:

2.作用:二进制传真是一种数据传输技术,通常用于传输图像或文档。它通过将文档转换为二进制数据,并使用调制解调器将二进制数据传输到接收端,然后再将二进制数据解码还原为原始文档或图像。二进制传真主要用于传输图像和文档,通常在传真机或传真软件中使用。 3.速度:二进制传真的速度取决于传输的数据量、调制解调器的速度和通信线路的质量。一般来说,它的传输速度可能会比较慢,尤其是在传输大型文件或图像时。

4.头部压缩(Header Compression):

5.作用:头部压缩是一种网络通信优化技术,用于减少 HTTP 请求和响应中头部信息的大小,从而减少网络带宽的消耗和提高通信效率。HTTP/2 中采用的头部压缩技术是 HPACK 算法。它通过使用索引表、动态表和静态表来对头部信息进行压缩,从而减少了重复头部信息的传输。 6.速度:头部压缩可以显著减少 HTTP 请求和响应的大小,从而加快数据传输速度。尤其是在移动网络或带宽受限的环境下,头部压缩可以大大提高通信效率。

总的来说,二进制传真和头部压缩是两种不同领域的技术,各自在传输图像或文档、优化网络通信方面发挥作用。虽然它们的速度和效率取决于不同的因素,但都可以帮助提高数据传输的速度和效率。

怎么理解多路复用 用什么连接 ?

多路复用是指在同一个 TCP 连接上同时发送和接收多个请求和响应。在传统的 HTTP/1.x 中,每个请求都需要建立一个独立的 TCP 连接,这会导致连接的开销和延迟,尤其在加载多个资源时会产生额外的网络开销。 而在 HTTP/2 中,通过多路复用的机制,客户端和服务器可以在同一个 TCP 连接上并行发送和接收多个请求和响应。这样一来,就不再需要为每个请求建立新的连接,而是可以复用现有的连接,减少了连接的开销和延迟,提高了网络通信的效率。 多路复用的实现原理如下:

1.客户端将多个请求并行发送到服务器,这些请求可以同时通过同一个 TCP 连接发送。 2.服务器收到这些请求后,可以同时处理它们,并将响应按照请求的顺序返回给客户端。 3.客户端接收到响应后,根据响应的标识符将它们分发给相应的请求。

通过多路复用,可以减少因建立和销毁多个 TCP 连接而产生的开销,提高网络通信的效率。这对于现代 Web 应用程序来说尤其重要,因为现代 Web 应用程序通常会加载大量的资源,如 HTML、CSS、JavaScript 文件、图像等,而多路复用可以帮助加快这些资源的加载速度,提升用户体验。 总之,多路复用利用了 TCP 连接的特性,在同一个连接上同时处理多个请求和响应,从而提高了网络通信的效率。

二进制传真 怎么实现

npm install的过程具体做了哪些事情?

1.读取 package.json: 首先,npm 会读取项目根目录下的 package.json 文件,该文件中包含了项目的依赖信息,包括依赖的名称、版本号以及其他配置信息。

2.解析依赖关系: npm 根据 package.json 文件中的依赖信息,解析出项目所依赖的所有包及其版本号。它会根据版本号信息生成一个依赖树,确保安装的每个包都符合依赖版本的要求。 3.安装依赖包: 接下来,npm 会开始安装依赖包。它会根据解析出的依赖树,从 npm 仓库中下载每个依赖包的压缩包(或者从本地缓存中获取),然后解压缩到项目的 node_modules 目录下。 4.执行安装钩子: 在安装过程中,npm 会执行一系列的安装钩子,包括 preinstall、postinstall 等,允许开发者在安装过程中执行自定义的脚本或者命令。 5.保存依赖信息: 安装完成后,npm 会更新 package.json 文件中的 dependencies 或 devDependencies 字段,将安装的依赖信息写入 package.json 文件,以便下次执行 npm install 时能够根据该文件恢复依赖关系。 6.生成 package-lock.json(可选): 如果项目中存在 package-lock.json 文件,npm 会根据安装过程生成或更新该文件,用于锁定依赖包的版本,确保在多次安装时能够安装相同的依赖版本,保证项目的一致性和稳定性。 7.安装全局包(可选): 如果使用了 -g 或 --global 参数,npm 会将依赖包安装到全局环境中,而不是项目的 node_modules 目录下。

总的来说,npm install 的过程主要包括读取 package.json、解析依赖关系、下载安装依赖包、执行安装钩子、保存依赖信息和生成 package-lock.json。

=====

微派网络一面

1.前端在项目开发中扮演的角色 可以做哪些前端以外的贡献

在项目开发中,前端工程师通常扮演以下几个角色,并且可以在项目中做出许多前端以外的贡献:

1.界面设计与交互体验优化: 前端可以与设计团队合作,参与界面设计和用户体验优化。可以提供技术上的建议,以确保设计的可实现性和保证下用户体验。

2.性能优化与页面加载速度提升: 还可以贡献于项目的性能优化工作。他们可以通过优化代码结构、减少资源加载时间、使用合适的技术栈等方式来提升页面的加载速度和性能表现。

====================================以外的=========================================

3.跨团队沟通与协调: 前端工程师通常需要与后端工程师、设计师、产品经理等团队成员紧密合作。他们可以在项目中担任沟通桥梁的角色,促进团队成员之间的协作和信息共享。

4.质量保证与测试: 前端工程师可以参与项目的质量保证工作,包括进行代码审查、解决 bug 等。他们可以通过测试和审查确保项目的稳定性和可靠性。

5.技术调研与新技术应用: 前端工程师可以贡献于项目的技术调研工作,探索新的前端技术和工具,并在适当的情况下应用到项目中,以提升项目的技术水平和竞争力。

6.文档编写与知识分享: 前端工程师可以编写技术文档,记录项目的架构设计、技术选型、使用方法等,以便团队成员之间的知识共享和传承。

2.做完项目带给自己的收获 不只是技术上的

一.沟通能力提升+如何快速熟悉业务很重要+还交到了很好的前辈朋友

沟通:

实习嘛,就是要在有限的条件里学到更多的东西。那沟通能力其实也很重要

1.比如说:有不懂不清楚的地方,及时问,不要不懂装懂,很影响开发效率。

要用言简意赅的表达能让别人听懂我们想问的点;

其次,是提高问问题的质量,在问问题之前要在脑子里有自己的想法或者大致的解决方案,不至于在请教沟通的过程中脑袋空空,只顾头而听不懂更深层次的内容;

最后,如果需要问的问题多且零散,我觉得要攒一定数量的问题后一起请教,另外,可以将所问问题和思考点形成文档,这样问问题时更直观、方便,也有利于对得到答案进行记录。

开会的时候要进行记录,把重要的东西记录下来,以便后期开展工作以及合理安排排期

2.然后因为身为实习生,大多数是杂活,难度没那么高的,但是我觉得我想要真正的参与到项目需求里面,所以说就主动和领导说,有没有机会能参与项目需求,想要学到很多东西,然后呢,后面就真的接到了一个项目需求。就是我觉得有什么诉求,勇敢的说出来,机会是自己争取的。

=================================================================================

二、学会了如何学习并且快速掌握业务知识

(1)可以多看prd需求文档,因为我们有的需求一般是有进步的版本,从当前要更新的最新版本看到以前的2个版本,就差不多能很理解项目需求了,只有充分的理解了项目需求,工作才会有效率

(2)积极主动的跟业务,产品后端沟通,尽量约线下面都面的交流。这样效率比教高

(3)还要多多参加需求方案会,可以了解到更多的业务细节

还有一点好的就是养成了写文档的习惯,做点啥我都想把他记录下来,感觉总结下来了就是赚到了,以后就不会再踩坑了。 问的话 就说事件和打包文件或者虚拟滚动

2.学习能力提升

学会了使用react-color,echarts,虚拟滚动,封装组件,封装可重用方法,代码规范

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值