前端缓存(强缓存和协商缓存)
webpack gzip压缩(compression-webpack-plugin),gzip有着比zip更优秀的压缩算法,可以有效的减少文件的大小。
减少重排和重绘
所以要给图片的width和height
<script>
// 为什么要在最后添加script标签
// 避免js操作dom失效
const x = document.getElementById('x')
console.log(x) // null
</script>
<div id="x" style="background: #f00; width: 100px; height: 100px"></div>
<script>
// 在执行完js之前,整个页面都不会渲染,是“空白”的
let startTime = Date.now()
let endTime = startTime + 3000 // 3秒后结束
while (Date.now() < endTime) {
// 模拟一些操作
}
console.log('3秒已到,循环停止。')
// 就会渲染页面了
</script>
如果这个js内容的执行时机不重要,可以把这个耗时的操作<script defer src="./foo.js"></script>
,用defer修饰下,让他不阻塞渲染和解析
let startTime = Date.now()
let endTime = startTime + 3000 // 3秒后结束
while (Date.now() < endTime) {
// 模拟一些操作
}
console.log('3秒已到,循环停止。')
懒加载
代码拆分,动态import
function 关键字的声明和赋值都提升函数写在后面也能调用
,var 关键字声明提升,赋值不提升。
let, const, class 标识符提升,形成死区,声明和赋值都不提升。
console.log('xxxx', x) // undefined
var x = 1
// 即var x会声明提升,就是下面的效果,先var x,在打印,在对x赋值所以是undefined
var x
console.log('xxxx', x) // undefined
x = 1
say()
// 声明和赋值都提升
function say() {
console.log('hi~')
}
<script>
标签(特别是没有 async 或者 defer 属性的)会阻塞渲染并停止 HTML 的解析
。封装了业务组件库(vue + setup + private npm),主要提供基于elementui二次封装和vue的v-bind、v-on指令并且属性配置就是类json schema
form、dialog、table、layout、scss
变量的theme主题基于element官方的nodejs库。
通过脚手架的cli,提供业务通用(crud)模板的最佳实践,用于快速创建一致性的页面。
由于业务原因,使用vue的install注册全局组件,所以需要对组件名称进行检测,防止重名,所以我们提供了一个eslint的插件。
对于破坏性的组件库升级,提供babel的脚本,用于快速migration,更加方便,减少业务开发人员的工作量,也减少出错。
就是利用babel parse对应的js文件的到ast,然后traverse这个ast对于的各个节点,进行rewrite。 比如一个简单的例子,一些替换函数名称,新增函数参数(这只是个思路,具体业务具体分析)
// => old
import { oldFunc } from 'your-lib'
const result = oldFunc('a', 'b')
// => to new
import { newFunc } from 'your-lib'
const result = newFunc('a', 'b', true)
const fs = require('fs')
const path = require('path')
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const generate = require('@babel/generator').default
const t = require('@babel/types')
const sourceCode = fs.readFileSync('./example.js', 'utf-8')
const ast = parser.parse(sourceCode, {
sourceType: 'module',
plugins: ['jsx', 'typescript'],
})
traverse(ast, {
ImportDeclaration(path) {
if (path.node.source.value === 'your-lib') {
path.node.specifiers.forEach((spec) => {
if (t.isImportSpecifier(spec) && spec.imported.name === 'oldFunc') {
spec.imported.name = 'newFunc'
spec.local.name = 'newFunc'
}
})
}
},
CallExpression(path) {
const callee = path.node.callee
if (
t.isIdentifier(callee, { name: 'oldFunc' }) ||
t.isIdentifier(callee, { name: 'newFunc' }) // 已替换也处理
) {
// 替换函数名
callee.name = 'newFunc'
// 添加一个布尔类型参数 true(如果没有)
if (path.node.arguments.length === 2) {
path.node.arguments.push(t.booleanLiteral(true))
}
}
},
})
const output = generate(ast, {}, sourceCode)
fs.writeFileSync('./example.migrated.js', output.code)
console.log('✅ Migration complete.')
我上一份工作的内容是 XXX,在那段时间里我收获了很多,也积累了扎实的 YYY 经验。 不过在后期我也发现,这份工作在技术成长和挑战性方面已经相对稳定,而我本身是一个比较喜欢学习和探索的人, 所以希望能寻找一个更有发展空间、能够接触新技术并参与到关键项目的团队。我觉得贵公司在这方面非常契合我的预期。
我的上一份薪资是??,当时是基于我当时的经验和岗位要求定的。而在这段时间里,我不仅独立承担了多个完整的模块开发,也逐步参与了系统架构优化、性能调优和一些跨团队协作的工作,整体的技术深度和广度都有明显提升。 比如在某个项目中,我通过 XXX 的优化手段,把首页加载时间从 3.2s 优化到 1.8s,用户留存率提升了明显,这类工作也让我意识到,我的输出是可以给业务带来实在价值的。 结合市场行情和我对岗位的理解,我认为 ?? 是一个比较合理的匹配,当然我也更看重的是未来的成长空间和团队氛围。
就那vue3.5来说,vue提供了一个新的hook:useTemplateRef
,但公司有些项目还是vue2.7,所以我根据vue3.5的源码,实现了
一个类似的功能,主要是为了方便在vue2.7中使用ref
来获取组件实例或DOM元素。
import { getCurrentInstance, shallowRef } from 'vue'
export function useTemplateRef(key) {
const vm = getCurrentInstance().proxy
if (!vm) {
throw new Error(
`useTemplateRef() is called when there is no active component ` +
`instance to be associated with.`
)
}
const refs = vm.$refs
const r = shallowRef(null)
Object.defineProperty(refs, key, {
get() {
return r.value
},
set(newValue) {
r.value = newValue
},
})
return r
}