2023.10.21 更新前端面试问题总结(16道题)

379 阅读24分钟

2023.10.02 - 2023.10.21 更新前端面试问题总结(16道题)
获取更多面试相关问题可以访问
github 地址: github.com/pro-collect…
gitee 地址: gitee.com/yanleweb/in…

目录:

  • 中级开发者相关问题【共计 8 道题】

    • 586.[React] react router 主要包有哪些,主要 api 有哪些?【web框架】【出题公司: 阿里巴巴】
    • 588.全局样式命名冲突和样式覆盖问题怎么解决?【热度: 772】【CSS】【出题公司: 腾讯】
    • 589.css module 是什么?【热度: 346】【CSS】【出题公司: 腾讯】
    • 591.[React] useLayoutEffect 和 useEffect 有什么区别?【热度: 313】【web框架】【出题公司: 腾讯】
    • 595.[Vue] 响应式为何要从 Object.defineProperty 改为 proxy?【热度: 352】【工程化】【出题公司: 阿里巴巴】
    • 599.[代码实现] 不使用 setTimeout 来实现 setInterval【热度: 231】【代码实现/算法】【出题公司: 腾讯】
    • 600.[代码实现] 手写 dom 分段渲染【热度: 280】【代码实现/算法】【出题公司: 阿里巴巴】
    • 601.[代码实现] 手写数组降维flat方法【热度: 244】【代码实现/算法】【出题公司: 阿里巴巴】
  • 高级开发者相关问题【共计 8 道题】

    • 587.[React] 如何实现转场动画?【web框架】【出题公司: 阿里巴巴】
    • 590.[React] 如何避免不必要的渲染?【热度: 632】【web框架】【出题公司: 腾讯】
    • 592.在 webpack 中,通常用于 css 提取的工具是什么?【热度: 269】【工程化】【出题公司: 腾讯】
    • 593.在你的项目中, 使用过哪些 webpack loader, 说一下他们的作用【热度: 361】【工程化】【出题公司: 阿里巴巴】
    • 594.在你的项目中, 使用过哪些 webpack plugin, 说一下他们的作用【热度: 361】【工程化】【出题公司: 阿里巴巴】
    • 596.为何 http2 非常快速的就过度到了 HTTP3 ?【热度: 945】【网络】【出题公司: 腾讯】
    • 597.http1.1 的 keep-alive 和 http2 的多路复用 有什么区别?【热度: 87】【网络】【出题公司: 腾讯】
    • 598.PM2 部署 nodejs 有哪些优势?【热度: 199】【Nodejs】【出题公司: 腾讯】

中级开发者相关问题【共计 8 道题】

586.[React] react router 主要包有哪些,主要 api 有哪些?【web框架】【出题公司: 阿里巴巴】

React Router是React官方提供的用于构建单页应用的路由库,主要包括以下几个主要包和API:

主要包:

  1. react-router-dom:用于Web应用的路由库。
  2. react-router-native:用于原生应用(如React Native)的路由库。
  3. react-router-config:用于配置静态路由的工具包。

主要API:

  1. BrowserRouter:一个使用HTML5 history API实现的路由器组件,用于在Web应用中处理路由。
  2. HashRouter:一个使用URL hash值实现的路由器组件,用于在不支持HTML5 history API的Web应用中处理路由。
  3. Route:定义了路由匹配规则及对应的组件,可以在路由器中使用。
  4. Switch:用于渲染与当前URL匹配的第一个Route或Redirect,只能包含Route或Redirect组件。
  5. Link:用于创建导航链接,点击后会更新URL,触发路由的切换。
  6. NavLink:与Link类似,但在匹配当前URL时会添加指定的样式。

其他常用API:

  1. Redirect:用于重定向到指定的路由。
  2. withRouter:高阶组件,用于将路由器的相关信息(如history、location)传递给被包裹的组件。
  3. useHistory:自定义hook,用于在函数式组件中获取history对象。
  4. useLocation:自定义hook,用于在函数式组件中获取location对象。
  5. useParams:自定义hook,用于在函数式组件中获取路由参数。
  6. useRouteMatch:自定义hook,用于在函数式组件中获取与当前URL匹配的路由信息。

