vue的seo
我们知道,常规用 Vue/React 开发的是 SPA 应用。
但是天然的单页面应用 SEO 就是不好。
虽然说现在也有各种技术可以改善了,比如使用服务端渲染、静态页面生成,不过也存在各种缺点。
但是即使这样,也抵不住 Vue/React 这类框架的潮流。
也有很多产品也可以通过其他亮点而不依赖 SEO 普及开,
也有需要登录才能用的,使用 SEO 也没有什么意义。
几个名词
CSR: Client Side Render 客户端渲染,即普通的SPA
SSR: Server Side Render 服务端渲染
SSG: Static Site Generation 静态生成, 也有人称其为预渲染Prerendering
这个在使用此类框架创建项目的时候,会让你选择。比如nuxtJS
? Rendering mode: // 选择你想要的 Nuxt 模式
Universal (SSR / SSG) // 通用模式 ssr或者ssg
Single Page App // 普通spa模式
SSR vs SSG
如果你调研服务器端渲染 (SSR) 只是用来改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么你可能需要预渲染。无需使用 web 服务器实时动态编译 HTML,而是使用预渲染方式,在构建时 (build time) 简单地生成针对特定路由的静态 HTML 文件。优点是设置预渲染更简单,并可以将你的前端作为一个完全静态的站点。
SSG 性能最佳,SSR 适用范围最广,CSR 跳转体验最优,非得在三者之间做出抉择吗?不,我全都要
CSR模式
这是Vue/React默认的模式。在这种模式下,页面之间跳转体验良好,借助于vdom、historyApi等技术,让网站交互如原生app般流畅。 但是却对seo不好,尤其是国内搜索引擎,如百度爬虫。

<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
<title>csr-vue</title>
<link href="/js/about.addee37b.js" rel="prefetch" />
<link href="/css/app.b087a504.css" rel="preload" as="style" />
<link href="/js/app.a33b1734.js" rel="preload" as="script" />
<link href="/js/chunk-vendors.2d69e2a7.js" rel="preload" as="script" />
<link href="/css/app.b087a504.css" rel="stylesheet" />
</head>
<body>
<noscript>
<strong>
We're sorry but csr-vue doesn't work properly without JavaScript enabled.
Please enable it to continue.
</strong>
</noscript>
<div id="app">
</div>
<script src="/js/chunk-vendors.2d69e2a7.js">
</script>
<script src="/js/app.a33b1734.js">
</script>
</body>
</html>
可以看到,客户端渲染是通过加载执行JS来创建DOM元素构建页面,但是爬虫只是请求静态资源,不会执行JS文件,所以抓取不到DOM结构,也分析不出来有用的信息。
SSR模式
ssr和ssg均有原生的编写模式,如vue的vue-server-renderer、react的react-dom/server。但是编写起来较为麻烦,除了研究外,实际用于生产的较少,作为研究原理性质可用。如果后边有时间 会单拉出来讲
现在我们使用框架来解决,vue对应的为nuxtJs(对应的react的框架为nextjs)。
用脚手架创建项目完毕npx create-nuxt-app ssr-vue,
并且本地运行启动npx create-nuxt-app ssr-vue

