前段时间面试了一个大厂,被问了一些犄角旮旯的面试题,整场下来,一脸懵逼,决定痛定思痛,把这些题总结下来,不断更新。每天一遍,每天进步。。。
目录
1、npm cnpm yarn pnpm的区别,各自的优势是什么? 你项目中用的什么?
2、devDependencies、dependencies,peerDependencies的区别
15、react的onClick和vue的@click分别是怎么实现的
21、http和https的区别?websocket和http的区别?
44、请求方式都有哪些,假如post请求最大支持2M,那么上传一个3M的文件应该怎么做最合适?
45、了解HTTP/2的特点、优势以及与HTTP/1.x的区别,以及如何在前端项目中优化使用HTTP/2协议。
48、nodejs的事件循环面试官:说说对Nodejs中的事件循环机制理解? | web前端面试 - 面试官系列
52、promise.all和promise.race的区别
61、什么是JavaScript中的柯里化(Currying)和偏函数应用(Partial Application)?它们在JavaScript中有哪些应用场景?
73、Cookie和LocalStorage与SessionStorage的区别?
76、keep-alive 怎么控制组件的缓存,以及和哪个生命周期有关
1、npm cnpm yarn pnpm的区别,各自的优势是什么? 你项目中用的什么?
1. npm (Node Package Manager)
-
特点:npm 是最基础的 JavaScript 包管理器,随 Node.js 一起安装。它支持注册和安装来自 npm 官方仓库的包。
-
优势:
-
广泛使用:作为 Node.js 的官方包管理器,几乎所有 Node.js 开发者都在使用。
-
支持社区:庞大的社区支持,拥有大量可用的包。
-
简单易用:命令行工具简单,易于上手。
-
2. cnpm (China npm)
-
特点:cnpm 是一个专为解决中国用户访问 npm 官方仓库的网络问题而开发的工具,它使用淘宝镜像来加速包的下载。
-
优势:
-
下载速度快:由于使用了中国境内的镜像,不会受到国际带宽限制,安装速度大幅提升。
-
兼容性好:与 npm 命令行接口基本相同,容易上手。
-
3. yarn
-
特点:Yarn 是 Facebook 开发的一个替代 npm 的包管理工具,强调速度和可靠性。
-
优势:
-
缓存机制:Yarn 会缓存下载的每一个包,下次安装时,可以直接从缓存中提取,显著提高安装速度。
-
锁文件:Yarn 会生成一个
yarn.lock
文件,确保安装的依赖版本一致,有助于团队和 CI/CD 圈稳定应用。 -
并行安装:支持并行下载包,相对比 npm 更快。
-
4. pnpm
-
特点:pnpm 是一个相对较新的 JavaScript 包管理工具,注重节省磁盘空间和提高安装性能。
-
优势:
-
节省空间:采用了硬链接的方式来共享包,避免了多个项目相同依赖的重复安装,大幅节省磁盘空间。
-
高效性:pnpm 使用的安装算法比 npm 和 yarn 更高效,安装时只会下载实际需要的包,速度更快。
-
锁文件:同样生成
pnpm-lock.yaml
文件,保证依赖关系的一致性。
-
总结
-
选择 npm:适合普通使用和对 npm 官方仓库的直接访问。
-
选择 cnpm:如果在中国使用,想要提高 npm 安装速度。
-
选择 yarn:需要更好的性能和可靠性,尤其是在大型项目中。
-
选择 pnpm:需要节省磁盘空间和提高安装速度,尤其是在多个项目共享依赖时。
2、devDependencies、dependencies,peerDependencies的区别
npm install mypack & npm install mypack -save 将 mypack安装到node_modules目录下,并且将该包名放入package.json下的dependencies中
npm install mypack -save-dev 将 mypack安装到node_modules目录下,并且将该包名放入package.json下的devdependencies中
npm install mypack -g 将 mypack安装你 node 的安装目录 及 全局目录。该包名不放入package.json中,可以直接在命令行里使用。如npm
dependencies 字段中指定的是项目运行时需要的依赖包,也就是生产环境下需要的依赖。这些依赖将会被安装在生产环境中,并被打包进最终的发布版本中。一般来说,这些依赖是指与项目密切相关的库和框架,比如 express、lodash、axios 等。当我们使用 npm install 安装项目时,dependencies 中指定的依赖包也会被自动安装。使用场景:适用于项目的主要功能模块、框架以及必要的第三方库。这些依赖项会随着应用程序一起部署,并在生产环境中运行。
devDependencies 字段中指定的是开发环境下所需的依赖包。这些依赖通常是开发人员在编写和测试代码时使用的,而不会被打包到最终的发布版本中。一般来说,这些依赖包是用于构建、测试、调试等用途,比如 Babel、Webpack、Mocha 等。当我们使用 npm install 安装项目时,devDependencies 中指定的依赖包不会被安装。若需要安装 devDependencies 中的依赖,需要使用 npm install --dev。使用场景:适用于开发过程中的辅助工具、测试框架、构建工具、代码质量检查工具等。这些依赖项不会影响应用程序的实际运行,只在开发环境中使用。
peerDependencies 字段中指定的是项目所依赖的其他包的版本号范围。这些依赖会要求安装方在安装项目时手动安装所需要的版本。peerDependencies 通常用于告知用户项目运行时所依赖的某些库或框架的版本,而且这些库或框架已经被全局安装或者被安装在项目外面。peerDependencies 可以确保安装的库版本与项目所依赖的版本一致,从而减少版本兼容性问题。
使用场景:
开发库或模块依赖特定版本的外部库:如果你正在开发一个库或模块,它依赖于外部库的特定版本来实现某些功能,但你不希望将这些外部库包含在你的库中,那么你可以在你的 package.json 中指定这些外部库为 peerDependencies。
版本兼容性:有时,不同的库可能依赖于同一个外部库的不同版本,这可能导致版本冲突。通过在你的库中使用 peerDependencies,你可以确保使用者在安装你的库时会同时满足这些依赖项的版本要求,从而避免版本冲突。
库的可插拔性:如果你的库需要与其他库或模块协同工作,而这些库或模块可能在项目中以插件或扩展的形式存在,你可以使用 peerDependencies 来确保插件与你的库兼容。
提供建议性的依赖项:有时候,你可能希望为使用者提供一些建议性的依赖项,虽然这些依赖项不是强制性的。在这种情况下,你可以将这些依赖项列为 peerDependencies,使用者可以根据自己的需求来决定是否安装。
使用 peerDependencies 时需要注意以下几点:
使用 peerDependencies 不会自动安装依赖项,它只是告诉使用者需要安装这些外部依赖项,并确保版本兼容性。
使用 peerDependencies 时,使用者需要手动安装符合要求的外部依赖项,以便与你的库或模块正常工作。
为了避免冲突和混淆,建议在文档中清楚地说明使用者需要安装的外部依赖项以及版本要求。
3、生产环境,开发环境,测试环境等不同的环境的面试题
开发环境:
开发环境时程序猿们专门用于开发的服务器,配置可以比较随意,为了开发调试方便,一般打开全部错误报告和测试工具,是最基础的环境。开发环境的分支,一般是feature分支。
测试环境
一般是克隆一份生产环境的配置,一个程序在测试环境工作不正常,那么肯定不能把它发布到生产服务器上,是开发环境到生产环境的过度环境。测试环境的分支一般是develop分支,部署到公司私有的服务器或者局域网服务器上,主要用于测试是否存在bug,一般会不让用户和其他人看到,并且测试环境会尽量与生产环境相似。
生产环境
生产环境是指正式提供对外服务的,一般会关掉错误报告,打开错误日志,是最重要的环境。部署分支一般为master分支。
上述环境也可以说是系统开发的三个阶段:开发->测试->上线,其中生产环境也就是通产说的真实的环境,最后交给用户的环境。
如何在Vue中丝滑的切换环境呢?
- 在根目录建立.env系列文件
- .env.development(开发环境,用于serve启动的项目)
- .env.production(生产环境,用于build打包的项目)
- .env.test(测试环境)
//在文件中可以配置下面的变量 后面写请求服务器的地址
VUE_APP_BASE_API = '需要请求API'
1 //对应的 "scripts": 2 "dev": "vue-cli-service serve", 对应开发环境 3 "test": "vue-cli-service serve --mode test", 对应测试环境 4 "build": "vue-cli-service build", 对应生产环境 5 "build:test": "vue-cli-service build --mode test",对应测试环境
在vue中使用的话可以直接使用 process.env.VUE_APP_BASE_API 进行取值,也就是我们预先配置好的请求地址
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 10000,
})
生产环境中如何调试,如何查找报错对应的位置?
1. 使用日志记录
-
集成日志库:使用像
Winston
、Bunyan
或Log4j
这样的日志库来记录重要的应用运行信息和错误。 -
等级分类:根据错误的严重等级记录日志(如 info、warn、error 等),便于后期分析。
-
结构化日志:使用结构化日志格式(如 JSON)有助于更好地解析和搜索日志内容。
-
集中式日志管理:将日志发送到集中式日志管理系统(如 ELK Stack、Graylog 或 Splunk),可以方便地进行查询和分析。
2. 错误监控服务
-
集成监控服务:使用错误监控服务(如 Sentry、Rollbar 或 Bugsnag)来捕获运行时错误并获得详细的堆栈跟踪。
-
实时通知:这些服务通常提供实时通知功能,可以在错误发生时立即向开发团队发送警报。
3. 使用假设和排除法
-
重现错误:在开发或测试环境中尽量模拟生产环境的条件,尝试重现问题。
-
逐步排查:逐步排查代码,排除可能的错误原因,使用本地环境的调试工具进行分析。
4. 源代码映射
-
生成 Source Maps:对于前端代码(如使用 TypeScript 或 Babel 编译的代码),确保生成 Source Maps,以便在调试时能够看到原始代码。
-
使用浏览器开发者工具:使用浏览器的开发者工具查看源代码及其对应的行号,以帮助定位问题。
5. 代码审查与静态分析
-
代码审查:定期进行代码审查,以确保代码质量,避免潜在的错误。
-
静态代码分析:使用工具(如 ESLint、TSLint)进行静态代码检查,提前识别和修复潜在问题。
6. 环境配置
-
详细错误信息:在开发环境中配置详细的错误信息输出,但在生产环境中避免直接暴露详细信息,以防安全风险。可以提供简化的错误信息给最终用户,同时在后台记录详细的错误信息。
7. 使用调试工具
-
Node.js 调试:
-
使用
node --inspect
或node --inspect-brk
启动 Node.js 应用程序,并连接到 Chrome DevTools 进行远程调试。
-
-
断点调试:在开发过程中加入断点,在生产环境中有特定的需求时,可以按照需要进行调试。
8. 性能监控
-
集成 APM 工具:使用应用性能监控(APM)工具(如 New Relic、Datadog 或 AppDynamics)来监控应用性能,识别性能瓶颈和错误。
总结
在生产环境中调试代码时,关注日志的记录与分析、使用错误监控服务、严格控制环境的详细错误输出信息等都是重要的调试策略。此外,进行定期的代码审查和静态分析也能有效提高代码质量,减少生产环境中的错误。如果错误发生了,及时找到问题的根源并修复是维护良好用户体验和系统稳定性的关键。
虽然map文件提供了便利,但是在生产环境,为了安全,是建议关闭SourceMap的,因为通过.map文件和编译后代码可以很容易反编译出项目的源码,这样就相当于泄露了项目的代码。
生产环境的代码,经过压缩、编译,很不利于debug。由于生产环境没有配置SourceMap,所以代码报错时,或是通过Fundebug,Sentry等工具搜集到的报错信息,得到报错代码的行和列都是编译后的代码,这样很不易于定位问题。针对这个问题,需要准备一份生产环境代码的map文件,为了方便,可以在项目的package.json增加debug命令用来生成map文件。这条命令除了开启sourcemap,其他的具体webpack配置和生产环境配置相同。
"scripts": {
"start": "vue-cli-service serve --mode dev",
"stage": "vue-cli-service build --mode staging",
"online": "vue-cli-service build",
"debug": "vue-cli-service build --mode debug"
},
有了map文件,通过SourceMap提供的API就可以定位到源码的位置。下面是实现的核心代码。
// Get file content
const sourceMap = require('source-map');
const readFile = function (filePath) {
return new Promise(function (resolve, reject) {
fs.readFile(filePath, {encoding:'utf-8'}, function(error, data) {
if (error) {
console.log(error)
return reject(error);
}
resolve(JSON.parse(data));
});
});
};
// Find the source location
async function searchSource(filePath, line, column) {
const rawSourceMap = await readFile(filePath)
const consumer = await new sourceMap.SourceMapConsumer(rawSourceMap);
const res = consumer.originalPositionFor({
'line' : line,
'column' : column
});
consumer.destroy()
return res
}
最重要的就是使用SourceMap提供的 originalPositionFor API。 SourceMapConsumer.prototype.originalPositionFor(generatedPosition)
originalPositionFor API的参数为一个包含line和column属性的对象
line 编译生成代码的行号,从1开始
column 编译生成代码的列号,从0开始
这个方法会返回一个具有以下属性的对象
{ source: 'webpack:///src/pages/common/403.vue?c891', // 源代码文件的位置,如果无法获取,返回null。
line: 4, // 源代码的行号,从1开始,如果无法获取,返回null。
column: 24, // 源代码的列号,从0开始,如果无法获取,返回null。
name: 'get' // 源代码的标识,如果无法获取,返回null。
}
4、库的版本问题
(1)版本号前面的“^”和“~”代表什么:
“^”它表示尽量使用最新版本,但保证不产生兼容问题。
~符号,表示版本号只能段改变最末尾那(如果是 ~x.y 末尾就是 y,如果是 ~x.y.z 末尾就是 z),比如这种情况:~1.2 等于 >=1.2.0; <2.0.0
因为0的特殊性所以如果你要指定 0 开头的库那一定要注意:~0.1 这种写法是很危险的,因为 ~0.1 等于 >=0.1.0; <1.0.0,可能出现无法向下兼容的情况,比较保险的写法还是:^0.1(等于 >=0.1.0; <0.2.0)
^
(caret)
- 当你在依赖项的版本号前使用
^
符号时,它表示兼容版本更新。 - 这意味着当你运行
npm install
或yarn install
时,包管理工具会安装最新的大版本(major version)和次版本(minor version),但是不会更新补丁版本(patch version)。 - 例如,
^1.2.3
将允许更新到1.3.0
,甚至是1.2.4
,但不允许更新到2.0.0
。
~
(tilde)
- 使用
~
符号时,它表示只允许补丁版本的更新。 - 这意味着包管理工具会安装与指定版本相同的大版本和次版本,但可以更新补丁版本。
- 例如,
~1.2.3
将允许更新到1.2.4
,但不允许更新到1.3.0
或2.0.0
。
*
- 使用
*
符号时,它表示接受任何版本的依赖项。 - 这给了包管理工具最大的灵活性,可以安装任何新版本,无论大版本、次版本还是补丁版本。
- 例如,
*
将允许从1.2.3
更新到2.0.0
,甚至是3.1.2
。
(2)改变版本号怎么做
npm version
命令用于更改版本号的信息,并执行commit
操作;该命令执行后, package.json
里的 version
会自动更新。
一般来说,当版本有较大改动时,变更第一位, 执行命令:npm version major -m "description"
, 例如1.0.0
-> 2.0.0
;
当前包变动较小时,可变更第二位,执行命令:npm version minor -m "description"
, 例如: 1.0.0
-> 1.1.0
;
当前包只是修复了些问题时,可变更第三位,执行命令:npm version patch -m "description"
, 例如: 1.0.0
-> 1.0.1
;
(3)pack.json的配置有哪些?
- 描述配置 主要是项目的基本信息,包括名称,版本,描述,仓库,作者等,部分会展示在 npm 官网上。
- 文件配置 包括项目所包含的文件,以及入口等信息。
- 脚本配置
命令行方式启动预设置的脚本
- 依赖配置 项目依赖其他包引用的相关信息。
- 发布配置 主要是和项目发布相关的配置。
- 系统配置 和项目关联的系统配置,比如 node 版本或操作系统兼容性之类。这些要求只会起到提示警告的作用,即使用户的环境不符合要求,也不影响安装依赖包。
- 第三方配置 一些第三方库或应用在进行某些内部处理时会依赖这些字段,使用它们时需要安装对应的第三方库。
5、有关提升项目性能的方案
1、减少 HTTP 请求次数:可以使用雪碧图、图片压缩等方法,减少静态资源的 HTTP 请求次数。
2、浏览器缓存:在合适的情况下,使用浏览器缓存可以显著减少请求时间,提高页面加载速度。
通过设置 http 头信息,可用的参数如下:其中 Expires 和 Cache-control 属于强缓存;Last-Modified/If-Modified-Since 和 Etag/If-None-Match 属于协商缓存。
* Expires
* Cache-control
* Last-Modified/If-Modified-Since
* Etag/If-None-Match
3、使用 CDN 加速:使用 CDN 加速可以将静态资源分发到多个节点,减少请求延迟,提高页面加载速度。
(1)、进行webpack的配置,将一些基本的npm包放在了CDN服务器上
(2)注入cdn变量 由于在开发环境时,文件资源还是可以从本地 node_modules 中取出,而只有项目上线了,才需要去使用外部资源。此时我们可以使用环境变量来进行区分。
(3)注入CDN配置到html模板 之后通过 html-webpack-plugin注入到 index.html之中:
4、延迟加载组件:对于一些比较耗时的组件,可以使用懒加载的方式,等到用户需要使用的时候再加载,避免在页面加载时一次性请求过多资源导致页面卡顿。
5、使用 Webpack 进行打包和压缩:Webpack 可以将多个 JS、CSS 文件打包成一个文件,减少 HTTP 请求次数;同时还可以进行代码压缩,减少文件大小,提高页面加载速度。
(1)下载压缩相关的库
1 # js 压缩
2 npm install uglifyjs-webpack-plugin --save-dev
3 # css提取
4 npm install mini-css-extract-plugin --save-dev
5 # css压缩
6 npm install css-minimizer-webpack-plugin --save-dev
7 # 读取环境变量
8 npm install cross-env --save-dev
(2)配置 webpack.config.js
1 const path = require("path")
2 const webpack = require("webpack")
3 const HtmlWebpackPlugin = require('html-webpack-plugin') // 生成html入口文件
4 const {CleanWebpackPlugin} = require('clean-webpack-plugin') // 编译文件时,清理 build/dist 目录,再生成新的
5
6 const MiniCssExtractPlugin = require('mini-css-extract-plugin');
7 const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
8 const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
11 const isProduction = process.env.NODE_ENV === "production"
12 const isDevelopment = process.env.NODE_ENV === "development"
13 console.log("print env: ", isProduction)
14
15 module.exports = {
16 entry: {
17 app: path.resolve(__dirname, "src/index.tsx"),
18 },
19 mode: "development",
20 module: {
21 rules: [
22 {
23 test: /\.(js|jsx|ts|tsx)$/,
24 exclude: /node_modules/,
25 use: [
26 {
27 loader: "babel-loader",
28 options: {
29 presets: [
30 [
31 "@babel/preset-env",
32 // 配置信息
33 {
34 targets: {
35 "chrome": "58",
36 "ie": "11",
37 },
38 // 指定 corejs 的版本
39 "corejs": "3",
40 // 使用 corejs 的方式 "usage" 表示按需加载
41 "useBuiltIns": "usage"
42 }
43 ],
44 [
45 "@babel/preset-typescript",
46 ],
47 [
48 "@babel/preset-react",
49 {}
50 ]
51 ]
52 }
53 },
54 {
55 loader: "ts-loader" // 1. 先加载ts
56 }
57 ],
58 },
59 {
60 test: /\.(css|scss)$/,
61 use: [
62
63 {
64 loader: process.env.NODE_ENV === "production"
65 ? MiniCssExtractPlugin.loader // 提取css到文件中,放到head中
66 : "style-loader", // 4. 加载样式文件到head
67
68 },
69 {
70 loader: "css-loader", // 3. 加载css
71 options: {
72 importLoaders: 1,
73 sourceMap: true
74 }
75 },
76 {
77 loader: "postcss-loader", // 2. 加载postcss(项目里配置的是 autoprefixer 和 px2rem) 转换 css里的rem和厂商前缀
78 options: {
79 postcssOptions: {
80 config: path.resolve(__dirname, 'postcss.config.js')
81 },
82 sourceMap: true
83 }
84 },
85 {
86 loader: "sass-loader", // 1. 加载 scss 转换成css
87 options: {
88 sourceMap: true
89 }
90 }
91 ]
92 },
93 // {
94 // test: /\.(png|jpg|gif)$/,
95 // use: [
96 // {
97 // loader: 'file-loader',
98 // options: {
99 // name: '[sha512:hash:base64:7].[ext]'
100 // }
101 // }
102 // ]
103 // } // by junfenghe 2021-12-06
104 {
105 test: /\.(png|jpg|gif|ico)$/,
106 type: 'asset/resource',
107 generator: {
108 filename: 'static/media/[hash][ext][query]'
109 }
110 },
111 {
112 test: /\.svg/,
113 type: 'asset/inline'
114 },
115 // 20230216 打包html中的图片
116 {
117 test: /\.(htm|html)$/i,
118 loader: "html-withimg-loader"
119 }
120 // {
121 // test: /\.(txt|pdf|excel)$/,
122 // type: 'asset/source'
123 // }
124 ]
125 },
126 resolve: {
127 extensions: ["*", ".js", ".jsx", ".ts", ".tsx"], // 尝试按顺序解析这些后缀名。能够用户再引入模块时不带扩展,例如:import File from '../path/to/file'
128 },
129 output: {
130 path: path.resolve(__dirname, "build"), // 文件输出的路径
131 // filename: "bundle.js", //对于单一入口(entry point)起点,filename 会是一个静态名称;
132 filename: "static/js/[name].[fullhash].bundle.js", // 决定了每个输出 bundle 的名称。这些 bundle 将写入到 output.path 选项指定的目录下。// 当通过多个入口起点(entry point)、代码拆分(code splitting)或各种插件(plugin) 创建多个 bundle,应该赋予每个 bundle 一个唯一的名称
133 assetModuleFilename: "images/[hash][ext][query]" // by junfenghe 2021-12-06 // by junfenghe 20221228
134 },
135 //20230216
136 optimization: {
137 minimizer: [
138 // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
139 `...`,
140 new CssMinimizerPlugin({
141 parallel: true,//使用多进程并发执行,
142 minimizerOptions:{
143 preset:[
144 "default",
145 {
146 discardComments: {removeAll:true},//移除所有注释
147 },
148 ]
149 }
150 }),
151 ]
152 },
153 //20230216
154 plugins: [
155 new HtmlWebpackPlugin({
156 template: path.join(__dirname, 'public/index.html')
157 }),
158 new CleanWebpackPlugin({
159 path: path.join(__dirname, 'build')
160 }),
161 // // 20230216 代码压缩
162 // new UglifyJsPlugin({
163 // parallel: true,// 使用多进程并行以提高构建速度
164 // sourceMap: true,// 使用源映射将错误信息位置映射到模块(这将会减慢编译速度)。
165 // // extractComments:true,//启用禁用提取注释
166 // cache: true,//启用缓存
167 // uglifyOptions: {
168 // comments: false,//如果你构建时不想出现注释,可以按照以下配置将 uglifyOptions.output.comments 设置为 false:
169 // },
170 // }),
171 // // 提取css
172 new MiniCssExtractPlugin({
173 // Options similar to the same options in webpackOptions.output
174 // both options are optional
175 filename: 'static/css/[name].[contenthash:8].css',
176 chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
177 }),
178 new CssMinimizerPlugin()
179
180 ],
181 devServer: {
182 static: {
183 directory: path.join(__dirname, "public")
184 },
185 historyApiFallback: true, //When using the HTML5 History API, the index.html page will likely have to be served in place of any 404 responses. Enable devServer.historyApiFallback by setting it to true:
186 port: 3003,
187 compress: true
188 },
189 devtool: isProduction?false:'source-map',//生产环境关闭sourcemap
190 }
191
192 if (isProduction) {
193 pluginsProduction = [
194 // 20230216 代码压缩
195 new UglifyJsPlugin({
196 parallel: true,// 使用多进程并行以提高构建速度
197 sourceMap: true,// 使用源映射将错误信息位置映射到模块(这将会减慢编译速度)。
198 // extractComments:true,//启用禁用提取注释
199 cache: true,//启用缓存
200 uglifyOptions: {
201 comments: false,//如果你构建时不想出现注释,可以按照以下配置将 uglifyOptions.output.comments 设置为 false:
202 },
203 }),
204
205 ]
206 module.exports.plugins.push(
207 ...pluginsProduction
208 )
209
210 }
(3)基于 React.lazy() 的优化
1 import DimensionReading from "../../pages/dimension/dimension-reading/dimension-reading";
2 import DimensionWriting from "../../pages/dimension/dimension-writing/dimension-writing";
3 import DimensionPhoto from "../../pages/dimension/dimension-photo/dimension-photo";
4 import DimensionPlan from "../../pages/dimension/dimension-plan/dimension-plan";
5 import DimensionAdd from "../../pages/dimension/dimension-add/dimension-add";
6 import DimensionHome from "../../pages/dimension/dimension-home/dimension-home";
7 import SelfIntro from "../../pages/self-intro/self-intro";
1 const DimensionReading = lazy(() => import("../../pages/dimension/dimension-reading/dimension-reading"))
2 const DimensionWriting = lazy(() => import("../../pages/dimension/dimension-writing/dimension-writing"))
3 const DimensionPhoto = lazy(() => import("../../pages/dimension/dimension-photo/dimension-photo"));
4 const DimensionPlan = lazy(() => import("../../pages/dimension/dimension-plan/dimension-plan"));
5 const DimensionAdd = lazy(() => import("../../pages/dimension/dimension-add/dimension-add"));
6 const DimensionHome = lazy(() => import("../../pages/dimension/dimension-home/dimension-home"));
7 const SelfIntro = lazy(() => import("../../pages/self-intro/self-intro"));
6、使用 Web Workers:对于一些计算密集型任务,可以使用 Web Workers 将任务分发到多个线程中,提高运算效率,避免页面卡顿。
7、优化 JavaScript 代码:优化 JavaScript 代码可以减少页面的运行时间,提高页面性能。一些常见的优化方案包括:避免使用全局变量,减少 DOM 操作,避免不必要的循环等。
8、使用响应式布局:使用响应式布局可以使页面适应不同大小的设备屏幕,提高用户体验,避免出现滚动条等不必要的元素。
9、使用 CSS3 动画:使用 CSS3 动画可以减少对 JavaScript 的依赖,提高动画效果的性能。
10、使用服务端渲染:服务端渲染可以将页面的渲染工作在服务端完成,减少客户端的渲染时间,提高页面性能。
11、如何对项目中的图片进行优化:
-
压缩图片: 使用专业的图片压缩工具(如TinyPNG、JPEGmini等)来减小图片的文件大小,以减少加载时间和节省带宽。
-
选择适当的格式: 根据图片的内容和用途,选择合适的图片格式。通常JPEG适合照片和复杂的图像,PNG适合具有透明部分或需要保留细节的图像,而SVG适合矢量图形。
-
调整图片尺寸: 通过调整图片的尺寸来匹配实际显示大小,避免加载过大的图片。不要通过CSS缩放大图片,而是使用适当尺寸的图片。
-
使用懒加载: 对于页面上加载大量图片的情况,使用懒加载技术可以延迟图片加载,只有当用户滚动到可见区域时才加载图片,减少页面初始加载时间。
-
响应式图片: 对于响应式网站,使用srcset和sizes属性或者Picture标签来提供不同尺寸的图片,以确保在不同设备上呈现最佳的图片质量。
-
使用CSS Sprites: 将多个小图片合并成一张大图,在网页中使用CSS Sprites技术,减少HTTP请求次数和提高加载速度。
-
使用CDN存储图片: 将图片文件存储在内容分发网络(CDN)上,可以加快图片的加载速度,减少服务器负载,提高用户体验。
6、前端性能优化指标RAIL是什么?
1. **R - Response(响应)**:
- 用户操作后的响应时间应在100毫秒以内,以保证界面响应迅速,让用户感受到操作的即时反馈。
2. **A - Animation(动画)**:
- 动画或过渡效果的帧率应保持在60帧每秒,以确保流畅的视觉体验。每帧渲染时间应不超过16毫秒。
3. **I - Idle(空闲)**:
- 完成用户的关键操作后,应该利用空闲时间进行后台工作,以便在有用户交互时能够立即响应。利用空闲时间来进行低优先级的任务,最好在50毫秒内进行切割和处理。
4. **L - Load(加载)**:
- 页面加载时间应在一秒内以保持用户的注意力。如果初始内容能够在一秒内呈现,会让用户觉得网站响应迅速;整个页面的交互准备时间应尽量控制在5秒以内。
通过遵循RAIL框架,开发者可以有针对性地优化前端性能,从而达到更好的用户体验。
7、ssr优缺点,实现的具体过程
优点:
-
SEO友好:SSR 可以让搜索引擎更容易抓取页面内容,提升网站的搜索引擎排名。
-
首屏加载性能:SSR 可以在服务端生成完整的 HTML 页面,减少客户端渲染时间,提升首屏加载性能。
-
更好的用户体验:由于服务端已经生成了完整的页面内容,用户可以更快地看到页面内容,提升用户体验。
-
利于缓存:SSR 可以更好地利用缓存,减少服务器压力,提高网站性能。
缺点:
-
服务器压力:SSR 需要在服务器端进行页面渲染,会增加服务器的压力和资源消耗。
-
开发复杂度:相比客户端渲染,SSR 的实现和调试相对复杂,需要考虑服务端和客户端的交互。
-
不适合单页面应用:对于单页面应用(SPA),SSR 可能会导致一些额外的复杂性和性能问题。
实现过程:
-
选择框架:选择支持 SSR 的前端框架,如 Next.js(React)、Nuxt.js(Vue)等。
-
创建服务端代码:在项目中创建服务端代码,处理路由、数据获取和页面渲染逻辑。
-
页面模板:创建页面模板,用于服务端渲染生成完整的 HTML 页面。
-
数据获取:在服务端获取页面所需的数据,可以通过 API 请求或其他方式获取数据。
-
页面渲染:使用模板引擎或框架提供的服务端渲染功能,将数据填充到页面模板中生成完整的 HTML 页面。
-
客户端注水(Hydration):在客户端将服务端生成的 HTML 页面“激活”,绑定事件和状态,使页面具有交互性。
-
部署:部署包含服务端代码和客户端代码的应用,确保服务器能够正确处理 SSR 请求。
8、怎么分析性能?
1. 使用浏览器开发者工具:
-
Performance 面板:浏览器开发者工具中的 Performance 面板可以记录页面加载过程中的各个阶段,包括网络请求、渲染时间等,帮助定位性能瓶颈。
-
Network 面板:可以查看页面加