以上是React Router的主要包和API。根据具体的需求,你可以使用这些API来构建和处理路由相关的逻辑。

588.全局样式命名冲突和样式覆盖问题怎么解决?【热度: 772】【CSS】【出题公司: 腾讯】

关键词:全局样式命名冲突

在前端开发过程中,有几种常见的方法可以解决全局样式命名冲突和样式覆盖问题:

  1. 使用命名空间(Namespacing):给样式类名添加前缀或命名空间,以确保每个组件的样式类名不会冲突。例如,在一个项目中,可以为每个组件的样式类名都添加一个唯一的前缀,例如.componentA-button 和.componentB-button,这样可以避免命名冲突。
  2. 使用BEM命名规范:BEM(块、元素、修饰符)是一种常用的命名规范,可以将样式类名分成块(block)、元素(element)和修饰符(modifier)三个部分,以确保样式的唯一性和可读性。例如,.button 表示一个块,.button__icon表示一个元素,.button--disabled表示一个修饰符。
  3. 使用CSS预处理器:CSS预处理器(如Sass、Less)可以提供变量、嵌套规则和模块化等功能,可以更方便地管理样式并避免命名冲突。例如,可以使用变量来定义颜色和尺寸,使用嵌套规则来组织样式,并将样式拆分成多个模块。
  4. 使用CSS模块:CSS模块提供了在组件级别上限定样式作用域的能力,从而避免了全局样式的冲突和覆盖。每个组件的样式定义在组件内部,使用唯一的类名,确保样式的隔离性和唯一性。
  5. 使用CSS-in-JS解决方案:CSS-in-JS是一种将CSS样式直接写入JavaScript代码中的方法,通过将样式与组件绑定,可以避免全局样式的冲突问题。一些常见的CSS-in-JS解决方案包括Styled Components、Emotion和CSS Modules with React等。

589.css module 是什么?【热度: 346】【CSS】【出题公司: 腾讯】

关键词:css module 概念、css module 作用

CSS Modules 是一种用于组织和管理 CSS 的技术。它通过在编译时为每个 CSS 类名生成唯一的标识符,并将它们作为 JavaScript 对象的属性导出。这样,可以确保每个类名在整个应用程序中的唯一性,避免样式冲突。

使用 CSS Modules,可以将 CSS 文件与组件文件绑定在一起,这样每个组件都有自己的 CSS 作用域,样式只会应用于特定的组件,不会影响其他组件。这种隔离性和局部作用域有助于降低样式冲突和维护 CSS 的复杂性。

CSS Modules 还提供了一些其他功能,例如:

  1. 局部作用域: CSS Modules 允许在组件中定义局部样式,这些样式仅适用于该组件。这样,可以避免全局样式造成的副作用,并使组件更加可重用。
  2. 类名和样式的映射: 使用 CSS Modules,可以通过导入生成的样式对象,将类名映射到组件中的类名,并将其应用于相应的元素。这样可以方便地将样式与组件关联起来,并跟踪样式的变化。
  3. 继承和组合: CSS Modules 支持继承和组合样式。可以通过使用类名组合和继承规则,将多个样式应用于同一个元素或组件。

总结来说,CSS Modules 提供了一种更可靠和可维护的方式来管理 CSS,通过实现局部作用域和唯一类名标识符,帮助开发者避免样式冲突和提高样式的可重用性。

591.[React] useLayoutEffect 和 useEffect 有什么区别?【热度: 313】【web框架】【出题公司: 腾讯】

关键词:useLayoutEffect 和 useEffect 区别

