使用Nuxt.js怎么实现一个SSR前端博客
这篇文章将为大家详细讲解有关使用Nuxt.js怎么实现一个SSR前端博客,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
目录结构
assets: 资源文件。用于组织未编译的静态资源如 LESS、SASS或 JavaScript。
components: 组件。
layouts: page: 模板页面,默认为 default.vue可以在这个目录下创建全局页面的统一布局,或是错误处理页面页,需要提供一个nuxt 标签,类似于router-view
middleware: 中间件,放置自定义的中间件,会在加载组件之前调用。可以在页面中调用: middleware: '中间件名称'。
pages: 页面,index.vue 为根页面,Nuxt.js 框架读取该目录下所有的 .vue文件并自动生成对应的路由配置,如需要动态参数id,则可以添加_id的文件,必须是下划线加参数名。
plugin: 插件,用于组织那些需要在 根Vue.js应用实例化之前需要运行的 Javascript 插件。
static: 静态文件,静态文件目录 static用于存放应用的静态文件,此类文件不会被 Nuxt.js 调用 Webpack 进行构建编译处理。
store: 用于组织vuex状态管理。具体使用请移步至 官网。
nuxt.config.js: nuxt.config.js文件用于组织Nuxt.js 应用的个性化配置,配置head,loading,css,plugins等。
Nuxt.js生命周期
1. incoming Request 浏览器发出的请求)2. nuxtServerInit 服务端接受请求后,要检查当前有没有 nuxtServerInit配置项,如果有就执行这个函数3. store action 用来操作vuex4. middleware 可以做jWT等一些操作。5. validate() 检验参数,参数检验失败,可以在layout里的error里面进行捕捉。6. asyncData()& fetch() asyncData用来渲染组件,fetch用来渲染vuex7. Render
Nuxt扩展以后的生命周期和方法以下:
beforeCreate:ƒbeforeCreate() components:{NuxtLoading:{…}} computed:{isOffline:ƒ} context:{isStatic:false,isDev:true,isHMR:true,app:{…},payload:undefined,…} created:ƒcreated() data:ƒdata() head:{title:"nuxt-meituan-ssr",meta:Array(3),link:Array(1),style:Array(0),script:Array(0)} methods:{refreshOnlineStatus:ƒ,refresh:ƒ,errorChanged:ƒ,setLayout:ƒ,loadLayout:ƒ} mounted:ƒmounted() nuxt:{…} render:ƒrender(h,props) router:VueRouter{app:Vue,apps:Array(1),options:{…},beforeHooks:Array(2),resolveHooks:Array(0),…} watch:{nuxt.err:"errorChanged"}
注意:
Vue.js生命周期的钩子只有beforeCreate和created会在服务端和客户端渲染。
以上生命周期里都获取不到window对象。
asyncData和fetch我们可以拿到数据,不要尝试挂载数据到data上,此时获取不到this对象。
开发总结
如何修改默认启动端口?
可以在package.json下面修改配置,如下。
"config":{ "nuxt":{ "host":"127.0.0.1", "port":"3304" } }
如何添加全局的样式?
可以在assets里添加全局Css文件,如在assets下的Css文件夹目录下添加了一个index.css文件,然后在nuxt-config.js里配置该css文件路径即可。 css:['~assers/css/index.css']
通过别名访问图片在template里是正确的,为何在Css设置背景图却报错?
在css配置的是,需要将'~/'后面的'/'去除掉。
backround-image:url('~static/logo.jpg');
如何添加路由动画?
同样,我们在Css文件里添加一些动画代码,一般样式会在其后面添加-active和-leave-active,其实和Vue动画形式一致。其中以page开头的动画,默认会作用于全部页面,如果想给特定的页面加动画,可以在对应的页面script里引用,如 transitions: 'bounce'即可。
.page-enter-active,.page-leave-active{ transition:opacity.3s } .page-enter,.page-leave-active{ opacity:0 } .bounce-enter-active{ animation:bounce-in.8s; } .bounce-leave-active{ animation:bounce-out.5s; } @keyframesbounce-in{ 0%{transform:scale(1)} 50%{transform:scale(1.01)} 100%{transform:scale(1)} } @keyframesbounce-out{ 0%{transform:scale(1)} 50%{transform:scale(1.01)} 100%{transform:scale(1)} }
路由参数如何传递?
同Vue-router,有声明式和编程式两种方式,无非是标签变成了 router.push(...)
nuxt-link:to="{name:'article',params:{id:1234}}">声明式 //编程式 this.$router.push({ name:'article', params:{ id:1234 } })
动态路由如何进行参数检验?
Nuxt.js提供了一个validate的生命周期钩子,可以在此进行参数的校验。以文章详情校验id为例,我们需要判断传入的id是否是数字,可以像下面这样处理。
validate({params}){ return/^\d+$/.test(params.id) }
如何添加404等错误页面?
可以在layout下新建一个error.vue页面,内容如下,当访问一个不存在的页面的时候,或者参数检验失败的时候,或者我们在middleware中间件处理抛出异常的时候,都会跳转到该页面。
页面不存在 应用发生错误异常 首页
middleware中的文件抛出错误
exportdefaultfunction({store,error,redirect}){ if(!store.state.user.userInfo.auth){ error({ message:'没有权限哦!', statusCode:403 }) } }
顶部进度条如何设置?
loading 属性配置 可以在nuxt-config.js设置loading的颜色,使用了this. loading可能无法在created里立即使用。此种配置loading有严重的缺陷,无法知道真正的加载进度。也可以自定义加载组件,loading: '~components/loading.vue'。
exportdefault{ mounted(){ this.$nextTick(()=>{ this.$nuxt.$loading.start() setTimeout(()=>this.$nuxt.$loading.finish(),500) }) } }
异步数据如何获取?
Nuxt.js提供了两个函数,asyncData和fetch函数。asyncData 获取组件的数据,fetch 在渲染页面之前获取数据填充应用的状态树(store)。
asyncData可以使用promise也可以使用async函数,记住,此时返回的东西需要用一个对象进行包裹,不能挂载到data里,此时没有this对象。
//方式一 asyncData({app,params,route,query,error}){ returngetUserlist({}).then(res=>{ letuser=[]; user=res.list console.log(user,'user') return{user} }) .catch(err=>{ console.log(err) }) }, //方式二 asyncasyncData({app}){ letdata=awaitgetUserlist({}); letuser=data.list; return{user} }
fetch函数同上,可以使用promise也可以使用async函数,通常会commit一个mutation。
exportdefault{ fetch({store,params}){ returnaxios.get('http://my-api/stars') .then((res)=>{ store.commit('setStars',res.data) }) } } //或者使用async或await的模式简化代码如下:Stars:{{$store.state.stars}}
如何动态修改title的内容?
如果是写死的,可以直接修改head的配置。
head(){ return{ //title:'',这里一旦声明,在asyncdata里修改也不起作用,直接以这个为准 meta:[ { hid:'description',//nuxt.config替换唯一标识hid{hid:'description',name:'description',content:'Nuxt.jsproject'} name:'content', content:'文章详情' } ] } },
如果是动态数据从数据源里获取,然后通过asynData里的app对象,动态修改head的title。
asyncData({app,params}){ constid=params.id; returngetArticleDetail({id}) .then(result=>{ app.head.title=result.title; }) .catch(err=>{}) }
如何进行权限JWT验证?
登录成功以后,我们会在cookie和Vuex中缓存token信息,当界面刷新的时候,会走store里的nuxtServerInit 函数,该函数仅在每个服务器端渲染中运,可以使用req.headers.cookie获取浏览器的cookie,再次更新store里的值,接着会走到中间件,中间件进行验证,如果有token信息则继续,没有则跳转到登录页。1. 为什么要在nuxtServerInit更新store的值?需要在middleware里使用,否则刷新后store里的值为空了。2. 客户端调用接口可以拿到token,服务器端如何拿到?可以通过nuxtServerInit里的req拿到请求信息的cookie,然后请求接口。3. 前后端分离,刷新的时候如何保证用户名、token等信息依然存在?可以像上面一样,每次取cookie的值再次更新store,但这样有一个问题,cookie可能会被篡改,后端代码需要做验证。也可以每次刷新重新通过token请求接口,更新用户信息。
store代码
importVuefrom'vue'; importVuexfrom'vuex'; importuserfrom'./modules/user'; import{COOKIE_KEY}from'~/assets/js/constant.js'; Vue.use(Vuex); conststore=()=> newVuex.Store({ modules:{ user }, actions:{ asyncnuxtServerInit({commit,dispatch},{req,app}){ if(req.headers.cookie){ letparsedResult={}; req.headers.cookie.split(';').forEach(cookie=>{ constcurrentCookie=cookie.split('='); parsedResult[currentCookie[0].trim()]=(currentCookie[1]||'').trim(); }); constuserInfo={ name:parsedResult[COOKIE_KEY.NAME], token:parsedResult[COOKIE_KEY.TOKEN] }; commit('user/setUserInfo',userInfo); } } } }); exportdefaultstore;
中间件代码
exportdefaultfunction({store,error,redirect}){ if(!store.state.user.userInfo.token||!store.state.user.userInfo.name){ //error({ //message:'Youarenotconnected', //statusCode:403 //}) redirect('/'); } }
nginx部署
npm run build选择build以后的四个文件: .nuxt, static, nuxt.config.js, package.json上传到服务器。pm2 pm2 start npm --name 'package.json.name' -- run startnginx配置
查看网页源代码可以看到:
server{ listen3000; server_namefelix12345.club; gzipon; gzip_buffers324K; gzip_comp_level6; gzip_min_length100; gzip_typesapplication/javascripttext/csstext/xml; gzip_disable"MSIE[1-6]\."; gzip_varyon; proxy_buffer_size64k; proxy_buffers3232k; proxy_busy_buffers_size128k; location/{ root/data/ww/nuxt; proxy_passhttp://127.0.0.1:3002; proxy_set_headerX-Real-IP$remote_addr; } }
关于使用Nuxt.js怎么实现一个SSR前端博客就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
推荐阅读
-
Notepad++ 插件推荐:代码折叠、语法高亮增强工具合集
-
Emacs Evil 模式:Vim 用户快速上手 Emacs 的过渡方案
-
Vim 寄存器深度解析:多缓冲区操作与复杂文本处理
-
Atom 主题切换:Material Design 与扁平化风格对比推荐
-
Lightly IDE 快捷键:Python 开发者必学的效率提升操作
-
Xcode 模拟器调试:多设备同步与性能监控技巧
-
PyCharm 代码格式化:黑魔法工具 Black 与自动规范配置
-
IntelliJ IDEA Docker 集成:微服务本地调试与镜像构建
-
VS Code Remote SSH:远程服务器开发环境搭建全流程
-
Retool 数据库连接:支持 MySQL、PostgreSQL 等多数据源配置
-
Notepad++ 插件推荐:代码折叠、语法高亮增强工具合集
-
Emacs Evil 模式:Vim 用户快速上手 Emacs 的过渡方案
-
Vim 寄存器深度解析:多缓冲区操作与复杂文本处理
-
Atom 主题切换:Material Design 与扁平化风格对比推荐
-
Lightly IDE 快捷键:Python 开发者必学的效率提升操作
-
Xcode 模拟器调试:多设备同步与性能监控技巧
-
PyCharm 代码格式化:黑魔法工具 Black 与自动规范配置
-
IntelliJ IDEA Docker 集成:微服务本地调试与镜像构建
-
VS Code Remote SSH:远程服务器开发环境搭建全流程
-
Retool 数据库连接:支持 MySQL、PostgreSQL 等多数据源配置
-
Notepad++ 插件推荐:代码折叠、语法高亮增强工具合集
-
Emacs Evil 模式:Vim 用户快速上手 Emacs 的过渡方案
-
Vim 寄存器深度解析:多缓冲区操作与复杂文本处理
-
Atom 主题切换:Material Design 与扁平化风格对比推荐
-
Lightly IDE 快捷键:Python 开发者必学的效率提升操作
-
Xcode 模拟器调试:多设备同步与性能监控技巧
-
PyCharm 代码格式化:黑魔法工具 Black 与自动规范配置
-
IntelliJ IDEA Docker 集成:微服务本地调试与镜像构建
-
VS Code Remote SSH:远程服务器开发环境搭建全流程
-
Retool 数据库连接:支持 MySQL、PostgreSQL 等多数据源配置