什么是构建工具
企业级项目构建可能会具备哪些功能?
1,typescript:如果遇到ts文件我们需要使用tsc将ts代码转化为js代码
2,react/vue: 安装react-component/vue-component,将我们写的jsx文件或者.vue文件转化为render函数
3,less/sass/postcss/component-style: 使用less-loader...等一系列编译工具
4,语法降级:bable将es的新语法转化为旧版浏览器可以接受的语法
5,体积优化:uglifyjs将我们的代码压缩变成体积更小的性能更高的文件
我们代码一变化就有人自动把上边的内容走一遍这就是构建工具
一个构建工具他到底承担了哪些工作?
1,模块化工作支持:直接从node—modules里引入代码 + 多种模块化支持
2,处理代码兼容性:比如babel语法降级,less,ts(构建工具将这些语法对应的处理工具集成进来自动化处理
3,提高项目性能:压缩文件,代码分割
4,优化开发体验:
构建工具自动帮你监听文件的变化,当文件变化后自动帮你调用对应的集成工具进行打包,然后浏览器重新运行(整个过程叫热更新 hot replacement)
开发服务器:域问题,用react-cli vue-cli解决跨域问题
构建工具他让我们不用关心我们的代码在浏览器如何运行,只需要首次给构建工具提供一个配置文件(非必须的,如果不给他他会默认帮你处理),我们就可以在下次需要更新时调用一次对应的命令就行了,如果我们再结合热更新,我们我就不需要管任何东西,这就是构建工具为我们做的
vite相较于webpack的优势
webpack支持多种模块化,他一开始必须要统一模块化代码,所以意味着他需要将所有的依赖都读取一遍
vite是基于es modules的,侧重点不一样,侧重点不一样webpack更多的关注兼容性,而vite关注浏览器端的开发体验
vite脚手架和vite的区别
create-vite内置了vite
vite启动项目初体验
开箱即用:不需要任何额外的的配置就可以使用vite来帮你处理构建工作
浏览器导入esm为什么不默认导入node_modules?
浏览器导入esm规范都是通过网络请求来进行导入的,为了节约网络性能
vite依赖预构建(开发环境下)
vite的预加载
对于esm的引入进行了路径补全(搜寻依赖的过程是自当前目录依次向上查找的过程,直到搜索到根目录或者搜索到对应依赖为止
依赖预构建:首先vite会找到对应的依赖,然后调用esbuild(对js语法进行处理的一个库),将其他规范的代码转换成es_modules代码规范,然后放到当前目录下的node_modules/.vite/deps,同时对es_modules规范的各个模块进行统一集成
它解决了三个问题:
1,不同的第三方包有不同的导出方式
2,对路径的处理上可以直接使用.vite/deps,方便路径重写
3,网络多包传输的性能问题(也是原生esm不敢支持node_modules的原因之一)
vite生产环境下的打包会全权交给rollup库
vite配置文件语法以及开发环境和生产环境的区分
标准注释
/**
* @param String //传参类型
* @return {string} //导出类型
*/
function bar(){
}
bar()
在vscode中的语法提示
import { defineConfig } from "vite";
export default defineConfig({
optimizeDeps:{
exclude:[]//将数组中依赖不进行依赖跟踪
}
})
/** @type import("vite").Userconfig */
const defineConfig ={
optimizeDeps:{
exclude:[]//将数组中依赖不进行依赖跟踪
}
}
/** @type import("vite").Userconfig */
const viteconfig ={
optimizeDeps:{
exclude:[]//将数组中依赖不进行依赖跟踪
},
}
export default viteconfig
关于环境的处理
使用webpack需要区分配置文件的一个环境
webpack.dev.config webpack.prod.config webpack.base.config webpackmerqe
vite进入dev还是serve主要取决于我们的输入命令
import { defineConfig } from "vite";
// 策略模式
const envResolver = {
"bulid":()=>Object.assign( {},viteBaseconfig,viteprodconfig),
"bulid":()=>Object.assign( {},viteBaseconfig,vitedevconfig)
}
export default defineConfig(({command})=>{
console.log(command);
return envResolver[command]()
})
vite环境变量配置
环境变量:会根据当前的代码环境的变化的变量就叫做环境变量
const envResolver = {
"build": () => {
console.log("生产环境");
return ({ ...viteBaseConfig, ...viteProdConfig })
},
"serve": () => {
console.log("开发环境");
return ({ ...viteBaseConfig, ...viteProdConfig }) // 新配置里是可能会被配置envDir .envA
}
}
export default defineConfig(({ command, mode }) => {
// 是build 还是serve主要取决于我们敲的命令是开启开发环境还是生产环境
// console.log("process", process.cwd());
// 当前env文件所在的目录
// 第二个参数不是必须要使用process.cwd(),
const env = loadEnv(mode, process.cwd(), "");
return envResolver[command]();
})
export default defineConfig({
optimizeDeps:{
exclude:[]//将数组中依赖不进行依赖跟踪
},
envPrefix:"ENV_",修改前缀
})
当我们在终端输入运行开发模式或者生产模式后,vite会调用dotenv这个第三方库去解析命令,首先会读取.env文件,并解析这个文件中的对应变量 并将其注入到process对象下(但是vite考虑到和其他配置的一些冲突问题, 他不会直接注入到process对象下)
而我们手动调用loadenv确认env文件
当我们调用loadenv的时候, 他会做如下几件事:
- 直接找到.env文件并解析其中的环境变量 并放进一个对象里
- 会将传进来的mode这个变量的值进行拼接:
.env.development
, 并根据我们提供的目录去取对应的配置文件并进行解析, 并放进一个对象 3.如果是客户端,vite会将对应得的环境变量注入到import.meta.env里
vite默认拦截隐私变量(除非VITE开头)直接去import.meta.env,想要修改前缀可以使用(envPrefix)
vite在node端读取esm规范时会率先node去解析文件语法进行替换成cmd规范(splic)
vite开发服务器原理以及vite为什么可以让浏览器识别.vue文件
vite服务器接收到不同的请求后,处理获取文件的绝对路径(fs,path),再通过response("content-Type","text-XXX")改变格式返回给客户端(.vue文件会进行一个字符串替换AST语法分析)
vite中对于css以及css模块化的简单处理
在vite中处理css
vite天生就支持对css文件的直接处理
- vite在读取到main.js中引用到了Index.css
- 直接去使用fs模块去读取index.css中文件内容
- 直接创建一个style标签, 将index.css中文件内容直接copy进style标签里
- 将style标签插入到index.html的head中
- 将该css文件中的内容直接替换为js脚本(方便热更新或者css模块化), 同时设置Content-Type为js 从而让浏览器以JS脚本的形式来执
css模块化(cssmodule)为了解决类名重复的问题
全部都是基于node
- module.css (module是一种约定, 表示需要开启css模块化)
- 他会将你的所有类名进行一定规则的替换(将footer 替换成 _footer_i22st_1)
- 同时创建一个映射对象{ footer: "_footer_i22st_1" }
- 将替换过后的内容塞进style标签里然后放入到head标签中 (能够读到index.html的文件内容)
- 将componentA.module.css内容进行全部抹除, 替换成JS脚本
- 将创建的映射对象在脚本中进行默认导出
vite配置文件中css配置流程(vite中配置postcss)
css: { // 对css的行为进行配置
// modules配置最终会丢给postcss modules
modules: { // 是对css模块化的默认行为进行覆盖
localsConvention: "camelCaseOnly", // 修改生成的配置对象的key的展示形式(驼峰还是中划线形式)
scopeBehaviour: "local", // 配置当前的模块化行为是模块化还是全局化 (有hash就是开启了模块化的一个标志, 因为他可以保证产生不同的hash值来控制我们的样式类名不被覆盖)
// generateScopedName: "[name]_[local]_[hash:5]" // https://github.com/webpack/loader-utils#interpolatename
// generateScopedName: (name, filename, css) => {
// // name -> 代表的是你此刻css文件中的类名
// // filename -> 是你当前css文件的绝对路径
// // css -> 给的就是你当前样式
// console.log("name", name, "filename", filename, "css", css); // 这一行会输出在哪??? 输出在node
// // 配置成函数以后, 返回值就决定了他最终显示的类型
// return `${name}_${Math.random().toString(36).substr(3, 8) }`;
// }
hashPrefix: "hello", // 生成hash会根据你的类名 + 一些其他的字符串(文件名 + 他内部随机生成一个字符串)去进行生成, 如果你想要你生成hash更加的独特一点, 你可以配置hashPrefix, 你配置的这个字符串会参与到最终的hash生成, (hash: 只要你的字符串有一个字不一样, 那么生成的hash就完全不一样, 但是只要你的字符串完全一样, 生成的hash就会一样)
globalModulePaths: ["./componentB.module.css"], // 代表你不想参与到css模块化的路径
},
preprocessorOptions: { // key + config key代表预处理器的名
less: { // 整个的配置对象都会最终给到less的执行参数(全局参数)中去
// 在webpack里就给less-loader去配置就好了
math: "always",//处理less中的表达式
globalVars: { // 全局变量
mainColor: "red",
}
},
},
devSourcemap: true, // 开启css的sourceMap(文件索引)
postcss: {postcssPresetEnv()}, // 配置postcss相关(post预设)
},
postcss
在css执行前对于css进行预处理,它的处理本包含less和sass但因为维护成本的原因而放弃,所以业内就产生了一个新的说法: postcss是后处理器
const postcssPresetEnv = require("postcss-preset-env");
// 预设就是帮你一次性的把这些必要的插件都给你装上了
// 做语法的编译 less语法 sass语法 (语法嵌套 函数 变量) postcss的插件 -->
module.exports = {
plugins: [postcssPresetEnv(/* pluginOptions */)]
}
const postcssPresetEnv = require("postcss-preset-env");
const path = require("path"); // 做路径处理的
module.exports = {
plugins: [
postcssPresetEnv({
importFrom: path.resolve(__dirname, "./variable.css"), // 就好比你现在让postcss去知道 有一些全局变量他需要记下来
})
]
}
node大致原理
利于fs读取模块文件内容复制,放入立即执行函数中
path,fs的含义
1,fs:处理文件的模块(修改文件,读文件的一些操作)
2,path:字符串处理方法,内部有非常多路径字符串处理方法
3,__dirname:可以用来动态获取当前文件所属目录的绝对路径
4,__filename:可以用来动态获取当前文件的绝对路径,包含当前文件
vite别名配置
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"), // 设置别名, 以后我们在其他组件中可以使用@来代替src这个目录
}
},
resolve.alias的原理
文件运行时读取到别名配置时找到别名配置进行替换
vite对于svg的处理
vite对svg依旧是开箱即用
vite在生产环境对静态资源的处理
build: {
rollupOptions: { // 配置rollup的一些构建策略(打包生产工具)
output: { // 控制输出
assetFileNames: "[hash].[name].[ext]" // hash在rollup里面, hash代表将你的文件名和文件内容进行组合计算得来的结果
}
},
assetsInlineLimit: 4096000, // 4000kb 小于数值转换base64,大于转化静态文件
outDir: "dist",打包文件夹名字
assetsDir: "static"静态资源文件夹名字
},
vite插件理解
vite会在生命周期的不同阶段中去调用不同的插件以达到不同的目的
vite-aliases插件
vite-aliases可以帮助我们自动生成别名: 检测你当前目录下包括src在内的所有文件夹, 并帮助我们去生成别名
ViteAliases({
"@": "/**/src",
"@aseets": "/**/src/assets",
"@components": "/**/src/components",
})
vite-plugin-html
vite-plugin-html可以可以帮我们动态控制html中的内容,如模板引擎替换(利用 `transformIndexHtml`钩子接收当前的 HTML 字符串和转换上下文)
ViteAliases()
createHtmlPlugin({
inject: {
data: {
title: "主页"//替换主页title
}
}
})
vite-plugin-mock
vite-plugin-mock可以可以帮我们进行数据模拟(拦截api请求,响应模拟数据)
VitePluginMock()
vite生命周期
以下钩子会在服务器启动的时候被调用:
option buildStart
以下钩子会在每个传入模块请求时被调用:
resolveID load transform
以下钩子会在服务器关闭的时候被调用:
buildEnd closeBundle
config:在解析 Vite 配置前调用。钩子接收原始用户配置(命令行选项指定的会与配置文件合并)和一个描述配置环境的变量,包含正在使用的?mode
?和?command
。它可以返回一个将被深度合并到现有配置中的部分配置对象,或者直接改变配置(如果默认的合并不能达到预期的结果)。
configResolved:在解析 Vite 配置后调用。使用这个钩子读取和存储最终解析的配置。当插件需要根据运行的命令做一些不同的事情时,它也很有用。
configureServer:是用于配置开发服务器的钩子。最常见的用例是在内部?connect?应用程序中添加自定义中间件
configurePreviewServer:与?configureServer
?相同,但用于预览服务器。configurePreviewServer
?这个钩子与?configureServer
?类似,也是在其他中间件安装前被调用。如果你想要在其他中间件?之后?安装一个插件,你可以从?configurePreviewServer
?返回一个函数,它将会在内部中间件被安装之后再调用
transformIndexHtml:钩子接收当前的 HTML 字符串和转换上下文
vite对ts的支持
vite 对ts天生支持
ts.confing.json配置
{
"compilerOptions": {
// "target": "ESNext",
"module": "ESNext",
"skipLibCheck": true//跳过node_modules检查
}
}
vite对ts错误阻塞:npm i?vite-plugin-checker
plugins:[checker({
typescript:true
})]
有错误不允许打包
"build": "tsc --noEmit && vite build" // 必须通过才能打包成dist
vite性能优化概述
1,开发时构建速度优化,yarn dev:
webpack,cache-loader (两次构建代码没有变化,直接使用缓存,不调用loader)多线程构建
vite 按需加载
2,页面性能指标:首屏 fcp first content paint 懒加载 代码实现
3,http 优化:协商缓存,强缓存
4,js: 写法上, 防抖 截流 forEach 使用lodash中的,作用域控制
5,css:继承属性,避免过深嵌套
6,生产优化:rollup 优化体积 图片压缩 cdn 分包 tree-sharking
分包策略:分包就是把一些不会常规更新的文件,进行单独打包处理
build: {
minify: false,
rollupOptions: {
output: {
manualChunks: id => {
console.log('打印***id', id)
//包含名字不会更新
if (id.includes('node_modules')) {
return 'vendor'
}
}
}
}
},
gzip压缩:浏览器解析压缩文件
import viteCompression from 'vite-plugin-compression'
export default defineConfig({
plugins: [
viteCompression({
threshold: 1024000 // 对大于 1mb 的文件进行压缩
})
],
});
动态导入:vite 按需加载,es 原生支持 code-split
cdn加速:第三方模块使用cdn,保证自己代码小体积
vite-plugin-fast-cdn-import
vite跨域
将浏览器请求交给node,由node向服务器发送请求,最后响应浏览器
server: {
proxy: {
"/api": {
//target是代理的目标路径
target: "http://open.xxx.cn",
changeOrigin: true, //必须要开启跨域
rewrite: (path) => path.replace(/\/baidu/, ""), // 路径重写
}
}
}
本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。
在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。
本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。
除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。
在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!
代办报建
本公司承接江浙沪报建代办施工许可证。
联系人:张经理,18321657689(微信同号)。
12条评论
信楼主,得永生!http://waxv.cqyiyou.net/test/474888846.html
学习雷锋,好好回帖!http://vsz5.icold2020.com
哥回复的不是帖子,是寂寞!http://i09.jshxhd.cn
论坛人气好旺!http://7ui6f.zt9.net
经典,收藏了!http://l4w.rropnrp.com
楼主内心很强大!http://8o4rp.lyjmshop.com
白富美?高富帅?http://os67sh.33v.com.cn
楼上的能详细介绍一下么?http://z2vg.nanyachem.com
楼上的能详细介绍一下么?http://uvav.8lds.com
楼主写的很经典!https://www.skypeis.com/
经典!http://chaomofang.cn/html/08f98999002.html
今天是个特别的日子,值得纪念!https://www.telegramlp.com/
发表评论