Vue - 项目编译速度、性能优化、打包体积优化

news2024/11/26 16:42:09

GitHub Demo 地址
在线预览

Vue - 项目编译速度、性能优化、打包体积优化

  • 一、编译速度优化
    • 1、使用缓存
      • 1.1、缓存插件 - HardSourceWebpackPlugin
      • 1.2、`webpack5` 配置cache
      • 1.3、cache-loader 插件
    • 2、合理使用source-map
    • 3、多线程打包
      • 3.1、thread-loader
      • 3.2、parallel-webpack
      • 3.3、HappyPack
    • 4、开启 热更新 / 热替换
    • 5、使用Dll预编译(DllPlugin / autodll-webpack-plugin)
    • 6、优化Loader
    • 7、exclude & include
    • 8、构建区分环境
    • 9、提升webpack版本
  • 二、打包体积优化
    • 分析插件 `webpack-bundle-analyzer `
    • 1、三方库按需引用
      • 1.1、element-ui按需引用
      • 1.2、echart按需引用
      • 1.3、lodash按需引用
    • 2、生产环境去除console.log
      • 2.1、 `babel-plugin-transform-remove-console`
      • 2.2、`terser-webpack-plugin`
      • 2.3、 `uglifyjs-webpack-plugin`
    • 3、合理使用source-map
    • 4、Code Splitting(代码拆分)
    • 5、Tree shaking技术
    • 6、大模块cdn引入
    • 7、压缩css、js、图片资源,删除无用代码
    • 8、gzip压缩
  • 三、性能、用户体验优化
    • 3.1、路由懒加载
    • 3.2、vue-lazyload插件,图片懒加载
    • 3.3、使用缓存
    • 3.4、watch & computed
    • 3.5、防抖 & 节流
    • 3.6、v-if与v-show的使用

webpack中文文档

文章 :
项目优化的方法以及优缺点
HardSourceWebpackPlugin配置和其他优化方案
Vue 项目性能优化方案分享
vue-cli 项目可以做的优化
Vue首评加载速度及白屏时间优化详解

webpack5 和 webpack4 的区别有哪些 ?
webpack5升级指南(附打包性能优化大全)

个人觉得优化方案选择合适的就好,没必要全上,可以把更多的心思花在业务代码的优化上。
项目环境基于webpack4x,可能有些已经过时了,自行判断
下面的方法只有部分使用,更多的是一种记录!!!

webpack版本查看 npm list webpack
或者可以找node_modules目录下面的webpack/package.json文件,查看文件中的version,如下图

在这里插入图片描述

一、编译速度优化

优化编译的文章:
vue项目编译、运行过慢如何提升编译(编译包括运行编译与打包编译)速度
开发过程中vue项目保存编译慢优化方法
webpack5 配置多线程和缓存加快构建速度

1、使用缓存

  • 在webpack3中为了提高构建速度,我们往往会用到 DllPlugin 和 DllReferencePlugin 插件,但是配置复杂,更新文件还需要手动重新生成dll,比较繁琐。还有一种autodll-webpack-plugin会好一些
  • 在webpack4之后可以使用HardSourceWebpackPlugin,它通过在磁盘中设置缓存来提升编译加载速度,第一次正常编译并缓存,第二次有缓存后能减少80%-90%的时间。需要安装使用
  • webpack5内置的cache配置。

1.1、缓存插件 - HardSourceWebpackPlugin

hard-source-webpack-plugin 插件GitHub地址

HardSourceWebpackPlugin是 webpack 的插件,为模块提供中间缓存步骤。为了查看结果,您需要使用此插件运行 webpack 两次:第一次构建将花费正常的时间。第二个构建将明显更快。
速度大概有80%-90%的提升

tips:

默认缓存位置:nodemodules/.cache,需要清除缓存的话可删除后再编译一次
HardSourceWebpackPlugin 和 speed-measure-webpack-plugin 不能一起使用 !!!

安装 hard-source-webpack-plugin

npm install --save-dev hard-source-webpack-plugin

配置

// webpack.config.js 或 vue.config.js
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const path = require('path')

module.exports = {
  // ...
  plugins: [
     // 默认缓存位置:node_modules/.cache路径下
     new HardSourceWebpackPlugin()
     // new HardSourceWebpackPlugin({
     //   cacheDirectory: path.resolve(__dirname, 'node_modules/.cache/hard_source_cache')
     // })
  ]
}

1.2、webpack5 配置cache

webpack5 内置了 cache 缓存机制。直接配置即可。
cache 会在开发模式下被设置成 type: memory 而且会在生产模式把cache 给禁用掉。

// webpack.config.js 或 vue.config.js
const path = require('path')
module.exports = {
  transpileDependencies: true,
  configureWebpack: {
    cache: {
      type: 'filesystem',
      // cacheDirectory: path.resolve(__dirname, '.webpack_cache') // 设置缓存目录(根路径下)
      cacheDirectory: path.join(__dirname, 'node_modules/.cache/webpack_cache') // 设置缓存目录(node_modules/.cache路径下)
    }
  }
}

1.3、cache-loader 插件

和第一种类似,这里不展开说

hard-source-webpack-plugin 安装前后对比

第一次编译 36340ms
在这里插入图片描述
第二次编译 3760ms
在这里插入图片描述

2、合理使用source-map

productionSourceMap的作用在于定位问题,打包时会生成.map文件,在生产环境就可以在浏览器查看到输出的信息具体是在哪一行,但相应的包的体积也会变大,也会影响构建速度,将其设置为false则不生成.map文件
把productionSourceMap 置为false,既可以减少包大小,也可以加密源码

module.exports = {
  productionSourceMap: false
}

3、多线程打包

3.1、thread-loader

文章
【Webpack 性能优化系列(9) - 多进程打包】极大的提升项目打包构建速度

thread-loader 是一个 Webpack 的 loader,它可以将一些开销较大的工作放到 worker 池中,并在 worker 池中执行,以提高构建速度。
例如,在构建 Vue.js 项目时,由于需要编译 .vue 单文件组件、解析模板等操作,构建的时间可能会很长,特别是对于大型项目来说。可以使用 thread-loader 将这些操作放到 worker 池中执行,从而显著缩短构建时间。

使用时,需将此 loader 放置在其他 loader 之前。放置在此 loader 之后的 loader 会在一个独立的 worker 池中运行。
在 worker 池中运行的 loader 是受到限制的。例如:
这些 loader 不能生成新的文件。
这些 loader 不能使用自定义的 loader API(也就是说,不能通过插件来自定义)。
这些 loader 无法获取 webpack 的配置。
每个 worker 都是一个独立的 node.js 进程,其开销大约为 600ms 左右。同时会限制跨进程的数据交换。
请仅在耗时的操作中使用此 loader!

注意,thread-loader 并不是适用于所有场景的,它只对一些开销较大的任务有效。如果任务本身就非常快速并且非常简单,则使用 thread-loader 可能会比直接在主线程中执行更慢。

安装

 npm install thread-loader --save-dev