<!doctype html>
<html data-n-head-ssr lang="en" data-n-head="%7B%22lang%22:%7B%22ssr%22:%22en%22%7D%7D">
<head>
<title>ssr-vue</title>
<meta data-n-head="ssr" charset="utf-8">
<meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1">
<meta data-n-head="ssr" data-hid="description" name="description" content="">
<link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="preload" href="/_nuxt/runtime.js" as="script">
<link rel="preload" href="/_nuxt/commons/app.js" as="script">
<link rel="preload" href="/_nuxt/vendors/app.js" as="script">
<link rel="preload" href="/_nuxt/app.js" as="script">
<link rel="preload" href="/_nuxt/pages/index.js" as="script">
<link rel="preload" href="/_nuxt/components/logo.js" as="script">
<style data-vue-ssr-id="3191d5ad:0">
.nuxt-progress {
position: fixed;
top: 0px;
...
</style>
</head>
<body>
<div data-server-rendered="true" id="__nuxt">
<!---->
<!---->
<div id="__layout">
<div>
<div class="container">
<div>
<svg>...</svg>
<h1 class="title">
ssr-vue
</h1>
<div class="links"><a href="https://nuxtjs.org/" target="_blank" rel="noopener noreferrer" class="button--green">
Documentation
</a> <a href="https://github.com/nuxt/nuxt.js" target="_blank" rel="noopener noreferrer" class="button--grey">
GitHub
</a></div>
</div>
</div>
</div>
</div>
</div>
<script>
window.__NUXT__ = (function(a, b) {
return {
layout: "default",
data: [{}],
fetch: {},
error: a,
serverRendered: true,
routePath: b,
config: {
app: {
basePath: b,
assetsPath: "\u002F_nuxt\u002F",
cdnURL: a
}
},
logs: []
}
}(null, "\u002F"));
</script>
<script src="/_nuxt/runtime.js" defer></script>
<script src="/_nuxt/pages/index.js" defer></script>
<script src="/_nuxt/components/logo.js" defer></script>
<script src="/_nuxt/commons/app.js" defer></script>
<script src="/_nuxt/vendors/app.js" defer></script>
<script src="/_nuxt/app.js" defer></script>
</body>
</html>
可以看到dom已经在服务端渲染完毕
我们不用官方脚手架生成的页面,下边我们自己写一个demo,包含请求
<template>
<div class="container">
<fieldset>
<legend>ssr-asyncData数据</legend>
<div v-for="item in teachers" :key="item.id">姓名: {{item.name}}</div>
</fieldset>
<fieldset>
<legend>ssr-data数据</legend>
<div v-for="item in teachers1" :key="item.id">姓名: {{item.name}}</div>
</fieldset>
<fieldset>
<legend>ssr-created</legend>
<div v-for="item in teachers2" :key="item.id">姓名: {{item.name}}</div>
</fieldset>
<fieldset>
<legend>csr-mounted数据</legend>
<div v-for="item in teachers3" :key="item.id">姓名: {{item.name}}</div>
</fieldset>
</div>
</template>
<script>
const getTeachers = ()=> {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
const teachers = [
{id:202101,name:'张老师'},
{id:202102,name:'丁老师'}
];
resolve(teachers);
},2000)
})
}
export default {
data(){ // 会走ssr
return {
teachers1: [
{id:202101,name:'张老师1'},
{ id:202102,name:'丁老师1'}
],
teachers2: [],
teachers3: []
}
},
mounted(){ // 会走csr
this.teachers3 = [
{id:202101,name:'张老师3'},
{id:202102,name:'丁老师3'}
]
},
created(){ // 会走ssr
this.teachers2 = [
{id:202101,name:'张老师2'},
{id:202102,name:'丁老师2'}
]
},
async asyncData({ params }) { // 会走ssr
const teachers = await getTeachers();
return {teachers}
}
}
</script>
<style>
.container {
margin: 0 auto;
padding: 10px;
}
</style>
编译后,可以看到data和created、asyncData里的代码都会被ssr。而其他钩子里的数据都会被csr。
这是因为:
在任何 Vue 组件的生命周期内, 只有
beforeCreate和created这两个方法会在 客户端和服务端被调用。其他生命周期函数仅在客户端被调用。
https://www.nuxtjs.cn/guide/plugins
Nuxt.js 会将
asyncData返回的数据融合组件data方法返回的数据一并返回给当前组件。
https://www.nuxtjs.cn/guide/async-data
<!DOCTYPE html>
<html data-n-head-ssr="" lang="en" data-n-head="%7B%22lang%22:%7B%22ssr%22:%22en%22%7D%7D">
<head>
<title>ssr-vue</title>
<meta data-n-head="ssr" charset="utf-8" />
<meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1" />
<meta data-n-head="ssr" data-hid="description" name="description" content="" />
<link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="preload" href="/_nuxt/runtime.js" as="script" />
<link rel="preload" href="/_nuxt/commons/app.js" as="script" />
<link rel="preload" href="/_nuxt/vendors/app.js" as="script" />
<link rel="preload" href="/_nuxt/app.js" as="script" />
<link rel="preload" href="/_nuxt/pages/index.js" as="script" />
<link rel="preload" href="/_nuxt/pages/index.4ee7ce6db4f1f6ace22f.hot-update.js" as="script" />
<style data-vue-ssr-id="3191d5ad:0">
.nuxt-progress {
position: fixed;
top: 0px;
...
</style>
</head>
<body>
<div data-server-rendered="true" id="__nuxt">
<!---->
<!---->
<div id="__layout">
<div>
<div class="container">
<fieldset>
<legend>ssr-asyncData数据</legend>
<div>
姓名: 张老师
</div>
<div>
姓名: 丁老师
</div>
</fieldset>
<fieldset>
<legend>ssr-data数据</legend>
<div>
姓名: 张老师1
</div>
<div>
姓名: 丁老师1
</div>
</fieldset>
<fieldset>
<legend>ssr-created</legend>
<div>
姓名: 张老师2
</div>
<div>
姓名: 丁老师2
</div>
</fieldset>
<fieldset>
<legend>csr-mounted数据</legend>
</fieldset>
</div>
</div>
</div>
</div>
<script>window.__NUXT__=(function(a,b){return {layout:"default",data:[{teachers:[{id:202101,name:"张老师"},{id:202102,name:"丁老师"}]}],fetch:{},error:a,serverRendered:true,routePath:b,config:{app:{basePath:b,assetsPath:"\u002F_nuxt\u002F",cdnURL:a}},logs:[]}}(null,"\u002F"));</script>
<script src="/_nuxt/runtime.js" defer=""></script>
<script src="/_nuxt/pages/index.js" defer=""></script>
<script src="/_nuxt/pages/index.4ee7ce6db4f1f6ace22f.hot-update.js" defer=""></script>
<script src="/_nuxt/commons/app.js" defer=""></script>
<script src="/_nuxt/vendors/app.js" defer=""></script>
<script src="/_nuxt/app.js" defer=""></script>
</body>
</html>

----再举例子验证-----
<template>
<div class="container">
<span @click="goList">我是详情,点我跳转列表</span>
</div>
</template>
<script>
export default {
methods: {
goList() {
this.$router.push("/");
},
},
mounted(){ // 客户端执行
console.log('mounted');
},
created(){ // 客户端和服务端执行
console.log('created');
},
asyncData(){ // 服务端执行
console.log('asyncData');
}
};
</script>
服务端会打印

浏览器也会打印

nuxtjs路由-入门
和传统的建立路由配置不同,nuxtjs更像小程序和原生html跳转。免路由配置
会依据 pages 目录结构自动生成 vue-router 模块的路由配置。
pages/
--| index.vue
--| detal.vue
index.vue
<template>
<div class="container">
<nuxt-link to="/detail">我是列表,点我跳转详情</nuxt-link>
</div>
</template>
<script>
export default {}
</script>
<style>
.container {
margin: 0 auto;
padding: 10px;
}
</style>
detail.vue
<template>
<div class="container">
<span @click="goList">我是详情,点我跳转列表</span>
</div>
</template>
<script>
export default {
methods: {
goList() {
this.$router.push("/");
},
},
};
</script>
<style>
.container {
margin: 0 auto;
padding: 10px;
}
</style>

nuxtjs视图
Nuxt.js 应用中为指定的路由配置数据和视图,包括应用模板、页面、布局和 HTML 头部等内容。
其他可以参考文档,这里主要演示一个对于seo比较重要的头部信息description、keywords
<template>
<div class="container">
<nuxt-link to="/detail">我是列表,点我跳转详情</nuxt-link>
</div>
</template>
<script>
export default {
head: {
title: "文章列表",
meta: [
{ charset: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{
name: "description",
content: "这是一个神奇的网站",
},
{
name: "keywords",
content: "神奇,网站",
},
],
link: [
{
rel: "stylesheet",
href: "https://fonts.googleapis.com/css?family=Roboto",
},
],
},
};
</script>
<style>
.container {
margin: 0 auto;
padding: 10px;
}
</style>
编译后代码,可以看到vue-ssr处理后html,已经通过header属性为html加上了标签
<!DOCTYPE html>
<html data-n-head-ssr="" lang="en" data-n-head="%7B%22lang%22:%7B%22ssr%22:%22en%22%7D%7D">
<head>
<title>文章列表</title>
<meta data-n-head="ssr" charset="utf-8" />
<meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1" />
<meta data-n-head="ssr" data-hid="description" name="description" content="" />
<meta data-n-head="ssr" charset="utf-8" />
<meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1" />
<meta data-n-head="ssr" name="description" content="这是一个神奇的网站" />
<meta data-n-head="ssr" name="keywords" content="神奇,网站" />
<link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico" />
<link data-n-head="ssr" rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto" />
<link rel="preload" href="/_nuxt/runtime.js" as="script" />
<link rel="preload" href="/_nuxt/commons/app.js" as="script" />
<link rel="preload" href="/_nuxt/vendors/app.js" as="script" />
<link rel="preload" href="/_nuxt/app.js" as="script" />
<link rel="preload" href="/_nuxt/pages/index.js" as="script" />
<style data-vue-ssr-id="3191d5ad:0"></style>
...
</head>
<body>
...
</body>
</html>

SSG模式
ssg既对seo友好,也对服务器友好。
由于是开发的时候就是已经生成好了的静态资源,所以不需要服务器实时做处理。
同时也不会在发起请求,因为在编译打包的时候,就会访问后端数据,填充到静态页面中
但是也正因为如此,ssg页面常常会存在数据更新不及时,每次更新数据,都需要再次编译方可更新页面的问题,
所以ssg常用在不常更新数据的页面上,比如about、concat等等
举个例子
<template>
<div class="container">
<fieldset>
<legend>ssr-asyncData数据</legend>
<div v-for="item in teachers" :key="item.id">姓名: {{item.name}}</div>
</fieldset>
<fieldset>
<legend>ssr-data数据</legend>
<div v-for="item in teachers1" :key="item.id">姓名: {{item.name}}</div>
</fieldset>
<fieldset>
<legend>ssr-created</legend>
<div v-for="item in teachers2" :key="item.id">姓名: {{item.name}}</div>
</fieldset>
<fieldset>
<legend>csr-mounted数据</legend>
<div v-for="item in teachers3" :key="item.id">姓名: {{item.name}}</div>
</fieldset>
</div>
</template>
<script>
const getTeachers = ()=> {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
const teachers = [
{id:202101,name:'张老师'},
{id:202102,name:'丁老师'}
];
resolve(teachers);
},2000)
})
}
export default {
head: {
title: "文章列表",
meta: [
{ charset: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{
name: "description",
content: "这是一个神奇的网站",
},
{
name: "keywords",
content: "神奇,网站",
},
],
link: [
{
rel: "stylesheet",
href: "https://fonts.googleapis.com/css?family=Roboto",
},
],
},
data(){ // 会走ssg
return {
teachers1: [
{id:202101,name:'张老师1'},
{ id:202102,name:'丁老师1'}
],
teachers2: [],
teachers3: []
}
},
mounted(){ // 会走csr
this.teachers3 = [
{id:202101,name:'张老师3'},
{id:202102,name:'丁老师3'}
]
},
created(){ // 会走ssg
this.teachers2 = [
{id:202101,name:'张老师2'},
{id:202102,name:'丁老师2'}
]
},
async asyncData({ params }) { // 会走ssg
const teachers = await getTeachers();
return {teachers}
}
};
</script>
<style>
.container {
margin: 0 auto;
padding: 10px;
}
</style>
然后我们运行ssg的命令,生产静态网页
npm run generate
进入dist,启动项目,我用的是http-server
<!DOCTYPE html>
<html data-n-head-ssr="" lang="en" data-n-head="%7B%22lang%22:%7B%22ssr%22:%22en%22%7D%7D">
<head>
<title>文章列表</title>
<meta data-n-head="ssr" charset="utf-8" />
<meta data-n-head="ssr" name="viewport" content="width=device-width,initial-scale=1" />
<meta data-n-head="ssr" data-hid="description" name="description" content="" />
<meta data-n-head="ssr" charset="utf-8" />
<meta data-n-head="ssr" name="viewport" content="width=device-width,initial-scale=1" />
<meta data-n-head="ssr" name="description" content="这是一个神奇的网站" />
<meta data-n-head="ssr" name="keywords" content="神奇,网站" />
<link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico" />
<link data-n-head="ssr" rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto" />
<link rel="preload" href="/_nuxt/e4e7482.js" as="script" />
<link rel="preload" href="/_nuxt/2a8f614.js" as="script" />
<link rel="preload" href="/_nuxt/699e2f6.js" as="script" />
<link rel="preload" href="/_nuxt/34083f3.js" as="script" />
<style data-vue-ssr-id="7e56e4e3:0 56b15182:0 1b7833da:0">.nuxt-progress{position:fixed;top:0;left:0;right:0;height:2px;width:0;opacity:1;transition:width .1s,opacity .4s;background-color:#000;z-index:999999}.nuxt-progress.nuxt-progress-notransition{transition:none}.nuxt-progress-failed{background-color:red}html{font-family:"Source Sans Pro",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:16px;word-spacing:1px;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;box-sizing:border-box}*,:after,:before{box-sizing:border-box;margin:0}.button--green{display:inline-block;border-radius:4px;border:1px solid #3b8070;color:#3b8070;text-decoration:none;padding:10px 30px}.button--green:hover{color:#fff;background-color:#3b8070}.button--grey{display:inline-block;border-radius:4px;border:1px solid #35495e;color:#35495e;text-decoration:none;padding:10px 30px;margin-left:15px}.button--grey:hover{color:#fff;background-color:#35495e}.container{margin:0 auto;padding:10px}</style>
</head>
<body>
<div data-server-rendered="true" id="__nuxt">
<!---->
<div id="__layout">
<div>
<div class="container">
<fieldset>
<legend>ssr-asyncData数据</legend>
<div>
姓名: 张老师
</div>
<div>
姓名: 丁老师
</div>
</fieldset>
<fieldset>
<legend>ssr-data数据</legend>
<div>
姓名: 张老师1
</div>
<div>
姓名: 丁老师1
</div>
</fieldset>
<fieldset>
<legend>ssr-created</legend>
<div>
姓名: 张老师2
</div>
<div>
姓名: 丁老师2
</div>
</fieldset>
<fieldset>
<legend>csr-mounted数据</legend>
</fieldset>
</div>
</div>
</div>
</div>
<script>window.__NUXT__=function(e){return{layout:"default",data:[{teachers:[{id:202101,name:"张老师"},{id:202102,name:"丁老师"}]}],fetch:{},error:e,serverRendered:!0,routePath:"/",config:{app:{basePath:"/",assetsPath:"/_nuxt/",cdnURL:e}}}}(null)</script>
<script src="/_nuxt/e4e7482.js" defer=""></script>
<script src="/_nuxt/34083f3.js" defer=""></script>
<script src="/_nuxt/2a8f614.js" defer=""></script>
<script src="/_nuxt/699e2f6.js" defer=""></script>
</body>
</html>
可以看到 ssg和ssr一样,也只会在data、created、asyncDate执行,唯一的和ssr的区别是,服务器不在实时参与渲染。即nuxtJs的执行时机是在这些属性和方法中
关于部署
ssg和csr是一样的,比较简单。编译后 直接拖到服务器容器上就行
ssr则较为麻烦,ssr以来后端node进程(npm start) 最好用pm2管理 不会独占进程
vue的seo的更多相关文章
- Springboot+thymeleaf结合Vue,通过thymeleaf给vue赋值解决Vue的SEO问题
前言 vue开发的项目有时候会有SEO的需求,由于vue是JavaScript框架,内容都在JavaScript和服务端,所以SEO效果很差.vue的服务端渲染又很难和现在成熟的springboot等 ...
- Vue项目SEO优化的另一种姿态
背景:当前项目首页和登陆后的平台在一个项目里,路由采用hash模式,现在要做SEO优化,这时候同构SSR(Server Side Rendering)服务端渲染代价显然太大,影响范围比较广,同样更改当 ...
- Vue的SEO问题汇总
方式一 思否 https://segmentfault.com/q/1010000011824706 SSR 和 Nuxt.js : https://zh.nuxtjs.org/ https://se ...
- VUE的Seo优化 如何实现
今天看到这样一个问题,在vue中,如何进行seo优化呢? 大家应该都知道,seo优化主要是做搜索引擎的排名,但是ajax异步又不支持seo,同时对于url #/的写法,搜索引擎也没办法爬取网站内其他路 ...
- 浅谈vue对seo的影响
不可否定的是,vue现在火.但是在实际项目中,特别是像一下交互网站,我们不可避免会考虑到的是seo问题,这直接关系到我们网站的排名,很多人说用vue搭建的网站不能做优化,那我们真的要放弃vue,放弃前 ...
- vue的seo问题?
seo关系到网站排名, vue搭建spa做前后端分离不好做seo, 可通过其他方法解决: SSR服务端渲染: 将同一个组件渲染为服务器端的 HTML 字符串.利于seo且更快. vue-meta-in ...
- vue的seo方案 prerender-seo-plugin
利用vue cli 3.0安装脚手架.记住:勾选vue-router. 在vue.config.js里添加配置: 2, var path = require('path') 3, const Prer ...
- 用prerender-spa-plugin插件Vue项目优化SEO做ssr服务端渲染及预渲染
今天在做公交的时候没干,用手机看看文章,偶然发现了一个关于Vue优化seo的文章,我先是在Vue的官方文档看了一篇关于Vue做SEO优化的文章. 上面提到了nuxt.js这个框架,这个框架我做过一个小 ...
- vue seo
最近在实习,刚来没几天,老大没安排什么大事给我,昨天下午说给我一个小任务,要求如下: 1.收集几个流量大的网站(必须是vue做的)页面交互和逻辑尽可能复杂多样2.对比一下各个页面的seo是如何做的3. ...
- 83.基于Vue SEO的四种方案(小结)
前言:众所周知,Vue SPA单页面应用对SEO不友好,当然也有相应的解决方案,下面列出几种最近研究和使用过的SEO方案,SRR和静态化基于Nuxt来说. 1.SSR服务器渲染:2.静态化:3.预渲染 ...
随机推荐
- 重生之我是操作系统(十)----I/O管理
简介 操作系统的I/O管理(input/output mannagment)是协调,控制计算机与外部设备(如磁盘,键盘,网络接口)等之间数据交换的核心功能.实现可靠高效且统一(隐藏设备差异,如磁盘.串 ...
- 通过PHP实现获取访问用户IP
在php中自带了一个非常的简单的获取IP地址的全局变量,很多初学都获取IP都使用它了,但是对于这些我们一般用法是满足了,但是对于要求高精度这个函数还是不行的. 这个是最简单的方法,对于开了透明代理之类 ...
- sqlalchemy多对多关联
sqlalchemy_many_to_many.py #!-*-coding:utf-8-*-from sqlalchemy import Table,Column,Integer,String,DA ...
- JS 构造函数与类
严格来说, JS 并不是一个面向对象的语言, 类似 Java, Python, C++ 这样的. JS 的独特精妙的设计其实是 原型 prototype 因此这里讲一嘴面向对象其实是为了后面引出原型的 ...
- 《OKR》| 聚焦小目标, 成就大梦想
今天想和大家分享的书籍是 <每个人的 OKR>. 恰好我司也是采用 OKR 结合 KPI 的方式进行目标和绩效管理, 在实践中通过放大目标的功能, 缩小行动的自由, 聚焦在单一方向的机制, ...
- SQL 强化练习 (十二)
还是 sql 冲鸭... , 停不下来了都, 趁着激情还在, 赶紧再整一把, 也渐渐发现, sql 果然是非常强大的, 然后搞了半天, 发现在写sql 的时候, 从它执行顺序来思考, 这样反而会轻松很 ...
- GStreamer开发笔记(四):ubuntu搭建GStreamer基础开发环境以及基础Demo
前言 本篇开始gstreamer的编程学习,先搭建基础的环境,跑通一个基础的Demo对GStreamer编程有个初步的了解. Demo GStreamer GStreame ...
- WPF 的 await Application.Current.Dispatcher.InvokeAsync,Func 如果是Task , 等待赋值可能存在没有等待执行完成的问题
最近在检查我们组内的代码,发现好多用到 await Application.Current.Dispatcher.InvokeAsync 相信好多WPF的开发都会用到 该方法做UI线程切换.但是细看里 ...
- SpringSecurity配置 1
spring security整合步骤 过滤器链 SpringSecurity的本质就是一个过滤器链,内部包含了提供各种功能的过滤器,基本案例中的过滤器链如下图所示: UsernamePassword ...
- Spring注解之@PropertySource注解加载配置文件的属性
注解@Value和@ConfigurationProperties可以用于获取配置文件的属性值,不过有个细节容易被忽略,那就是二者在Spring Boot项目中都是获取默认配置文件的属性值,也就是 ...