useLayoutEffect 和 useEffect 的主要区别在于它们执行的时机。

  • useLayoutEffect: useLayoutEffect 是在 DOM 更新完成但在浏览器绘制之前同步执行的钩子函数。它会在 DOM 更新之后立即执行,阻塞浏览器的绘制过程。这使得它更适合于需要立即获取最新 DOM 布局信息的操作,如测量元素尺寸或位置等。使用 useLayoutEffect 可以在更新后同步触发副作用,从而保证 DOM 的一致性。
  • useEffect: useEffect 是在组件渲染完毕后异步执行的钩子函数。它会在浏览器完成绘制后延迟执行,不会阻塞浏览器的绘制过程。这使得它更适合于处理副作用操作,如发送网络请求、订阅事件等。使用 useEffect 可以将副作用操作放到组件渲染完成后执行,以避免阻塞浏览器绘制。

总结:

  • useLayoutEffect 是同步执行的钩子函数,在 DOM 更新后立即执行,可能会阻塞浏览器的绘制过程;
  • useEffect 是异步执行的钩子函数,在浏览器完成绘制后延迟执行,不会阻塞浏览器的绘制过程。

通常情况下,应优先使用 useEffect,因为它不会阻塞浏览器的渲染,并且能够满足大多数的副作用操作需求。只有在需要获取最新的 DOM 布局信息并立即触发副作用时,才需要使用 useLayoutEffect。

595.[Vue] 响应式为何要从 Object.defineProperty 改为 proxy?【热度: 352】【工程化】【出题公司: 阿里巴巴】

关键词:vue Object.defineProperty、vue proxy 使用

Vue 在早期版本中使用了 Object.defineProperty 来实现响应式系统。但是,在 Object.defineProperty 中存在一些限制和局限性,导致在某些场景下无法完全满足需求。因此,Vue 在最新的版本中引入了 Proxy 来替代 Object.defineProperty

以下是一些 Proxy 相对于 Object.defineProperty 的优势:

  1. 功能更强大:Proxy 可以代理整个对象,而 Object.defineProperty 只能对已存在的属性进行拦截。使用 Proxy 可以在对象级别上进行拦截、代理、验证等操作。
  2. 更易于使用和理解:Proxy 提供了一组更直观和易于理解的 API,使开发者可以更容易地创建和管理代理。
  3. 性能优化:Proxy 针对属性的访问和修改都提供了更佳的性能优化。而 Object.defineProperty 在拦截属性访问和修改时会有一定的性能损耗。
  4. 更好的嵌套支持:Proxy 可以代理嵌套对象的属性,而 Object.defineProperty 只能对顶层对象的属性进行拦截。

总的来说,Proxy 相对于 Object.defineProperty 在功能上更强大、使用更便捷、性能更优,并且在更复杂的场景下也能提供更好的支持。因此,Vue 在新版本中选择了使用 Proxy 来实现响应式系统。

599.[代码实现] 不使用 setTimeout 来实现 setInterval【热度: 231】【代码实现/算法】【出题公司: 腾讯】

关键词:实现setInterval、requestAnimationFrame实现setInterval、setTimeout实现setInterval

如果不使用 setTimeout 来实现 setInterval,可以使用 requestAnimationFrame 函数和时间戳来实现定时循环。下面是实现的代码示例:

实现方式1

function mySetInterval(callback, interval) {
  let startTime = Date.now();
  let elapsedTime = 0;

  function loop() {
    const currentTime = Date.now();
    const deltaTime = currentTime - startTime;

    if (deltaTime >= interval) {
      callback();
      startTime = currentTime;
    }

    requestAnimationFrame(loop);
  }

  requestAnimationFrame(loop);

  return {
    clear: function() {
      startTime = 0;
      elapsedTime = 0;
    }
  };
}

这个实现中,我们通过 requestAnimationFrame 函数来循环执行 loop 函数。在 loop 函数中,我们获取当前时间戳 currentTime,并计算与上一次执行的时间间隔 deltaTime 。如果 deltaTime 大于等于指定的间隔时间 interval,则执行回调函数 callback,并更新 startTime 为当前时间,以便下一次判断。