下面是 thread-loader 的使用示例(将会被应用到所有 .js 和.vue 文件中,除了 node_modules 中的文件。):

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        include: path.resolve('src'),
        exclude: /node_modules/,
        use: [
          'thread-loader', // 将后续 loader 放在 worker 池中执行
          // 耗时的 loader (例如 babel-loader)
          'babel-loader'
        ]
      }
    ]
  }
}

vue.config.js

module.exports = {
  // ... 
  configureWebpack: {
    module: {
      rules: [
        {
          test: /\.js$/,
          include: path.resolve('src'),
          exclude: /node_modules/,
          use: [
            'thread-loader', // 将后续 loader 放在 worker 池中执行
            // 耗时的 loader (例如 babel-loader)
            'babel-loader'
          ]
        }
      ]
    }
  }
}

options

use: [
  {
    loader: "thread-loader",
    // 有同样配置的 loader 会共享一个 worker 池
    options: {
      // 产生的 worker 的数量,默认是 (cpu 核心数 - 1),或者,
      // 在 require('os').cpus() 是 undefined 时回退至 1
      workers: 2,

      // 一个 worker 进程中并行执行工作的数量
      // 默认为 20
      workerParallelJobs: 50,

      // 额外的 node.js 参数
      workerNodeArgs: ['--max-old-space-size=1024'],

      // 允许重新生成一个僵死的 work 池
      // 这个过程会降低整体编译速度
      // 并且开发环境应该设置为 false
      poolRespawn: false,

      // 闲置时定时删除 worker 进程
      // 默认为 500(ms)
      // 可以设置为无穷大,这样在监视模式(--watch)下可以保持 worker 持续存在
      poolTimeout: 2000,

      // 池分配给 worker 的工作数量
      // 默认为 200
      // 降低这个数值会降低总体的效率,但是会提升工作分布更均一
      poolParallelJobs: 50,

      // 池的名称
      // 可以修改名称来创建其余选项都一样的池
      name: "my-pool"
    },
  },
  // 耗时的 loader(例如 babel-loader)
];

3.2、parallel-webpack

parallel-webpack 是一个基于 Webpack 的插件,它能够将构建任务分解为多个子进程并行运行,以此来提高构建速度。与其他类似的插件相比,parallel-webpack 最大的特点是支持异步和同步模块的并行处理,而不仅仅局限于 Loader 和 Plugin。

npm install --save-dev parallel-webpack
// webpack.config.js
const ParallelWebpack = require('parallel-webpack').Plugin

module.exports = {
  // ...
  plugins: [
    new ParallelWebpack({
      // 配置选项
    }),
    /* 其他插件 */
  ],
  // ...
}

以上配置会启用 parallel-webpack 插件,从而实现多进程打包。您可以根据自己的需求在配置选项中对插件进行配置。

需要注意的是,使用多线程打包时可能会增加系统的 CPU 和内存消耗,因此建议在配合与机器性能相匹配的线程数,并且测试多线程打包效果时,应该同时观察构建时间和构建过程中的 CPU 和内存消耗情况。

3.3、HappyPack

HappyPack 是一个用于将 Webpack 进行多线程编译的工具,它能够将一个复杂的 Loader 或者 Plugin 任务分解成多个子进程并行执行,以此来加快构建速度。

npm install happypack --save-dev
const HappyPack = require('happypack');

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: 'happypack/loader?id=js'
      }
    ]
  },
  plugins: [
    new HappyPack({
      id: 'js',
      threads: 4,
      loaders: ['babel-loader']
    })
  ],
  // ...
};

在上述代码中,我们定义了一个名为 js 的 HappyPack 实例,使用了 4 个线程并行编译 babel-loader 处理的 JavaScript 文件。

注:2和3插件相关的代码没有经过实际使用测试效果!!!

4、开启 热更新 / 热替换

webpack 中文文档 HMR 加载样式

webpack 热加载 使用module.hot.accept和不使用的区别
模块热替换(HMR)

  • 热更新(Hot Update):在代码文件被修改后,自动编译出新的代码,并将新代码注入到浏览器运行的 JavaScript 中。热更新并没有重新加载页面,而是更新了部分改动的内容,保留了页面的状态信息,因此可以保持用户的操作状态。
  • 热重载(Hot Reload):在代码文件被修改后,以最快的速度重新编译、打包,并刷新浏览器窗口。相比于热更新,热重载不仅更新了 JavaScript 代码,还重新渲染了整个页面,因此会有一短暂的闪屏,更适用于 UI 相关的修改。
  • 模块热替换(Hot Module Replacement):类似于热更新,但是只替换变化的部分,不会重载整个模块或者应用程序,因此速度更快,体验更好。模块热替换不仅适用于 JavaScript 模块,还可以用于 CSS、图片等资源的替换。

HotModuleReplacementPlugin 是 Webpack 提供的一个插件,用于启用模块热替换(HMR)功能。HMR 是一种开发模式,它可以在不刷新整个页面的情况下,只更新修改过的部分,提高开发效率。

注:

只对js生效
修改css的时候,页面不会自动刷新,只会更新我们修改后的css

const webpack = require('webpack');

module.exports =  {
  // ...
  mode: 'development',
  devtool: 'eval-source-map', // 使用 source-map 方便调试
  devServer: {
    port: 8080,
    hot: true, // 开启 HMR 功能
    open: true // 自动打开浏览器
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin() // 启用 HMR 功能
  ]
}

其中,hot 选项设置为 true,表示开启 HMR 功能;plugins 中添加了 HotModuleReplacementPlugin 插件,以启用 HMR 功能。

在js 代码中添加如下代码:

// js 代码中添加 HMR 相关的代码
if (module.hot) {
  // 如果支持HMR,告诉 Webpack,当前模块更新不用刷新
  module.hot.accept()
  // 如果支持HMR,告诉 Webpack,当前模块更新时一定要刷新
  // module.hot.decline()
}

通过上述配置,就可以开启 Webpack 的模块热替换功能,使得在开发过程中能够实时预览修改的效果,提高开发效率。需要注意的是,HMR 功能只适用于开发环境,在生产环境中不应该使用。

在这里插入图片描述

5、使用Dll预编译(DllPlugin / autodll-webpack-plugin)

DllPlugin是webpack的一个插件,可以将一些不常变化的代码或三方库打包成一个单独的动态链接库(DLL 文件),这样在每次编译时就不需要重新打包这些代码,从而提高编译速度。

使用 DllPlugin 可以将一些稳定的、难以修改的库,如 vue、vue-router、vuex 等预先编译,并通过构建工具在项目编译时直接使用预先编译的 dll 库文件,从而提升了打包速度。

推荐使用 autodll-webpack-plugin

更推荐直接使用 hard-source-webpack-plugin

npm install autodll-webpack-plugin --save-dev

vue.config.js

const AutoDllPlugin = require('autodll-webpack-plugin');

