vue项目目录的执行顺序是怎么样的?
-
1、package.json
在执行npm run dev时,会在当前目录寻找package.json文件,此文件包含了项目的名称版本、项目依赖等相关信息。 -
2、webpack.config.js(会被@vue-cli脚手架隐藏)
-
3、vue.config.js
对webpack进行配置,webpack打包的时候会自动对这个文件的配置进行加载。 -
4、index.html
提供一个div给vue挂载。 -
5、main.js
引入了vue、app和router模块,创建了一个vue对象并把app.vue模板的内容挂载到index.html的id为app的div标签下,并绑定了一个路由配置。 -
6、App.vue
上面 main.js 把 App.vue 模板的内容,放置在了 index.html 的 div 标签下面。查看 App.vue 的内容我们看到,这个文件的内容就是整个项目的页面放置的地方(router-view)。
React调用顺序: index.html → index.js → components/组件
原文链接:React进阶(十):React 项目启动原理详解
vue如何加载main.js
npm run dev的时候会出来页面, 是因为你根目录下的package.json文件里script配置了:
"dev": "node build/dev-server.js",
也就是其实执行的是dev-server.js这个文件,里面有定义。
var webpackConfig = require(‘./webpack.dev.conf’);
因为我们这个脚手架工具里是用webpack来打包项目文件的,依赖的webpack.dev.conf文件里又定义了。
var baseWebpackConfig = require(‘./webpack.base.conf’);
在这个依赖webpack.base.conf文件里面entry入口文件就配置了。
app: ‘./src/main.js’
所以当你运行npm run dev的时候就从main.js这个入口文件开始执行了。
怎么设置入口文件和打包路径
vue:在项目的根目录下的vue.config.js文件里添加配置(如果项目中没有这个文件,可以手动创建一个):
pages属性用于设置项目中多页应用的入口文件;
publicPath属性用于设置项目中所有静态资源的基础路径。默认情况下是’/‘,表示根路径。可以根据需要修改这个路径,比如设置为’/my-app/‘,表示静态资源会以’/my-app/‘作为基础路径。
假设一个Vue项目生产环境需要部署到域名的子目录,如https://example.com/my-app/,则需要在vue.config.js中将publicPath设置为’/my-app/'。这样打包后的静态资源引用路径就会自动加上/my-app/前缀。
// vue.config.js
module.exports = {
pages: {
index: {
entry: 'src/main.js',//入口文件
template: 'public/index.html',
filename: 'index.html'
},
subpage: {//多个入口文件
entry: 'src/subpage.js',
template: 'public/subpage.html',
filename: 'subpage.html'
}
}
publicPath: process.env.NODE_ENV === 'production' ? '/my-app/' : '/'
// 其他配置
};
react:使用命令行npm run eject暴露webpack文件,然后在webpack.config.dev.js中修改配置,但不推荐这个做法:
执行 eject 产生了什么变化?
create-react-app 框架本身将 webpack、babel 的相关配置封装在了 react-scripts 中, 执行 npm run eject 后,会将 webpack、babel 等配置暴露在 config 目录下,同时 scripts 目录下会有新的命令文件更新,package.json 文件中 scripts 命令同步更新。
执行 eject 带来了什么问题?
首先,执行 eject 是不可逆的,复杂的 webpack 等配置由框架本身转交给用户自己进行维护了。
其次,在版本迭代时,如果更新了 react、react-scripts、eslint、tsconfig 等依赖,有可能会引起版本依赖的问题,即使我们按错误信息修复了之后,项目还是无法运行。
推荐使用插件 react-app-rewired 更改配置文件,安装插件后,在根目录下配置 config-overrides.js 文件 (类似 vue.config.js)
const path = require('path')
const paths = require('react-scripts/config/paths')
paths.appBuild = path.join(path.dirname(paths.appBuild),'../myApp.org')
封装图片上传组件要适配各个端的话,要考虑的风险点有哪些,以及怎么解决
1、风险点:平台API调用差异
解决方案:判断当前所处的平台,然后再去调用对应的api
2、风险点:上传性能瓶颈,如文件过大,上传时间过久
解决方案:实现分片上传(如按2MB分块),展示上传进度条。(上传进度可视化公式:上传进度 = 已传输分片数 / 总分片数 ×100%)
3、风险点:将其他格式的文件修改为图片格式后上传
解决方案:不使用截取后缀名判断文件格式的方式,使用文件内容也就是二进制数据去判断文件格式(文件的魔术数字(Magic Numbers)或文件签名)。
步骤一:读取文件二进制数据
使用FileReader读取文件的前几个字节(通常前4-32字节足够):
async function readFileHeader(file) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = (e) => {
const buffer = e.target.result;
const bytes = new Uint8Array(buffer);
resolve(bytes);
};
// 仅读取前32字节
reader.readAsArrayBuffer(file.slice(0, 32));
});
}
步骤二:定义魔术数字规则
根据文件类型的十六进制签名定义检测规则:
const fileSignatures = {
jpeg: { offset: 0, bytes: [0xFF, 0xD8] },
png: { offset: 0, bytes: [0x89, 0x50, 0x4E, 0x47] }, // ‰PNG
pdf: { offset: 0, bytes: [0x25, 0x50, 0x44, 0x46] }, // %PDF
zip: { offset: 0, bytes: [0x50, 0x4B, 0x03, 0x04] }, // PK..
gif: { offset: 0, bytes: [0x47, 0x49, 0x46, 0x38] }, // GIF8
};
步骤三:实现检测函数
对比文件的字节与签名是否匹配:
function detectFileFormat(bytes) {
for (const [type, { offset, bytes: signature }] of Object.entries(fileSignatures)) {
const slice = bytes.slice(offset, offset + signature.length);
if (slice.every((byte, i) => byte === signature[i])) {
return type;
}
}
return 'unknown';
}
步骤四:整合使用
async function checkFileFormat(file) {
const bytes = await readFileHeader(file);
const format = detectFileFormat(bytes);
console.log('Detected format:', format);
}
响应式布局该怎么实现
1、百分比布局
百分比是相对于 包含块 的计量单位,通过对属性设置百分比来适应不同的屏幕
包含块:
-
有父元素相对于父元素
-
无父元素相对于视口
-
或者继承于父元素
2、rem布局
rem(font size of the root element)是指相对于根元素的字体大小的单位,rem只是一个相对单位
题外: rem和em的对比
1. rem和em都是相对单位
2. rem相对于根元素
3. em相对于父元素
情景描述:
1. 设置HTML的根元素的font-size为20px
2. 设置一个正方形宽高为2rem
3. 则正方形的宽高为40px
4. 所以1rem === 根元素字号 === 20px
项目中如何方便的使用的rem呢?
设想一个场景,如果一个元素的宽需要47px,根元素是20px,如果要适应不同的终端,需要转为rem,除以20px得到相应的rem值,很麻烦,那么就需要找一个可以简单计算的数值.
1. 设想屏幕宽度为750px,设计稿宽度也为750px
2.设置 font-size = 1rem = 屏幕宽度*100/设计稿宽度 = 100px (乘以100的原因,屏幕宽度/设计稿宽度得出的值是1,而浏览器可以接受的最小字号12px,所以乘以100既可以满足浏览器最小字号的要求,也比较好计算)
3. 屏幕宽度不会只是750px,假设屏幕宽度为width(getBoundingClientRect().width可以获取宽度),在该宽度下的字号为fontSize
4.width/(750*fontsize)=750/(750*100)
5. 通过上面这个方法可以计算出fontSize的值
3、媒体查询 @media screen
CSS媒体查询是实现响应式布局的核心技术,通过检测设备屏幕特性(如宽度、分辨率)动态调整样式。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@media screen</title>
<style>
.box {
width: 10rem;
height: 10rem;
background-color: pink;
margin-left: 20rem;
}
@media screen and (min-width: 1200px) {
html {
font-size: 20px;
}
}
@media screen and (max-width: 1200px) {
html {
font-size: 10px;
}
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>
4 、flex布局
5、vw 和 vh
vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度,除了vw和vh外,还有vmin和vmax两个相关的单位。各个单位具体的含义如下:
vw 相对于视窗的宽度,1vw 等于视口宽度的1%,即视窗宽度是100vw
vh 相对于视窗的高度,1vh 等于视口高度的1%,即视窗高度是100vh
vmin vw和vh中的较小值
vmax vw和vh中的较大值
答案出自响应式布局的实现方式(5种)
webpack跟vite有什么区别
- 核心区别
构建方式
Webpack:采用 打包优先 的模式,需 预构建所有依赖 并生成打包文件后才能启动开发服务器,导致 冷启动时间较长1。
Vite:利用浏览器原生支持的 ES Modules (ESM),实现 按需编译,启动时仅加载当前所需模块,速度极快。
开发体验
Webpack:热更新(HMR)需重新构建修改的模块及其依赖链,响应速度随项目规模增长而下降。
Vite:HMR 直接更新修改的模块,无需重新打包,响应速度与项目复杂度无关,实现 毫秒级更新。
生产构建
Webpack:内置成熟的代码分割、Tree Shaking 等优化策略,适合复杂场景。
Vite:默认使用 Rollup 进行生产构建,配置更简洁,但对插件生态的依赖度较高。
配置复杂度
Webpack:需手动配置加载器(Loader)、插件(Plugin)等,学习曲线陡峭。
Vite:内置对 TypeScript、CSS 预处理器等的支持,开箱即用,配置更简单。
2. 适用场景
选择 Webpack 的情况:
需要兼容旧版本浏览器(如 IE11);
项目依赖大量 Webpack 专属插件(如复杂代码分割策略);
已有成熟 Webpack 配置的大型遗留系统。
选择 Vite 的情况:
面向现代浏览器的应用开发(如 Vue/React 单页应用);
追求极速启动与热更新效率的新项目;
希望减少构建配置的复杂度,快速搭建开发环境。
3. 实战示例对比
Webpack 启动耗时:典型项目冷启动时间:30秒以上
npm run dev
Vite 启动耗时:典型项目冷启动时间:1秒以内
npm run dev
1. 打包机制
Webpack:采用传统打包模式,通过静态分析将所有模块(如JS、CSS、图片)提前打包成一个或多个bundle。开发环境下需等待整个打包完成才能启动服务,可能导致冷启动较慢4。
Webpack流程: 代码分析 → 依赖图构建 → 打包bundle → 启动服务
Webpack流程: 代码分析 → 依赖图构建 → 打包bundle → 启动服务
Vite:基于浏览器原生ES模块(ESM)支持,开发环境按需编译。仅编译当前页面所需模块,大幅减少初始等待时间。生产环境则使用Rollup进行优化打包4。
Vite流程: 启动服务 → 按需编译模块
Vite流程: 启动服务 → 按需编译模块
2. 配置复杂度
Webpack:配置复杂,需手动处理加载器(Loader)、插件(Plugin)及代码分割规则。例如,处理Sass需配置sass-loader、css-loader和style-loader2。
Vite:开箱即用,内置对TypeScript、CSS预处理器等的支持,默认配置覆盖常见场景。支持自定义配置,但更注重简化流程。
3. 开发环境性能
冷启动速度:
Webpack需打包全部模块,项目越大启动越慢。
Vite直接启动开发服务器,仅编译入口文件,速度极快4。
热更新(HMR):
Webpack需重新打包修改的模块及其依赖,可能导致延迟。
Vite通过ESM实现精准HMR,仅更新修改的模块,响应更快。
4. 生产环境构建
Webpack:自行处理生产构建,支持代码分割、Tree Shaking等优化,适合复杂项目5。
Vite:使用Rollup进行生产打包(尽管开发环境用ESBuild)。Rollup在生成小体积代码方面表现优异,但复杂场景下可能需额外配置。
5. 插件生态
Webpack:拥有庞大成熟的插件生态,覆盖各类需求(如压缩、懒加载)。
Vite:插件生态较新,但兼容Rollup插件,且社区正在快速扩展。
6. 适用场景
Webpack:适合大型复杂项目(如多入口、自定义构建流程),需要深度优化和长期维护3。
Vite:适合快速原型开发、中小型项目或现代框架(如Vue/React)的轻量化应用3。
Vite是否需要打包?
开发环境无需打包:Vite在开发模式下直接使用浏览器原生ES模块加载能力,通过按需编译实现秒级启动。例如修改单文件组件时,仅重新编译当前文件。
生产环境需要打包:为了优化资源加载性能(如代码压缩、Tree-shaking、懒加载),Vite在生产环境必须进行打包构建,此时会将代码转换为兼容性更好的传统静态资源格式。
二、生产环境构建流程
依赖预构建
使用esbuild将CommonJS模块转换为ES模块
合并碎片化依赖为单个文件,减少网络请求
建立模块缓存机制加速构建
Rollup打包阶段
代码分割(Code Splitting)
资源压缩(JS/CSS minify)
静态资源处理(图片转base64、文件名哈希)
兼容性语法转换(通过Babel)
环境变量注入
根据.env.production等文件注入变量
在构建时通过import.meta.env替换实际值2
vite为什么生产环境不用esbuild?
虽然esbuild打包速度比Rollup快10-100倍,但Vite仍选择Rollup的核心原因:
插件生态兼容性:现有Vite插件体系基于Rollup API设计
功能完整性:Rollup对CSS代码分割、复杂模块转换等场景支持更成熟
稳定性验证:Rollup经过长期生产环境验证(Webpack、Parcel等工具也采用其核心)
seo
SEO,全称Search Engine Optimization,即搜索引擎优化。它是一种利用搜索引擎的规则来提高网站在搜索引擎内自然排名的方式,从而吸引更多的用户访问网站,提高网站的访问量,进而提升网站的销售能力和宣传能力,达到提升网站品牌效应的目的。
SEO主要分为两种:站外SEO和站内SEO。站外SEO则是指从外部网站对搜索引擎排名的影响,其中最有用的外部因素通常是反向链接,即外部链接。站内SEO指的是网站的内部优化,包括代码标签优化、内容优化和网址优化等。
站外SEO
1.外部链接建设
外部链接是站外SEO最重要的一种策略。这些链接是指从其他网站链接到你的网站,被视为一种“投票”,可以提高你网站的排名和权重。
2.搜索引擎收录提交
如果搜索引擎没有及时抓取和收录你的网站内容,那么网站内容就无法在搜索引擎上展现。因此,你可以通过搜索引擎的提交入口(百度、搜狗、360、谷歌)进行提交,以便加快收录速度。
站内SEO
1.使用title标签
标签包裹的文字要对网页内容有准确而简洁,能够吸引用户,而且长度要适中。
<title>博客网</title>
2.使用meta标签
meta标签在HTML语言中,是head区的一个辅助性标签,主要用于提供有关HTML文档的元数据。这些元数据不会显示在页面上,但会被浏览器解析,用于指导浏览器的行为,或者为搜索引擎提供关于页面的信息。
description:用于提供网页的描述,这有助于搜索引擎理解网页内容。
keywords:用于提供网页的关键词,这有助于搜索引擎对网页进行分类和排名。
author:用于标识网页的作者。
viewport:用于控制网页在移动设备上的视口设置。
robots:用于指导搜索引擎爬虫如何处理页面,例如是否允许索引或跟踪链接。
<meta name="description" content="这是一个面试题记录博客">
3.多使用语义化标签
HTML5新出的 Header, Nav,Aside,Article,Footer等语义化标签,能帮助爬虫更好的获取页面内容。img的alt属性,为搜索引擎提供替代文本,图片使用alt标签优化。
4. robots文件
robots.txt 是一个文本文件,用于指导搜索引擎爬虫如何访问和索引网站的页面。可以通过合理地使用 robots.txt 来帮助优化网站的 SEO(搜索引擎优化)。
1.了解基础
robots.txt 文件应位于网站的根目录下。
它的语法相对简单,主要使用 User-agent 和 Disallow 指令。
User-agent 用于指定爬虫的名称,例如 * 表示所有爬虫。
Disallow 用于指定不希望爬虫访问的 URL 路径。
2. 允许爬虫访问:
默认情况下,如果不设置 robots.txt,爬虫会尝试访问并索引网站的所有页面。
为了确保网站内容能被搜索引擎找到,通常建议允许所有爬虫访问。
3.排除敏感或重复内容:
使用 Disallow 指令排除不希望被索引的页面,例如后台管理页面、重复内容、测试页面等。
这有助于减少搜索引擎的噪音,提高网站的整体质量得分。
4.优化爬虫效率:
通过 robots.txt 可以指导爬虫优先访问重要页面,但这主要依赖于搜索引擎的实现,不一定总是有效。
确保 robots.txt 文件尽可能小,以减少爬虫的加载时间。
5.定期检查和更新:
随着网站内容的更新和结构的调整,可能需要定期检查和更新 robots.txt。
确保它始终与网站的当前状态保持一致。
5.网站性能
网站打开速度越快,识别效果越好,否则爬虫会认为该网站对用户不友好,降低爬取效率,这时候就要考虑压缩文件体积之类的性能优化了。
6.使用https
使用HTTPS,因为它提供更高的安全性和更好的用户体验。当您的网站使用HTTPS时,搜索引擎会将其视为更可信和更安全的网站。
答案出自作为前端工程师如何SEO优化
websocket
一、WebSocket协议简介
WebSocket是HTML5引入的一种基于TCP的全双工通信协议,由W3C于2011年标准化。与HTTP的请求-响应模式不同,WebSocket通过一次握手即可建立持久连接,允许客户端和服务器随时双向传输数据,适用于实时性要求高的场景。
二、协议特点
基于TCP与应用层协议:
WebSocket运行在TCP之上,属于独立的第七层协议,默认端口为80(WS)或443(WSS)。
帧结构设计:
数据通过二进制帧传输,帧头包含操作码(如 0x1表示文本帧)、FIN标志(标记消息结束)及掩码(客户端到服务端需掩码加密)。
握手过程:
客户端发送包含Sec-WebSocket-Key的HTTP升级请求,服务端响应时生成Sec-WebSocket-Accept,计算方式为:
Sec-WebSocket-Accept=Base64(SHA-1(Sec-WebSocket-Key+
258EAFA5-E914-47DA-95CA-C5AB0DC85B11))
Sec-WebSocket-Accept=Base64(SHA-1(Sec-WebSocket-Key+258EAFA5-E914-47DA-95CA-C5AB0DC85B11))
验证成功后,连接升级为WebSocket协议。
三、应用场景
实时通信
如在线聊天、弹幕系统,消息可实时推送2。
协同编辑工具
多用户同时编辑文档时同步内容变更。
金融交易与游戏
股票价格实时推送、多玩家在线游戏的即时状态同步。
四、示例代码
// 创建WebSocket连接
const socket = new WebSocket('wss://example.com/ws');
// 监听消息
socket.onmessage = function(event) {
console.log('收到数据:', event.data);
};
// 发送数据
socket.send('Hello Server!');
WebSocket (WS) 和 WebSocket Secure (WSS) 的定义与区别
- 定义 WebSocket (WS) 基于 HTML5 的通信协议,支持客户端与服务端在单个 TCP 连接上进行全双工双向通信。通过一次握手建立持久连接,允许双方主动推送数据,适用于实时性要求高的场景(如在线聊天、实时游戏)。协议标识为 ws://,默认使用80端口(与 HTTP相同)。
WebSocket Secure (WSS) 是 WS 的安全版本,通过 SSL/TLS加密传输数据,确保通信内容的机密性和完整性。协议标识为 wss://,默认使用443端口(与 HTTPS相同)。常用于需要保护敏感信息的场景(如金融交易、隐私数据传输)。
- 核心区别:
- 应用场景
WS:适合内部系统或对安全性要求不高的实时通信,如本地测试、局域网监控。
WSS:必须用于涉及用户隐私或敏感数据的场景,如在线支付、医疗信息同步。
axios断连怎么处理
1、可以在请求拦截器和响应拦截器里面对错误信息进行判断,如果是网络错误则可以通过事件总线或者vuex的方式通知app.vue,显示一个网络错误相关的页面,如刷新按钮等,等用户点击或者执行某个动作后重新发起请求。
2、当发生网络错误的时候,我们也可以自动重新发起请求,但是需要设置一个重试次数和延迟时间。对于请求重试的功能来说,我们希望让用户不仅能够设置重试次数,而且可以设置重试延时时间。当请求失败的时候,若该请求的配置对象配置了重试次数,而 Axios 就会重新发起请求进行重试操作。为了能够全局进行请求重试,接下来我们在响应拦截器上来实现请求重试功能,具体代码如下所示:
axios.interceptors.response.use(null, (err) => {
let config = err.config;
if (!config || !config.retryTimes) return Promise.reject(err);
const { __retryCount = 0, retryDelay = 300, retryTimes } = config;
// 在请求对象上设置重试次数
config.__retryCount = __retryCount;
// 判断是否超过了重试次数
if (__retryCount >= retryTimes) {
return Promise.reject(err);
}
// 增加重试次数
config.__retryCount++;
// 延时处理
const delay = new Promise((resolve) => {
setTimeout(() => {
resolve();
}, retryDelay);
});
// 重新发起请求
return delay.then(function () {
return axios(config);
});
});
前端性能优化相关知识
一、代码层面优化
Vue框架优化
使用v-if替代v-show:v-if是惰性渲染,适合切换频率低的场景;v-show通过CSS控制显示,适合频繁切换场景
列表渲染添加唯一key:帮助Vue高效复用DOM元素
组件懒加载:通过script setup或defineAsyncComponent延迟加载非关键组件
// 异步组件示例
const AsyncComponent = defineAsyncComponent(() => import(‘./AsyncComponent.vue’))
通用JavaScript优化
避免强制同步布局(Layout Thrashing)
使用事件委托减少事件监听器数量
采用Web Workers处理CPU密集型任务
二、构建工具优化(Webpack)
代码分割
// webpack.config.js
optimization: {
splitChunks: {
chunks: ‘all’
}
}
Tree Shaking
使用ES6模块语法(import/export)
配置sideEffects标记无副作用模块
资源压缩
启用TerserPlugin压缩JS
使用CssMinimizerPlugin压缩CSS
配置图片压缩(image-webpack-loader)
三、基础Web技术优化
图片优化(核心优化项)
使用WebP格式(比JPEG小25-34%)
响应式图片:通过与srcset适配不同分辨率
SVG图标替代位图
HTTP缓存策略
Nginx
Nginx配置示例
location ~* .(js|css|png)$ {
expires 1y;
add_header Cache-Control “public”;
}
通过Last-Modified和ETag实现条件请求3
CDN加速
静态资源部署到CDN
启用HTTP/2协议提升并发性能4
资源预加载
<link rel="preload" href="critical.css" as="style">
<link rel="preconnect" href="https://cdn.example.com">
四、监控与持续优化
性能指标监测
核心Web指标:LCP(最大内容渲染)、FID(首次输入延迟)、CLS(累计布局偏移)
工具链