最后,返回一个具有 clear 方法的对象,用于清除定时器。调用 clear 方法时,将 startTime 和 elapsedTime 重置为初始值。

实现方式2

const obj = {
  timer: null,
  setInterval: function(callback, interval) {
    const now = Date.now
    let startTime = now()
    let endTime = startTime
    const self = this
    const loop = function() {
      self.timer = requestAnimationFrame(loop)
      endTime = now()
      if (endTime - startTime >= interval) {
        startTime = endTime = now()
        callback && callback()
      }
    }
    this.timer = requestAnimationFrame(loop)
    return this.timer
  },
  clearInterval: function() {
    cancelAnimationFrame(this.timer)
  }
}

let count = 0
const timer = obj.setInterval(() => {
  console.log('interval...')
  count++
  if (count >= 3) {
    obj.clearInterval()
  }
}, 500)

实现方式3

使用 setTimeout 来实现

/**
 * setTimeout 版本
 */
function _setIntervalUseTimeout(
  fn: () => void,
  millisec: number,
  count?: number
) {
  let timer: number;

  function interval() {
    if (typeof count === 'undefined' || count-- > 0) {
      timer = setTimeout(interval, millisec);
      try {
        fn();
      } catch (e: any) {
        count = 0;
        throw e.toString();
      }
    }
  }

  timer = setTimeout(interval, millisec);
  return {
    clear: () => clearTimeout(timer),
  };
}

600.[代码实现] 手写 dom 分段渲染【热度: 280】【代码实现/算法】【出题公司: 阿里巴巴】

关键词:dom 分段渲染

分时函数案例:把1秒创建1000个DOM节点,改成每隔200毫秒创建10个节点,这样不用短时间在页面中创建大量的DOM。

var timeChunk = function(arr, fn, count, interval) {
  var timer = null;
  var data = null;
  var start = function() {
    for (var i = 0; i < Math.min(count || 1, arr.length); i++) {
      fn(arr.shift());
    }
  }
  return function() {
    timer = setInterval(function() {
      if (arr.length == 0) {
        clearInterval(timer);
        timer = null;
        return;
      }
      start();
    }, interval || 200)
  }
}

var arr = [];
for (var i = 0; i < 1000; i++) {
  arr.push(i);
}

var renderDOMList = timeChunk(arr, function(data) {
  var div = document.createElement('div');
  div.innerHTML = data;
  document.body.appendChild(div);
}, 10, 200);
renderDOMList();

601.[代码实现] 手写数组降维flat方法【热度: 244】【代码实现/算法】【出题公司: 阿里巴巴】

关键词:JS数组降维、reduce数组降维

原生Array.prototype.flat方法接受一个depth参数,默认值为1,depth表示要降维的维数:

输出结果:

const arr = [1, [2, 3], [4, [5, 6]]]
console.log(arr.flat(1))         // [1, 2, 3, 4, [5, 6]]
console.log(arr.flat(Infinity))  // [1, 2, 3, 4, 5, 6]

reduce + 递归实现方案

// MDN: 可查看更多flat实现方法
function flat(arr = [], depth = 1) {
  if (arr.length === 0) {
    return []
  }
  let result = []
  if (depth > 0) {
    result = arr.reduce((acc, val) => {
      return acc.concat(Array.isArray(val) ? flat(val, depth - 1) : val)
    }, [])
  } else {
    result = arr.slice()
  }
  return result
}

const arr = [1, 2, 3, [1, 2, 3, 4, [2, 3, 4]]]
const myResult1 = flat(arr, 1)
const originResult1 = arr.flat(1)
const myResult2 = flat(arr, Infinity)
const originResult2 = arr.flat(Infinity)
console.log(myResult1)      // [1, 2, 3, 1, 2, 3, 4, [2, 3, 4]]
console.log(originResult1)  // [1, 2, 3, 1, 2, 3, 4, [2, 3, 4]]
console.log(myResult2)     // [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
console.log(originResult2) // [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]

高级开发者相关问题【共计 8 道题】