module.exports = {
  // ...
  plugins: [
    new AutoDllPlugin({
      inject: true,
      debug: true,
      filename: '[name]_[hash].js',
      path: './dll',
      entry: {
        vendor: [
          'vue',
          'vue-router',
          'vuex'
        ]
      }
    })
  ]
}

以上配置中,我们使用了 AutoDllPlugin 插件,并传入了以下参数:

  • inject: true 表示自动将生成的 DLL 引用到 HTML 中;
  • debug: true 表示在 webpack 日志中输出调试信息;
  • filename: ‘[name]_[hash].js’ 表示生成的 DLL 文件名,其中 [name] 对应 entry 中的 key,[hash] 表示文件 hash 值;
  • path: ‘./dll’ 表示生成的 DLL 文件存放路径;
  • entry 表示要编译成 DLL 的第三方库列表。

以上配置将会生成一个名为 vendor_XXXX.js 的 DLL 文件,其中 XXXX 表示文件哈希值。该文件包含了 vue、vue-router 和 vuex 这三个库的代码。

在 HTML 中添加以下代码来引用生成的 DLL 文件, 其中,XXXX 应替换为生成的 DLL 文件的哈希值。

<script src="./dll/vendor_XXXX.js"></script>

如果使用 webpack-dev-server 进行开发,需要在 DevServer 配置中添加以下内容:
这样,在启动 DevServer 后,autodll-webpack-plugin 会自动将生成的 DLL 引入到 HTML 中,从而提升构建速度。

const AutoDllPlugin = require('autodll-webpack-plugin');

module.exports = {
  // ...
  devServer: {
    // ...
    before(app, server) {
      AutoDllPlugin({
        debug: true,
        filename: '[name]_[hash].js',
        path: './dll',
        entry: {
          vendor: [
            'vue',
            'vue-router',
            'vuex'
          ]
        }
      }).apply(new webpack.Compiler());
    }
  }
}

6、优化Loader

Loader是webpack的一个重要组成部分,它对文件进行处理的过程中可能会影响编译速度。优化Loader的配置可以大大提高编译速度。

  • 减少 Loader 数量:尽可能地避免重复的 Loader 使用,或者在必要的情况下尽可能合并多个 Loader,从而减少需要编译的 Loader 数量。

  • 缓存 Loader 的编译结果:使用 Webpack 的 cache-loader 插件可以将 Loader 的编译结果缓存到硬盘中,在不改变源文件的基础上可以大大缩短 Loader 的重新编译时间。

  • 启用多线程编译:使用多线程编译工具可以将 Webpack 构建任务分解成多个子进程并行执行,这样可以充分利用 CPU 多核并行计算的优势,加快编译速度。可以采用 happyPack 或 thread-loader 等工具来实现。

  • 避免使用正则表达式作为 Loader 规则:在定义 Loader 规则时,尽量避免使用正则表达式做为规则匹配方式,这样会导致构建过程变慢。如果必须使用,也可以尝试限制正则表达式的匹配范围,提高匹配效率。

7、exclude & include

在 Vue 项目中使用 exclude 和 include 可以帮助提升编译速度,这是因为它们可以减少不必要的文件检查和编译。

exclude 和 include 是通过 webpack 的 module.rules 配置项来设置的。其中,exclude 表示排除某些目录或文件不被编译,而 include 表示包含某些目录或文件进行编译。

下面以 Vue 项目的 Babel 编译为例,介绍如何使用 exclude 和 include。

安装依赖

npm install --save-dev babel-loader @babel/core @babel/preset-env

其中,babel-loader 是用于编译 JavaScript 代码的工具,@babel/core 是 Babel 核心库,@babel/preset-env 是一种预设包,可以根据目标环境自动选择转换插件。

配置 webpack.config.js

以下配置中,exclude: /node_modules/ 表示排除 node_modules 目录下的 JavaScript 文件不被编译,以提高编译速度。

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  }
}

有时候,如果我们只需要编译项目中某个目录下的 JavaScript 文件,可以使用 include 来指定相应的目录。

例如,我们只需要编译 src/components 目录下的 JavaScript 文件,可以将配置改为:

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.js$/,
        include: path.resolve(__dirname, 'src/components'),
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  }
}

以上配置中,include: path.resolve(__dirname, ‘src/components’) 表示只包含 src/components 目录下的 JavaScript 文件进行编译,以减少不必要的文件检查和编译。

8、构建区分环境

比如,在开发环境中,我们通常需要启用 source map 和热更新等功能,而在生产环境中,我们则需要启用代码压缩和 Tree Shaking 等优化技术。因此,我们可以在 Webpack 的配置文件中使用以下代码来根据环境配置不同的插件和优化:

const isProd = process.env.NODE_ENV === 'production';

module.exports = {
  // ...
  plugins: [
    isProd ? new UglifyJSPlugin() : null,
    // ...
  ].filter(Boolean),
};

9、提升webpack版本

升级 Webpack 版本是提高构建速度的一个重要方式,每个新版本都会带来新的优化和性能改进。

更新 Webpack 到最新版本:
首先需要确定当前使用的 Webpack 版本并检查是否需要更新,可以通过 npm 命令安装最新版本的 Webpack:

npm install webpack@latest --save-dev

注意事项:

  • 检查 Webpack 相关的插件和 loader 的版本:
    升级 Webpack 时,应该同时检查相关的插件和 loader 是否需要更新,需要确保其与 Webpack 的版本兼容。
  • 移除废弃的插件和 loader:
    升级可能有些插件和loader 已经随着升级废弃了,因此需要移除对应的插件和 loader。

二、打包体积优化

分析插件 webpack-bundle-analyzer

首先推荐一个分析插件,使用这个插件可以在编译和打包时打开一个分析页面,可以帮助我们优化打包后的文件大小和性能。
它可以生成一个可视化的报告,展示各个模块的大小、依赖关系和构成。通过这个报告,我们可以清晰地了解每个模块的大小和依赖关系,从而确定哪些模块对打包结果的大小贡献较大,进而进行优化。

webpack-bundle-analyzer 插件配置

安装 webpack-bundle-analyzer 插件

npm install --save-dev webpack-bundle-analyzer

在 Webpack 配置文件中使用插件

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  // ...
  plugins: [
      new BundleAnalyzerPlugin({
        openAnalyzer: true
      }),
  ]
}

vue cli 生成的项目下面的就不需要了,直接编译打包会打开一个分析页面

运行 Webpack 构建
运行 Webpack 的构建命令,例如:

webpack --config webpack.config.js

查看分析报告
上述命令执行完成之后,会生成一个报告页面,端口号会打印在控制台中,例如:

Webpack Bundle Analyzer is started at http://127.0.0.1:8888

在浏览器中打开相应的地址,即可查看分析报告。

需要注意的是,如果你的构建配置是基于 Vue CLI 或者 Create React App 等工具生成的,则无需手动添加 webpack-bundle-analyzer 插件,这些工具已经默认包含了该插件。可以直接编译打包或者通过相应的命令来查看分析报告,例如:

vue-cli-service build --mode production --report

在这里插入图片描述

1、三方库按需引用

