绝了:掘金
前端优化
1: 首屏优化
首屏加载时间一般不超过2-3s,针对首屏的快速显示做优化,比如使用Loading等待动画、服务器渲染首屏(同构)...
2: DNS 预解析
减少DNS解析 时间 和 次数 是个很好的优化方式
浏览器对网站第一次的域名DNS解析查找流程依次为:
浏览器缓存---系统缓存---路由器缓存----ISP DNS缓存---递归搜索
DNS预解析实现方法:
1: 使用meta 告诉浏览器,当前页面要做DNS预解析
<meta http-equiv="x-dns-prefetch-control" content="on" />
2: 在页面header中使用link来强制对DNS预解析
<link ref="dns-prefetch" href="http://bdimg.share.baidu.com" />
PS:DNS预解析主要是用于网站前端页面优化,在SEO中的作用湛蓝还未作验证,
但作为增强用户体验的一部分 rel="dns-prefetch" 或许值得大家慢慢发现。
3: index.html分析 rel=prefetch/preload
rel=preload:告诉浏览器这个资源要给我提前加载。
rel=prefetch:告诉浏览器这个资源空闲的时候给我加载一下。
as=script:告诉浏览器这个资源是script,提升加载的优先级。
Webpack 打包优化
1:路由懒加载
1: 页面实现懒加载
前言
Vue 为什么需要懒加载(按需加载)?
学习Vue的时候,各类教程都会告诉我们:Vue 的特点是SPA——Single Page Application(单页应用程序)。它有着诸如:“只有第一次会加载页面, 以后的每次页面切换,只需要进行组件替换;减少了请求体积,加快页面响应速度,降低了对服务器的压力” 等等优点。但是呢!因为Vue 是SPA,所以首页第一次加载时会把所有的组件以及组件相关的资源全都加载了。这样就会导致首页加载时加载了许多首页用不上的资源,造成网站首页打开速度变慢的问题,降低用户体验。
为了解决上面问题,我们需要对Vue实现组件懒加载(按需加载)
组件懒加载:组件先在路由里注册但不进行组件的加载与执行,等到需要访问组件的时候才进行真正的加载。
1: 第一步:要实现懒加载,就得先将进行懒加载的子模块(子组件)分离出来。
2: 第二步:通过 ES6的动态加载模块import()
引用的子模块会被单独分离出来,打包成一个单独的文件(打包出来的文件被称为chunk )
这里有个知识的前提:
项目通过webpack
打包时会进行资源整合,也就是会把项目中的JS、CSS等文件按照一定的规则进行合并,已达到减少资源请求的目的,但是问题来了:
依照
webpack
原本的打包规则打包项目,我们就无法确定子模块在打包出来的哪个JS文件中,而且子模块的代码会和其他代码混合在同一个文件中。这样就无法进行懒加载操作。所以,要实现懒加载,就得保证懒加载的子模块代码单独打包在一个文件中
3: 第三步:借助import()
,实现子模块(子组件)的独立打包
- 首先,
webpack.config.js
文件配置如下:/*webpack.config.js*/ const path = require('path') module.exports = { entry:'./src/main.js', //入口文件 output: { path: path.resolve(__dirname, 'dist'), chunkFilename: '[name].bundle.js', filename: 'bundle.js', } }
- 创建入口文件
main,js
/* main.js */ // 方式1: 这里引入con.js,注意没有使用import() require('./con.js') // 方式2: 接下来,使用import()引入con.js: // 通过下面这个注释,再配合webpack.config.js的output.chunkFilename,我们可以设置打包生成的文件(chunk)的名字。 import(/* webpackChunkName: "con" */ './con.js') /* con.js */ function cons(){ console.log("123") } module.exports = {cons}
- 接着运行
npm run build
进行打包。 【require()
引入】con.js,打包
结果如下:可以看到使用require()
引入con.js
,打包后的结果是con.js
合并到的bundle.js
。 打开
bundle.js
,可以看到con.js
代码被嵌入bundle.js
-
使用 【import 导入】打包结果如下:
可以看到,【 使用
import()
引入con.js
,con.js
打包成独立的js文件。】小知识点:
import()
中的注释import()
括号里面有一串注释。如:import(/* webpackChunkName: "con" */ './con.js')
它并不是可有可无的东西。通过这个注释,再配合
webpack.config.js
的output.chunkFilename
,我们可以 设置 打包生成的文件(chunk
)的 名字。/*webpack.config.js*/ module.exports = { entry:'./src/main.js', //入口文件 output: { path: path.resolve(__dirname, 'dist'), chunkFilename: '[name].bundle.js', filename: 'bundle.js', } }
这里设定了chunkFilename的命名规则为:
[name]
+.
+bundle.js
。这里的[name]
就是/* webpackChunkName: "con" */
设定的值。
4: 第四步:借助函数实现懒加载(按需加载)【如何正确使用独立打包的子模块文件(children chunk)实现懒加载 】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>懒加载演示</title>
</head>
<body>
<button class="button1" style="cursor: pointer;">懒加载 con.js</button>
<script src="bundle.js"></script>
</body>
</html>
main.js文件
window.onload = () => {
const btn = document.querySelector('.button1')
// 给按钮添加click事件,按钮被点击后,加载 con.js
btn.onclick = () => import(/* webpackChunkName: "con" */ './con.js')
}
可以看到,con.js实现了懒加载(按需加载)。
总结:
懒加载(按需加载)实现原理的概括分为两步:
第一步:将需要进行懒加载的子模块打包成独立的文件(children chunk);
第二步: 借助函数来实现延迟执行子模块的加载代码;
是不是很简单呀!这里的技术难点(就是如何将懒加载的子模块打包成独立的文件)。好在ES6提供了import()。然后这一切就变得十分简单了。
2: 在 Vue-router 实现路由懒加载(按需加载)
import Vue from 'vue'
import VueRouter from 'vue-router'
// 这里引入子模块
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [{
path: '/',
name: 'Home',
// component: Home
// 实现子组件懒加载,则改动如下:将子组件加载语句封装到一个function中,
// 将function赋给component
component: () => import( /* webpackChunkName: "home" */ '../views/Home.vue')
}
]
const router = new VueRouter({
mode: 'history',
routes
})
export default router
上面的例子先加载子组件,然后将子组件命名为Home,最后再将Home赋给Vue的 component。
这样就导致子组件的提前加载。
将子组件加载语句封装到一个function
中,将function
赋给component
。这样就可以实现Vue-router
懒加载(按需加载)。
是不是非常简单!哈哈
可能这里有人会疑惑,component可以接收一个function吗?
这确实可以的。不要被以往的观念束缚。component是对象的一个属性,在Javascript中属性的值是什么类型都可以。
关于懒加载(按需加载) 在Vue中的应用,详细可参考:《Lazy Load in Vue using Webpack’s code splitting》
参考文档