587.[React] 如何实现转场动画?【web框架】【出题公司: 阿里巴巴】

这个问题非常复杂, 我这边用白话文解释一下原理, 若有不对的地方, 请大家更正:

如果没有专场动画, 那么在路由切换的一瞬间, 加载下一个路由页面的组件, 注销上一个路由页面的组件;

但是如果加上专场动画, 比如专场动画时间为 500ms, 那么, 在咋合格 500ms 过程中, 首先要加载下一个路由页面的组件, 然后加载上一个渐进的动画。 同时不能注销掉当前路由, 需要给当前路由加载一个渐出的动画。 需要当两个页面完成动画时间, 完成页面覆盖切换之后, 然后注销上一个路由页面的组件;

所以涉及到的知识点:

  1. 如何做页面跳转拦截;
  2. 如何在页面路由组件不跳转的同时, 加载下一个页面的组件;
  3. 配置页面层级;
  4. 如何执行、加载、完成专场动画;
  5. 动画结束的时候手动注销组件;

具体实现, 可以参考以下两个文档:

590.[React] 如何避免不必要的渲染?【热度: 632】【web框架】【出题公司: 腾讯】

关键词:react 渲染优化

在 React 中,有几种方法可以避免不必要的渲染,以提高性能和优化应用程序的渲染过程:

  1. 使用 PureComponent 或 shouldComponentUpdate 方法:继承 PureComponent 类或在自定义组件中实现 shouldComponentUpdate 方法,以检查组件的 props 和 state 是否发生变化。如果没有变化,则阻止组件的重新渲染。这种方式适用于简单的组件,并且可以自动执行浅比较。
  2. 使用 React.memo 高阶组件:使用 React.memo 包装函数组件,以缓存组件的渲染结果,并仅在其 props 发生变化时重新渲染。这种方式适用于函数组件,并且可以自动执行浅比较。
  3. 避免在 render 方法中创建新对象:由于对象的引用发生变化,React 将会认为组件的 props 或 state 发生了变化,从而触发重新渲染。因此,应尽量避免在 render 方法中创建新的对象,尤其是在大型数据结构中。
  4. 使用 key 属性唯一标识列表项:在渲染列表时,为每个列表项指定唯一的 key 属性。这样,当列表项重新排序、添加或删除时,React 可以更准确地确定哪些列表项需要重新渲染,而不是重新渲染整个列表。
  5. 使用 useCallback 和 useMemo 避免不必要的函数和计算:使用 useCallback 缓存函数引用,以确保只有在其依赖项发生变化时才重新创建函数。使用 useMemo 缓存计算结果,以确保只有在其依赖项发生变化时才重新计算结果。这些钩子函数可以帮助避免不必要的函数创建和计算过程,从而提高性能。
  6. 使用 React.lazy 和 Suspense 实现按需加载组件:使用 React.lazy 函数和 Suspense 组件可以实现按需加载组件,只在需要时才加载组件代码。这可以减少初始渲染时的资源负载。

592.在 webpack 中,通常用于 css 提取的工具是什么?【热度: 269】【工程化】【出题公司: 腾讯】

关键词:mini-css-extract-plugin作用、mini-css-extract-plugin使用

概念

在 webpack 中,通常使用 mini-css-extract-plugin 来提取 CSS。它是一个独立的插件,可以将 CSS 从 JavaScript 文件中提取出来,生成独立的 CSS 文件。 使用 mini-css-extract-plugin 可以优化代码分离和缓存,以及提高加载速度。

通过配置 webpack 的插件选项,可以将 mini-css-extract-plugin 添加到 webpack 构建流程中。在配置中,需要将该插件实例化,并指定输出的 CSS 文件名和路径。 一旦配置完成并运行 webpack 构建,mini-css-extract-plugin 就会将 CSS 提取到独立的文件中,而不是将其嵌入到 JavaScript 文件中。