1.1、element-ui按需引用

完整组件列表以 components.json(引用版本的)为准

  • 步骤1:安装 babel-plugin-component 插件:
npm i babel-plugin-component -D
  • 步骤2:在babel.config.js.babelrc文件中配置:
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset',
    ['@babel/preset-env', { 'modules': false }]
  ],
  plugins: [
    [
      'component',
      {
        libraryName: 'element-ui',
        styleLibraryName: 'theme-chalk'
      }
    ]
  ]
}
  • 步骤3:创建element.js

// element-ui 按需引入
// 注:完整组件列表以 components.json (引用版本的)为准
// https://github.com/ElemeFE/element/blob/master/components.json

import {
  Pagination,
  Dialog,
  Autocomplete,
  Dropdown,
  DropdownMenu,
  DropdownItem,
  Menu,
  Submenu,
  MenuItem,
  MenuItemGroup,
  Input,
  InputNumber,
  Radio,
  RadioGroup,
  RadioButton,
  Checkbox,
  CheckboxButton,
  CheckboxGroup,
  Switch,
  Select,
  Option,
  OptionGroup,
  Button,
  ButtonGroup,
  Table,
  TableColumn,
  DatePicker,
  TimeSelect,
  TimePicker,
  Popover,
  Tooltip,
  Breadcrumb,
  BreadcrumbItem,
  Form,
  FormItem,
  Tabs,
  TabPane,
  Tag,
  Tree,
  Alert,
  Slider,
  Icon,
  Row,
  Col,
  Upload,
  Progress,
  Spinner,
  Badge,
  Card,
  Rate,
  Steps,
  Step,
  Carousel,
  Scrollbar,
  CarouselItem,
  Collapse,
  CollapseItem,
  Cascader,
  ColorPicker,
  Transfer,
  Container,
  Header,
  Aside,
  Main,
  Footer,
  Timeline,
  TimelineItem,
  Link,
  Divider,
  Image,
  Calendar,
  Backtop,
  PageHeader,
  CascaderPanel,
  Avatar,
  Drawer,
  Popconfirm,
  // 单独设置
  Loading,
  MessageBox,
  Message,
  Notification
} from 'element-ui'

const components = [
  Pagination,
  Dialog,
  Autocomplete,
  Dropdown,
  DropdownMenu,
  DropdownItem,
  Menu,
  Submenu,
  MenuItem,
  MenuItemGroup,
  Input,
  InputNumber,
  Radio,
  RadioGroup,
  RadioButton,
  Checkbox,
  CheckboxButton,
  CheckboxGroup,
  Switch,
  Select,
  Option,
  OptionGroup,
  Button,
  ButtonGroup,
  Table,
  TableColumn,
  DatePicker,
  TimeSelect,
  TimePicker,
  Popover,
  Tooltip,
  Breadcrumb,
  BreadcrumbItem,
  Form,
  FormItem,
  Tabs,
  TabPane,
  Tag,
  Tree,
  Alert,
  Slider,
  Icon,
  Row,
  Col,
  Upload,
  Progress,
  Spinner,
  Badge,
  Card,
  Rate,
  Steps,
  Step,
  Carousel,
  Scrollbar,
  CarouselItem,
  Collapse,
  CollapseItem,
  Cascader,
  ColorPicker,
  Transfer,
  Container,
  Header,
  Aside,
  Main,
  Footer,
  Timeline,
  TimelineItem,
  Link,
  Divider,
  Image,
  Calendar,
  Backtop,
  PageHeader,
  CascaderPanel,
  Avatar,
  Drawer,
  Popconfirm
]

const element = {
  install: (Vue) => {
    components.forEach(component => {
      Vue.component(component.name, component)
    })

    // 单独设置
    Vue.use(Loading.directive)
    Vue.prototype.$loading = Loading.service
    Vue.prototype.$msgbox = MessageBox
    Vue.prototype.$alert = MessageBox.alert
    Vue.prototype.$confirm = MessageBox.confirm
    Vue.prototype.$prompt = MessageBox.prompt
    Vue.prototype.$notify = Notification
    Vue.prototype.$message = Message
  }
}
export default element
  • 步骤4:main.js引用(引用方式从引用官方组件换成引用自定义的element.js)
// import ElementUI from 'element-ui' // 全局引用
import ElementUI from '@/utils/element' // 按需引用
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)

之后正常使用即可

1.2、echart按需引用

这里直接创建一个echart.js文件,然后在需要使用的地方引用即可,
引用方式从引用官方组件换成引用自定义的echarts.js

// import * as echarts from 'echarts' // 全量引入
import echarts from '@/utils/echarts' // 按需引入

echart.js文件

// echarts 按需引入

// 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。
import * as echarts from 'echarts/core'

// 引入图表类型,图表后缀都为 Chart
import { BarChart, LineChart, PieChart } from 'echarts/charts'
// 自定义类型的图表
import { CustomChart } from 'echarts/charts'

// 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  DatasetComponent,
  TransformComponent,
  DataZoomComponent
} from 'echarts/components'

// 标签自动布局、全局过渡动画等特性
import { LabelLayout, UniversalTransition } from 'echarts/features'
// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
// import { CanvasRenderer } from 'echarts/renderers'
import { SVGRenderer } from 'echarts/renderers'

// 将以上引入的组件使用use()方法注册
echarts.use([
  BarChart,
  LineChart,
  PieChart,
  CustomChart,
  // 提示框,标题,直角坐标系,数据集 等组件
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  DatasetComponent,
  TransformComponent,
  DataZoomComponent,
  // 标签自动布局、全局过渡动画等特性
  LabelLayout,
  UniversalTransition,
  // Canvas 渲染器
  // CanvasRenderer
  SVGRenderer
])

// 导出
export default echarts

1.3、lodash按需引用

方法一:使用’lodash-es’代替’lodash’

import { cloneDeep } from 'lodash-es' // 按需引入
import { throttle, debounce } from 'lodash-es' // 按需引入
// import lodash from 'lodash-es' // 全量引入

方法二:使用’lodash’时注意按需引用

// import cloneDeep from 'lodash/cloneDeep' // 按需引入
// import lodash from 'lodash' // 全量引入

2、生产环境去除console.log

开发环境需要调试加的控制台日志,在生产环境也打印的话,一方面容易造成数据泄漏,一方面也会占用体积

2.1、 babel-plugin-transform-remove-console

这是一个Babel插件,可以在构建期间删除所有console.*语句。

npm install --save-dev babel-plugin-transform-remove-console

然后,在babel.config.js.babelrc文件中添加以下代码:

const plugins = []
// remove console.* in production
if (process.env.NODE_ENV === 'production') {
  plugins.push('transform-remove-console')
  // plugins.push(['transform-remove-console', { 'exclude': ['error', 'warn'] }])
}

module.exports = {
  //...
  plugins: plugins
}

2.2、terser-webpack-plugin

这个插件来压缩js代码的,它自带一个删除 console.log 的功能
webpack4 上需要下载安装 terser-webpack-plugin 插件,并且需要以下配置:

npm install terser-webpack-plugin --save-dev
const TerserPlugin = require('terser-webpack-plugin')
 
module.exports = { 
// ...other config
optimization: {
  minimize: !isDev,
  minimizer: [
    new TerserPlugin({
      extractComments: false, 
      terserOptions: { 
        compress: { 
          pure_funcs: ['console.log'] 
        }
      }
    }) ]
 }

webpack5 内部本身就自带 js 压缩功能,他内置了terser-webpack-plugin插件,我们不用再下载安装。而且在 mode=“production” 的时候会自动开启 js 压缩功能。

如果你要在开发环境使用,就用下面:

  // webpack.config.js中
  module.exports = {
     optimization: {
       usedExports: true, //只导出被使用的模块
       minimize : true // 启动压缩
     }
  }
 

2.3、 uglifyjs-webpack-plugin

uglifyjs-webpack-plugin 是一个用于压缩 JavaScript 代码的 Webpack 插件,它是以 UglifyJS 为基础,用于对 JavaScript 进行代码压缩和混淆。

npm install --save-dev uglifyjs-webpack-plugin
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
  // ...
  optimization: {
    minimize: true,
    minimizer: [
      new UglifyJsPlugin({
        // 开启并发
        parallel: true,
        // 多进程压缩
        uglifyOptions: {
          compress: {},
          output: {
            comments: false,
          },
        },
      }),
    ],
  }
}

注:2和3插件相关的代码没有经过实际使用测试效果!!!

3、合理使用source-map

productionSourceMap的作用在于定位问题,打包时会生成.map文件,在生产环境就可以在浏览器查看到输出的信息具体是在哪一行,但相应的包的体积也会变大,也会影响构建速度,将其设置为false则不生成.map文件
把productionSourceMap 置为false,既可以减少包大小,也可以加密源码

module.exports = {
  productionSourceMap: false
}

4、Code Splitting(代码拆分)

Code Splitting 是一种优化 Web 应用程序性能的技术,它将应用程序的 JavaScript 代码拆分成多个较小的部分,并根据需要按需加载,减少首页的加载时间,加快响应速度。

代码在没分包之前,整个工程的代码全部被打包到一个main.js里面,那么在访问某一个页面时,必然就会造成资源的浪费,和延长页面的加载时间。
代码分包之后,各个模块分开进行打包,main.js被拆分之后变的体积很小,页面在进行加载的时候,也会按需进行加载。

作用:

  • 加速页面加载
    当应用程序的 JavaScript 代码被拆分为多个较小的部分并按需加载时,可以减少页面加载时间并加快网站的响应速度。

  • 减少资源浪费
    对于大型的 Web 应用程序,往往包含了大量的 JavaScript 代码,这些代码不会在每个页面中都被用到。通过 Code Splitting 技术,可以将不必要的代码延迟加载,从而减少资源浪费。

  • 提高用户体验
    在使用 Code Splitting 技术时,用户只需要加载实际需要的代码,而不是整个应用程序的所有代码。这样可以提高页面响应速度和用户的体验,同时降低应用程序的加载时间和资源利用率。

我这里把elementUI ,echarts,xlsx,和项目中使用的components单独拆分成文件,如chunk-echarts.js,chunk-elementUI.js等,其他的按配置的规则分配到不同的chunk js文件

vue.config.js

module.exports = {
  // ...
  chainWebpack(config) {
  
    config
      .when(process.env.NODE_ENV !== 'development',
        config => {
          config
            .optimization.splitChunks({
              chunks: 'all',
              cacheGroups: {
                libs: {
                  name: 'chunk-libs',
                  test: /[\\/]node_modules[\\/]/,
                  priority: 10,
                  chunks: 'initial' // only package third parties that are initially dependent
                },
                elementUI: {
                  name: 'chunk-elementUI', // split elementUI into a single package
                  priority: 25, // the weight needs to be larger than libs and app or it will be packaged into libs or app
                  test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
                },
                echarts: {
                  name: 'chunk-echarts', // split echarts into a single package
                  priority: 30, // the weight needs to be larger than libs and app or it will be packaged into libs or app
                  test: /[\\/]node_modules[\\/]_?echarts(.*)/ // in order to adapt to cnpm
                },
                xlsx: {
                  name: 'chunk-xlsx', // split xlsx into a single package
                  priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
                  test: /[\\/]node_modules[\\/](xlsx|file-saver)[\\/]/ // in order to adapt to cnpm
                },
                commons: {
                  name: 'chunk-commons',
                  test: resolve('src/components'), // can customize your rules
                  minChunks: 3, //  minimum common number
                  priority: 5,
                  reuseExistingChunk: true
                }
              }
            })
        }
      )

  }
}

5、Tree shaking技术

webpack 中文网 Tree Shaking

前端体验优化tree-shaking
1分钟了解 Tree-shaking
浅析 Tree Shaking

使用Tree shaking技术,剔除无用的代码,减小打包后文件大小,提高页面加载速度。
Tree Shaking 是一种用于清除 JavaScript 中未被使用代码(dead-code)的技术。它依赖于 ES6 模块语法中的静态结构,并通过识别和移除项目中没有使用到的部分来减少 bundle 的体积,从而提高应用程序的性能。

在 Webpack 中启用 Tree Shaking 需要做如下配置:

使用 ES6 模块语法:
Tree Shaking 依赖于 ES6 模块语法的静态结构,因此需要确保在项目中使用 ES6 模块语法,并避免使用 CommonJS / AMD 等非静态的模块语法。

在 Webpack 的配置文件中设置 mode:

odule.exports = {
  // ...
  mode: 'production',
  optimization: {
    usedExports: true, // 开启 Tree shaking
  },
};

在 package.json 文件中设置 sideEffects 属性:

{
  "name": "example",
  "sideEffects": [
    "*.css",
    "*.scss",
    "*.jpg",
  ]
}

在 package.json 文件中添加 sideEffects 属性,告诉 Webpack 哪些模块不应该被 Tree Shaking,如 CSS / SCSS 文件等有副作用的文件。

确保使用了 UglifyJSPlugin 插件:
UglifyJSPlugin 是 Webpack 内置的一个插件,用于对 JavaScript 代码进行压缩和混淆,同时也可以用于移除未被使用的代码。在 Webpack 4 中,由于 mode 为 production 时,会自动使用 TerserWebpackPlugin 进行 JavaScript 代码压缩和优化,因此不需要单独添加 UglifyJSPlugin。

启用 Tree Shaking 后,Webpack 会分析项目代码,将所有没有被引用到的模块和代码块删除掉。这样做不仅可以减少打包后的体积,还可以提高应用程序的性能,因为没有被使用的无效代码不再需要解析和执行。

在设置好上述配置后,Webapck 就会自动进行 Tree shaking,删除未使用的代码。

下面给出一个简单的示例:

// index.js
import { add } from './math.js';
console.log(add(1, 2));
// math.js
export function add(x, y) {
  return x + y;
}