示例代码如下:

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  // ...其他配置
  module: {
    rules: [
      // ...其他规则
      {
        test: /.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ],
};

在上述示例中,MiniCssExtractPlugin.loader 是用于提取 CSS 的 loader。css-loader 用于处理 CSS 文件的导入和解析。 MiniCssExtractPlugin则是插件实例,用于配置输出的 CSS 文件名。

基本API使用

下面是 MiniCssExtractPlugin 的常用参数及其说明:

参数名类型默认值描述
filenamestring[name].css输出的 CSS 文件名,可以包含 [name][id][contenthash] 等占位符变量,用于生成唯一的文件名。
chunkFilenamestringundefined输出的 CSS 文件名的 chunk 文件名,可以包含 [name][id][contenthash] 等占位符变量。
ignoreOrderbooleanfalse是否忽略 CSS 导入顺序。
insertfunction  stringhead用于指定 CSS 文件的插入位置。可以是字符串(headbody)或自定义函数。
publicPathstringundefined设置在 CSS 文件中使用的公共路径。
attributesobject{}附加到 link 标签的自定义属性。
chunkLoadTimeoutnumber120000加载 CSS chunk 的超时时间(毫秒)。
esModulebooleantrue是否使用 ES modules 规范导出 CSS 模块。
experimentalUseImportModulebooleanfalse是否在导出 CSS 模块时使用 import() 函数。**此选项需要 webpack 5+
才能使用。**
hmrbooleanundefined是否启用模块热替换(Hot Module Replacement)。**此选项需要 webpack 5+
才能使用。**
ignoreOrderbooleanfalse是否忽略 CSS 导入顺序。
minimizeboolean  objecttrue是否对提取的 CSS 进行压缩。可以通过传入一个对象来设置压缩的选项。使用 cssnano 进行 CSS 压缩。
sourceMapbooleanfalse是否生成 CSS 的 Source Map。
moduleFilenamefunction(getAssetPath => ${path.relative(options.context, getAssetPath('css'))})用于自定义生成的 CSS 文件路径和文件名的函数。
hotbooleanundefined是否启用热模块替换(Hot Module Replacement)。**此选项需要 webpack 4.46.0+
才能使用。**

593.在你的项目中, 使用过哪些 webpack loader, 说一下他们的作用【热度: 361】【工程化】【出题公司: 阿里巴巴】

Loader 名称作用
babel-loader将 ES6+ 代码转换为 ES5 代码,以便在旧版浏览器中运行。
css-loader解析 CSS 文件,处理 CSS 中的依赖关系,并将 CSS 转换为 JS 模块。
style-loader将 CSS 代码以内联的方式注入到 HTML 页面中。
file-loader处理文件资源(如图片、字体等),将文件复制到输出目录,并返回文件路径。
url-loader与 file-loader 类似,但可以根据文件大小将文件转换为 Data URL(base64 格式)或文件路径。
sass-loader解析 Sass/SCSS 文件,并将其转换为 CSS 代码。
less-loader解析 Less 文件,并将其转换为 CSS 代码。
postcss-loader使用 PostCSS 处理 CSS,可以进行自动添加前缀、压缩、CSS Modules 等操作。
ts-loader将 TypeScript 代码转换为 JavaScript 代码。
eslint-loader在构建过程中使用 ESLint 进行代码检查。
stylelint-webpack-plugin在构建过程中使用 Stylelint 进行 CSS/SCSS 代码检查。
vue-loader解析 Vue 单文件组件(.vue 文件),并将其转换为 JavaScript 代码。
image-webpack-loader优化图片资源,包括压缩、转换格式等操作。
html-loader解析 HTML 文件,处理其中的引用资源(如图片、字体等),并返回处理后的 HTML 代码。
markdown-loader将 Markdown 文件转换为 HTML 代码。
json-loader解析 JSON 文件,并返回解析后的 JavaScript 对象。
eslint-loader在构建过程中使用 ESLint 进行代码检查。
tslint-loader在构建过程中使用 TSLint 进行 TypeScript 代码检查。
prettier-loader在构建过程中使用 Prettier 进行代码格式化。
stylelint-webpack-plugin在构建过程中使用 Stylelint 进行 CSS/SCSS 代码检查。
mini-css-extract-plugin提取 CSS 代码到单独的文件,而不是内联到 JavaScript 代码中。
optimize-css-assets-webpack-plugin压缩 CSS 代码。
terser-webpack-plugin压缩 JavaScript 代码。

这些 Loader 可以根据需要配置在 Webpack 的模块规则(module.rules)中,以实现对不同类型文件的处理和转换操作。

594.在你的项目中, 使用过哪些 webpack plugin, 说一下他们的作用【热度: 361】【工程化】【出题公司: 阿里巴巴】

下表列出了常见的 Webpack 插件及其作用:

插件名称作用
HtmlWebpackPlugin自动生成 HTML 文件,并将打包后的资源自动注入到 HTML 中。
MiniCssExtractPlugin将 CSS 代码提取到单独的文件中,而不是内联到 JavaScript 中。
CopyWebpackPlugin将指定的文件或目录复制到输出目录。
CleanWebpackPlugin在每次构建之前清理输出目录,避免旧的文件残留。
DefinePlugin在编译过程中创建全局常量,可以在代码中直接使用。
HotModuleReplacementPlugin启用热模块更换(Hot Module Replacement),在开发过程中实现代码修改后实时更新页面,无需刷新。
ProvidePlugin自动加载模块,使模块在使用时可以直接使用对应的全局变量,无需引入。
MiniCssExtractPlugin将 CSS 代码提取到单独的文件中,而不是内联到 JavaScript 中。
OptimizeCSSAssetsPlugin压缩提取出的 CSS 文件。
uglifyjs-webpack-plugin压缩 JavaScript 代码。
webpack-bundle-analyzer分析打包后的文件大小,并可视化展示,方便优化打包结果。
CompressionWebpackPlugin使用 gzip 或其他压缩算法对文件进行压缩,减小文件大小,加快网络传输速度。
CopyWebpackPlugin将指定的文件或目录复制到输出目录。
FriendlyErrorsWebpackPlugin提供友好的构建错误提示和优化构建速度的功能。
ImageminWebpackPlugin压缩图片资源,减小文件大小,提升加载速度。
HotModuleReplacementPlugin启用热模块更换(Hot Module Replacement),在开发过程中实现代码修改后实时更新页面,无需刷新。
HtmlWebpackPlugin自动生成 HTML 文件,并将打包后的资源自动注入到 HTML 中。
IgnorePlugin忽略特定的模块,避免将其打包到最终的输出文件中。
BannerPlugin在打包的文件块顶部添加自定义的注释和信息。
webpack.DefinePlugin在编译过程中创建全局常量,可以在代码中直接使用。
webpack.ProgressPlugin在控制台输出构建进度信息。
webpack-bundle-analyzer分析打包后的文件大小,并可视化展示,方便优化打包结果。
webpackbar在命令行中显示构建进度条,提供更直观的构建进度信息。

这些插件可以根据需要配置在 Webpack 的插件列表(plugins)中,以实现对构建过程的各种增强和优化操作。

596.为何 http2 非常快速的就过度到了 HTTP3 ?【热度: 945】【网络】【出题公司: 腾讯】

关键词:http3

HTTP/2 被广泛采用后,HTTP/3 的出现是为了解决一些 HTTP/2 存在的问题以及提升性能。

HTTP/2 在性能方面确实有很大的改进,通过多路复用和头部压缩等特性,可以提高页面加载的速度和效率。然而,HTTP/2 仍然使用了基于 TCP 的传输层协议。TCP 的一些特性,如拥塞控制和传输层阻塞,可能造成延迟和性能下降。

HTTP/3 则引入了一种全新的传输层协议,即基于 UDP 的 QUIC(Quick UDP Internet Connections)。QUIC 具有更低的延迟和更好的拥塞控制,通过在应用层实现了可靠性和安全性,避免了在传输层和应用层之间的不必要的交互。

另外,HTTP/3 还支持多路复用、头部压缩等 HTTP/2 的特性。这意味着在 HTTP/3 中,仍然可以享受到 HTTP/2 带来的性能优势,同时还能更好地解决一些 HTTP/2 存在的问题。

综上所述,HTTP/3 之所以被广泛采用是因为它在 HTTP/2 的基础上进一步提升了性能,并解决了一些 HTTP/2 存在的问题,提供了更快速和更可靠的页面加载体验。

597.http1.1 的 keep-alive 和 http2 的多路复用 有什么区别?【热度: 87】【网络】【出题公司: 腾讯】

关键词:http1.1 keep-alive、http2 多路复用

HTTP/1.1 的 keep-alive 和 HTTP/2 的多路复用是两种不同的技术机制,它们都旨在提高 HTTP 协议的性能和效率,但具有不同的实现方式和特点。

  1. HTTP/1.1 的 keep-alive:

    • 在 HTTP/1.1 中,默认情况下,每个请求都需要建立一个新的 TCP 连接,请求完成后即关闭连接。
    • 为了减少这种连接建立和关闭的开销,HTTP/1.1 引入了 keep-alive 机制,允许在一个 TCP 连接上发送多个 HTTP 请求和响应。
    • keep-alive 通过在响应头中添加 Connection: keep-alive 字段来启用。
    • 使用 keep-alive 可以减少连接建立和关闭的开销,提高性能。
  2. HTTP/2 的多路复用:

    • HTTP/2 使用二进制协议而不是文本协议,通过在一个 TCP 连接上同时发送多个请求和响应,实现了多路复用。
    • 在 HTTP/2 中,请求和响应被切分为多个帧,每个帧都有一个帧头,可以根据帧头中的流标识符将帧重新组装成完整的请求或响应。
    • 多路复用允许多个请求和响应同时在一个 TCP 连接上进行传输,避免了 HTTP/1.1 中的队头阻塞问题。
    • 多路复用提高了并发性能,减少了延迟,提升了 Web 页面的加载速度。

总结: HTTP/1.1 的 keep-alive 通过在一个 TCP 连接上发送多个请求和响应来减少连接建立和关闭的开销,提高性能。而 HTTP/2 的多路复用则通过在一个 TCP 连接上同时发送多个请求和响应,实现了并发传输,提高了并发性能和加载速度。

598.PM2 部署 nodejs 有哪些优势?【热度: 199】【Nodejs】【出题公司: 腾讯】

关键词:PM2 Nodejs

PM2部署Node.js应用程序有以下几个优势:

  1. 进程管理和监控:PM2可以自动监控Node.js应用程序的运行状态,并在进程崩溃或无响应时自动重启进程。它还提供了实时的日志输出和监控面板,方便查看和分析应用程序的运行情况。
  2. 无缝部署和热重载:使用PM2可以实现无缝部署Node.js应用程序,无需手动停止和启动进程。通过使用PM2的热重载功能,可以在不中断服务的情况下重新加载应用程序代码,实现零停机更新。
  3. 环境管理和配置:PM2可以通过环境变量来管理应用程序的配置,如端口号、数据库连接等。它还支持在不同的环境(如开发、测试、生产)之间切换配置,方便应用程序的部署和管理。
  4. 高可用性和负载均衡:PM2支持启动多个进程,并自动在多个CPU核心间平衡负载。这样可以提高应用程序的并发处理能力和性能,确保应用的高可用性和稳定性。
  5. 集中化管理:PM2提供了命令行工具和Web界面,可以集中管理和操作所有的Node.js应用程序。通过PM2,可以方便地查看和管理进程、查看日志、监控性能指标等,提升管理效率。

综上所述,PM2提供了完善的进程管理和监控功能,以及便捷的部署和配置管理方式,可以大大简化Node.js应用程序的部署和运维工作,提高应用的可用性和性能。

参考文档: zhuanlan.zhihu.com/p/627009546