export function sub(x, y) {
  return x - y;
}

以上代码中,sub 函数没有被使用,因此 Tree shaking 后会被删除。最终输出的代码中,只包含 add 函数的代码,sub 函数的代码被成功删除。

一般情况下,Tree Shaking 需要结合其他优化技术一起使用,例如代码分割(Code Splitting)、懒加载(Lazy Loading)、预加载(Preloading)等,以进一步提高应用程序的性能和用户体验。

6、大模块cdn引入

CDN 提供商
https://unpkg.com/
https://www.jsdelivr.com/
https://www.bootcdn.cn/
http://www.staticfile.org/

unpkg 使用,比如搜xlsx

在浏览器录入unpkg.com/xlsx 会跳到最新版本的源码

在这里插入图片描述

退几格,在浏览器录入unpkg.com/xlsx/dist/ 会跳到最新版本的dist列表

在这里插入图片描述

文章

正确使用externals,vue工程构建性能提升67%
Vue项目CDN引入ElementUI

缺点:线上使用 cdn 可能会因为网络问题不稳定,除非公司有自己的 cdn 库。
不过这确实也是一种优化方案,效果也还不错。它的配置也很简单,在 externals 中配置如下:

module.exports = {
    // 设置通过cdn引入的库,不打包到vendor中(需要去掉导入的相关代码),需要在index.html中引入cdn资源
    externals: {
      vue: 'Vue', // 使用cdn引用element-ui时,必须设置vue和element-ui为外部依赖。
      'element-ui': 'ELEMENT', // 不去 node_modules 中找,而是去找 全局变量 ELEMENT
      // 'vue-router': 'VueRouter',
      // axios: 'axios',
      echarts: 'echarts'
      // XLSX: 'XLSX'
    }
}

如何得知第三方包对应的keyvalue是啥,keypackage.json中安装的包名,value时包真实注册或者说暴露的全局变量的值,比如element-uivalueELEMENT,打开elememt-ui的源码,格式化可以看到如下,注册的值是ELEMENT,且依赖了vue;其他包同样思路

在这里插入图片描述
在public/index.html 引入 CDN

<!-- vue必须在element-ui前面 -->
<script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script> 
<!-- unpkg element-ui 源 -->
<link href="https://unpkg.com/element-ui@2.15.13/lib/theme-chalk/index.css" rel="stylesheet">
<script src="https://unpkg.com/element-ui@2.15.13/lib/index.js"></script>
<!-- bootcdn element-ui 源 -->
<!-- <link href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/theme-chalk/index.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/index.min.js"></script> -->
    
<script src="https://unpkg.com/echarts@5.4.2/dist/echarts.min.js"></script>
<!-- <script src="https://unpkg.com/xlsx@0.18.5/dist/xlsx.full.min.js"></script> -->

如果在main.js 使用了下面的代码可以去掉

import ElementUI from 'element-ui'
Vue.use(ElementUI)

关于echarts 使用还是通过下面的代码

import * as echarts from 'echarts'

7、压缩css、js、图片资源,删除无用代码

8、gzip压缩

Gzip 是一种常用的文件压缩算法,可以将文本文件压缩成更小的体积,提高网站的加载速度和用户体验。在 Web 开发中,常用的压缩工具有 Gzip 和 Brotli 等。

要开启 Gzip 压缩,你可以使用 webpack 内置的 compression-webpack-plugin 插件。该插件会自动将打包后的 js、css 文件进行 Gzip 压缩,并生成对应的 .gz 文件。

以下是如何在 项目中开启 Gzip 压缩的步骤:

1、安装 compression-webpack-plugin 插件。

npm install compression-webpack-plugin --save-dev

在 vue.config.js 中添加配置,启用 compression-webpack-plugin

const CompressionWebpackPlugin = require('compression-webpack-plugin');

module.exports = {
  configureWebpack: {
    plugins: [
      // 启用 Gzip 压缩
      new CompressionWebpackPlugin({
        filename: '[path][base].gz',
        algorithm: 'gzip',
        test: /\.(js|css)$/,
        threshold: 10240,
        minRatio: 0.8,
        deleteOriginalAssets: false,
      }),
    ],
  },
}

以上配置中,CompressionWebpackPlugin 的参数含义如下:

filename:压缩后的文件名,[path] 表示文件路径,[base] 表示文件名。
algorithm:压缩算法,这里选用 Gzip。
test:匹配需要压缩的文件类型。
threshold:文件大小超过这个值才会被压缩,单位是字节。
minRatio:压缩后的文件大小和原文件大小的比率,小于这个值才会生成压缩文件。
deleteOriginalAssets:是否删除原文件。若为 true,则原文件将会被删除,只保留压缩后的文件。
执行 npm run build 构建生产环境代码,可以看到在 dist 目录下生成了 .gz 的压缩文件。

在服务器上启用 Gzip 压缩。如果你是使用 Nginx 作为 Web 服务器,可以在 nginx.conf 文件中设置:

gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_vary on;
gzip_proxied any;

这样就可以在服务器端启用 Gzip 压缩,提高网站的加载速度和用户体验。

三、性能、用户体验优化

3.1、路由懒加载

路由懒加载是指在需要的时候才加载对应的路由模块,而不是在项目初始化时就加载所有的路由模块。这样可以减少初始加载时间和资源消耗,提高页面加载速度和用户体验。在 Vue 项目中,可以使用动态导入的方式来实现路由懒加载。

下面是如何使用路由懒加载的步骤:

安装 @babel/plugin-syntax-dynamic-import 插件

npm install @babel/plugin-syntax-dynamic-import --save-dev

在 .babelrc 文件中添加插件

{
  "plugins": ["@babel/plugin-syntax-dynamic-import"]
}

在路由配置文件(如 router.js)中定义路由时,使用 import 函数懒加载路由组件

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

const Home = () => import('./views/Home.vue')

export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
  ]
})

以上代码中,通过使用 import 函数来动态加载组件,在访问对应路由时,才会加载该组件。这样就实现了路由懒加载。

3.2、vue-lazyload插件,图片懒加载

vue-lazyload 是一个 Vue.js 的插件,用于实现图片的懒加载。它可以自动监听页面的滚动事件,在图片出现在用户可见区域时再进行加载,从而减轻页面加载压力,优化用户体验和加快页面渲染速度。

以下是使用 vue-lazyload 实现图片懒加载的基本步骤:

1). 安装 vue-lazyload 插件

npm install vue-lazyload --save

2). 编写 Vue 组件,并在模板中引入待懒加载的图片

<template>
  <div class="container">
    <img v-lazy="imgSrc" alt="图片描述">
  </div>
</template>

<script>
export default {
  data() {
    return {
      imgSrc: 'path/to/image.jpg'
    }
  }
}
</script>

3). 在 Vue 中注册 vue-lazyload 插件

import Vue from 'vue'
import VueLazyLoad from 'vue-lazyload'

Vue.use(VueLazyLoad)

4). 配置 vue-lazyload 的全局参数

import Vue from 'vue'
import VueLazyLoad from 'vue-lazyload'

Vue.use(VueLazyLoad, {
  loading: 'loading.gif', // 加载中的占位图
  error: 'error.gif' // 加载失败的占位图
})

通过以上步骤,就可以实现对 Vue 应用程序中图片的简单懒加载,提高页面性能表现和用户体验。

需要注意的是,在移动端浏览器上,为了提高页面的滚动流畅度和用户体验,建议在 vue-lazyload 中启用 listenEvents 选项,使用 Touch 事件代替 scroll 事件来监听页面滚动。同时,考虑到用户可能会在滚动过程中快速滑动界面,所以建议开启 adapter 选项,其作用是在页面滚动时自动调整懒加载图片的加载时机和顺序,从而避免某些图片由于滚动过快而无法加载。

3.3、使用缓存

使用缓存和资源重用技术,减少不必要的重复请求和渲染,如使用keep-alive组件缓存组件状态。

缓存技术是一种优化 Web 应用程序性能和用户体验的有效方式,Vue.js 项目也可以通过缓存技术进一步提高应用程序的响应速度、减轻服务器负担和增强用户体验。下面是几种常见的 Vue.js 项目中使用缓存技术提高用户体验的方法:

1). 浏览器缓存
浏览器缓存是一种常见且易于实现的缓存技术,通过将资源文件(例如图片、CSS、JS 等)缓存到客户端浏览器中,可以减少服务器请求次数,加快页面加载速度并减轻服务器负担。在 Vue.js 中,你可以使用 Vue Router 提供的 keep-alive 组件来实现组件缓存,当组件被缓存后,每次访问该组件时,都会从浏览器缓存中加载,从而减少服务器的请求次数,提高用户体验。

2). 服务端缓存
在 Vue.js 项目中,我们通常会使用 AJAX 或者 Axios 发送 HTTP 请求以获取数据,如果每次请求都要重新向服务器请求数据,会消耗大量的时间和带宽资源,影响用户体验。因此,可以使用服务端缓存技术来缓存数据,例如使用 Redis 来缓存常用数据或者使用 CDN 存储静态资源文件,从而减轻服务器的请求负担,提高数据访问速度和响应时间。

3). 懒加载
如果一个页面中包含大量的图片或者其他资源文件,会极大地影响页面的加载速度和用户体验。为了避免这种情况,可以采用懒加载技术,即在用户需要浏览某个区域时才加载该区域的资源文件。在 Vue.js 中,你可以使用 vue-lazyload 插件实现图片的懒加载。

4). 数据缓存
在 Vue.js 项目中,可以使用 Vuex 来管理应用程序的状态,在应用程序中经常需要获取相同的数据,因此可以使用 Vuex 的缓存技术来缓存请求过的数据,在下次请求时直接从缓存中获取数据,从而减少服务器的请求次数,提高用户体验。

3.4、watch & computed

watchcomputed 是 Vue 中非常常用的两种响应式数据处理方式,它们都能够监听数据变化并执行相应的操作。在提高 Vue 项目的性能和用户体验方面,watchcomputed 也有着不同的应用场景和优化方法。

1). 优化 watch 的性能

  • 尽量避免在 watch 中进行异步操作,因为异步操作通常会阻塞 JS 线程,影响页面性能。如果必须进行异步操作,可以使用 vm.$nextTickPromise.then 方法,将异步操作推迟到下一次 DOM 更新时执行。
  • 在监听数组或对象等复杂数据类型时,尽量使用 deep 选项来监听其子属性的变化,而不是使用 immediate 选项来立即执行回调函数。因为 immediate 会立即执行回调函数,导致监听的数据被多次计算和渲染,影响页面性能。
  • 避免在 watch 中执行过多的计算和渲染操作,尽量将这些操作放在 computed 属性中进行处理。
  1. 优化 computed 的性能
  • 避免在 computed 中引用其他 computed,因为这样会导致多余的计算和渲染,降低页面性能。
  • 对于数据量较大或计算量较大的 computed,可以使用 lazy 选项,将其设置为惰性计算,只有在需要计算时才会重新计算。
  • 对于一些频繁变化的响应式数据,可以考虑使用 watch 来监听其变化,而不是使用 computed 来计算。

3.5、防抖 & 节流

函数节流(throttle)与 函数防抖(debounce)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象
是应对频繁触发事件的优化方案。

Vue - 使用Lodash实现防抖和节流

3.6、v-if与v-show的使用

v-ifv-show 是 Vue 中两种常用的条件渲染指令。它们都可以根据表达式的值来控制元素的显示和隐藏,但是在具体使用上存在一些差异。

1). v-if
v-if 指令的作用是,根据绑定的表达式的真假值来决定是否渲染 DOM 元素。当绑定的表达式为真值时,该元素会被渲染到页面中;当绑定的表达式为假值时,该元素不会被渲染到页面中,相当于从 DOM 树中移除该元素及其子元素。
优点:在条件不成立时,可以减少不必要的 DOM 元素的渲染和加载,从而提高页面的加载速度和性能表现。
缺点:每次切换条件,都会重新创建和销毁对应的组件或元素,因此在程序运行时可能会比 v-show 慢。

2). v-show
v-show 指令的作用是,根据绑定的表达式的真假值来控制元素的显示和隐藏。与 v-if 不同,v-show 并不会从 DOM 树中移除元素,而是通过修改其 CSS 样式来控制元素的显示和隐藏。
优点:在条件不成立时,并不会从 DOM 树中移除该元素及其子元素,因此在切换条件时,可以保留该元素的状态和属性,提高页面切换的平滑度和体验。
缺点:在条件不成立时,该元素仍会被加载到页面中,因此可能会增加页面的渲染和加载时间。所以,对于需要频繁切换的元素或组件,建议使用 v-show

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/621319.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阿里5面,成功唬住面试官拿了21K,面试也没有那么难吧....

阿里的面试挺独特&#xff0c;每轮面试都没有 HR 约时间&#xff0c;一般是晚上 8 点左右面试官来一个电话&#xff0c;问是否能面试&#xff0c;能的话开始面&#xff0c;不能就约一个其它时间。 全程 5 面&#xff0c;前四面技术面&#xff0c;电话面试&#xff0c;最后一面…

吴恩达 ChatGPT Prompt Engineering for Developers 系列课程笔记--08 Chatbot

08 Chatbot ChatGPT的一种重要功能是作为一个聊天机器人&#xff0c;本节将展示如何和ChatGPT进行对话 1) 不同的角色&#xff08;Roles&#xff09; 前面几节的课程中&#xff0c;我们通过如下函数调用ChatGPT的接口&#xff0c;输入用户输入的prompt&#xff0c;返回模型生…

第二章硬件入门之电容

第二章硬件入门之电容 文章目录 第二章硬件入门之电容一、电容是什么&#xff1f;二、实际应用场景常见电容&#xff1a;1.陶瓷电容&#xff08;无正负极之分&#xff09;1、旁路2、去耦 2.铝电解电容贴片式插件式3.安规电容x电容Y电容 总结 一、电容是什么&#xff1f; **电容…

【kernel exploit】CVE-2022-2602 UNIX_GC错误释放io_uring注册的file结构-UAF

本文主要参考 [漏洞分析] CVE-2022-2602 io_uring UAF内核提权详细解析 并做一些补充。 影响版本&#xff1a;Linux Kernel < v6.0.3。v6.0.3已修复。 测试版本&#xff1a;Linux-v6.0.2 &#xff08;v6.0.2 测试失败&#xff0c;v5.18.19测试成功&#xff09; exploit及测…

React Fiber 使用 MessageChannel + requestAnimationFrame 模拟实现 requestIdleCallback

由于 requestIdleCallback 兼容性较差且不支持 Safari&#xff0c;React Fiber 需要实现一个 requestIdleCallback polyfill 做浏览器兼容&#xff1b; MDN RequestIdleCallbackMDN RequestAnimationFrameMDN MessageChannel 以下为其使用 MessageChannel requestAnimationF…

vivado中ila的使用方法记录

ILA工具生成方法 一、 ILA工具介绍 在FPGA的开发中&#xff0c;当完成代码设计后&#xff0c;为了验证代码的准确性和各种不同条件下的可靠性&#xff0c;往往需要优先想到通过逻辑仿真进行相关验证。使用逻辑仿真进行验证虽然可以周密的考虑给出不同输入条件下的输出结果或交…

“智慧赋能 强链塑链”—— 汽车行业供应链管理数字化应用探讨

01车企供应链数字化的必要性 汽车供应链是一个复杂的系统&#xff0c;很多汽车企业因为供应链管理不当&#xff0c;造成资源浪费、成本高、客户满意度低等一系列问题&#xff1b;而汽车行业规模技术门槛高、配合协同复杂的特性&#xff0c;决定了其供应链缺口无法在短时间内填…

Three.js系列-报错export ‘Geometry‘ (imported as ‘THREE‘) was not found in ‘three‘

今天遇到报错export ‘Geometry’ (imported as ‘THREE’) was not found in ‘three’ port Geometry (imported as THREE) was not found in three (possible exports: ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, …

为什么大家都不用postman而选择 Apifox呢?

丢掉 Postman&#xff0c;Apifox 更香 作为开发者&#xff0c;丢掉 Postman 和 Jmeter吧&#xff0c;这款国产 API 工具更香&#xff0c;更安全&#xff01;一键即可导入 Postman 数据&#xff01; 一、Apifox 是什么&#xff1f; 1、Apifox 定位 Apifox Postman Swagger …

Altium Designer(AD)局域网内使用解冲突

1. Altium Designer 版本 AD15.0.8&#xff0c;电路设计软件&#xff0c;硬件工攻城狮必备技能&#xff0c;软件攻城狮也要会一点点 2. AD软件出现“Your license is already used on computer “LAPTOP-F99R6OR1” using product “AltiumDesigner” 用同事的安装包解压安装的…

Mysql 索引详细解析——底层->应用

1、索引的数据结构 1.1 概述 索引&#xff08;index&#xff09;是帮助Mysql高效获取数据的数据结构。 索引的本质&#xff1a; 索引是数据结构。简单理解为“排好序的快速查找数据结构”&#xff0c;满足特定查找算法。这些数据结构以某种方式指向数据&#xff0c; 这样就可…

期末计算机网络知识点总结

开篇提示: 因为博主图床使用的是GitHub进行存储的&#xff0c;因此当出现图片无法加载&#xff0c;可以尝试更换网络&#xff0c;或者用其他上网方法。当时想用 Gitee进行存储&#xff0c;但一直失败&#xff0c;过一段时间再试几次。目前这篇博文会一直更新&#xff0c;补充新…

Python的内置函数和保留字(关键字)

目录 内置函数 关键字&#xff08;保留字&#xff09; 内置函数 Python 解释器自带的函数叫做内置函数&#xff0c;这些函数可以直接使用&#xff0c;不需要导入某个模块。 将使用频繁的代码段封装起来&#xff0c;并给它起一个名字&#xff0c;以后使用的时候只要知道名字就可…

虹科分享 | 《面向金融行业的商业智能解决方案》白皮书

在以数据为中心的商业环境中&#xff0c;金融业面临着众多挑战&#xff0c;包括瞬息万变的市场动态、监管要求以及客户期望。金融行业从各种来源生成大量数据&#xff0c;包括交易、客户互动、市场数据和内部运营等。然而&#xff0c;如果缺乏有效的数据管理和分析&#xff0c;…

算法修炼之筑基篇——筑基二层后期(初步理解解决贪心算法)

✨博主&#xff1a;命运之光 &#x1f984;专栏&#xff1a;算法修炼之练气篇 &#x1f353;专栏&#xff1a;算法修炼之筑基篇 ✨博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;学习了算法修炼之练气篇想必各位蒟蒻们的基础已经非常的扎实了&#xff0c;下来…

【opencv】无法打开源文件opencv.hpp | bug记录

问题描述 今天这个bug其实比较搞笑&#xff1a; 原因分析&#xff1a; 那就是我们的VS软件没有识别到安装的库。肯定是下面三个环节哪里出错了&#xff1a; 1&#xff09;项目属性里的包含目录&#xff08;include&#xff09; 2&#xff09;项目属性里的库目录(lib) 3&…

随笔记录阿里云开发者社区Java开发高级技能自测20道题

目录 【单选】1.MyBatis中&#xff0c;主要使用哪个Java 接口来执行SQL命令&#xff1f;【单选】2.Spring中ApplicationContext的主要用法是&#xff1f;【单选】3.MySQL中&#xff0c;使用正则表达式查找news表中title以S或Q或L字母开头的所有数据&#xff0c;语句是&#xff…

【MySql】MySql的数据类型

文章目录 数据类型分类数值类型tinyint类型bit类型小数类型floatdecimal 字符串类型charvarchar日期和时间类型enum和set 数据类型分类 对于数据类型分类&#xff0c;这里简单分为数值类型&#xff08;如BIT,BOOL,INT&#xff09;&#xff0c;文本、二进制类型&#xff08;如CH…

JMeter 测试 ActiveMq

JMeter 测试 ActiveMq 的资料非常少&#xff0c; 我花了大量的时间才研究出来 关于ActiveMq 的文章请参考我另外的文章。 版本号: ActiveMq 版本号: 5.91 Jmeter 版本号: 1.13 添加ActiveMq 的jar包 将 ActiveMq 下的 "activemq-all-5.9.1.jar" 复制…

labelme安装与打包为独立exe程序(超级详细版!!!!)

文章目录 labelme安装与打包为独立exe安装打包以上全部命令直接复制粘贴就行&#xff01;&#xff01;&#xff01;&#xff01; labelme安装与打包为独立exe 按照官网给出的详细教程即可&#xff0c;不用去看一些博客&#xff08;都过时了&#xff09;。。。label官网 简要说…