当我第一接触nuxt的时候,真的被惊艳到了,它把vue的生态(vue、vue-router、vuex、vue-meta、vue-server-renderer)用非常好的方式封装起来,免去一系列繁琐的webpack、nodejs服务端配置,把搭建成本降低到很低很低。比vue-cli的webpack模板少了很多配置文件,最重要的nuxt支持ssr!
我的第一个用到vue server-rendered是通过vue-hackernews改造过来的。相比之下,nuxt为我们多考虑了一些东西:
集成vue-meta,又可以少写一些配置性质的代码了,当初可是在
renderToString
里堆了好些逻辑。页面过渡添加loading、页面布局layout(包括错误页面)
与后端的无缝接入,通过暴露req使首屏逻辑更加简单
例如关于前后端用户身份的鉴权问题,处理起来非常方便:
store/actions.js
1
2
3
4
5nuxtServerInit({ commit }, { req }) {
if (req.user) {
commit('SET_USER', req.user)
}
}middleware/ssr-cookie.js
1
2
3
4
5
6
7import axios from '~plugins/axios'
export default function ({ isServer, req }) {
if (isServer) {
axios.defaults.headers.common.cookie = req.headers.cookie
}
}
但是在使用过程中仍然遇到了不少坑,毕竟nuxt的版本才到1.0.0-alpha.4,除了本身因素,还有依赖、依赖的集成,或者本身没有考虑这种情况而导致各种各样的问题,这里我稍微讲一下我所遇到的比较严重的问题。
router切换后的锚定位
我们都知道,vue-router中router切换是可以定义滚动行动,包括锚定位
1 | const router = new Router({ |
vue-router通过scrollBehavior返回的selector进行锚定位,譬如this.$router.push('/article/xxx#content')
定位到id为content的HTMLElement,但是,后来我发现,如果router切换有transition的情况下,锚定位无效!
具体请看 Handle scrollBehaviour with transitions
router 自定义path问题
nuxt有一套自己的路由加载规则,例如
1 | pages/ |
将会自己生成:
1 | router: { |
也就是说,想自定义route.path的话,就比较麻烦了……
目前的解决办法是:
nuxt.config.js
1 | module.exports = { |
这样就显得有点僵硬了……
nuxt.render
nuxt可以通过render函数可以作为node server的一个中间件(middleware),例如它可以配合express作为前端的一个中间件:
1 | const app = express() |
现在看起来好像没有毛病,真的。但是————
有没有看到nuxt.render的上一层有个session中间件!nuxt.render可是包含前端的静态资源文件的响应,也就是你就算访问一个js文件也会走session这个中间件!!!想一想如果你的session中间件使用了其他持久化方式(例如RedisStore、MongoStore),那表示你访问一个js文件也会因为session消耗额外的开销,这后果不敢想像,而且ssr生成的页面包含了大量的prefetch……但愿你的服务器能撑下去。
目前我的解决方法是添加额外的过滤来跳过这些用不上的中间件
1 | const router = express.Router() |
如果还有更好的方式请告诉我
大量link prefetch
nuxt使用了prefetch来预取下一页的资源文件,你知道这意味着什么吗?仔细想一想,如果你整个项目包含了很多个页面的时候,是酱紫的:
1 | <link rel="prefetch" href="/_nuxt/0.nuxt.bundle.dace679158194ffdf6c6.js" as="script"> |
那就意味着当你打开一个页面,load了一大堆用不上的js,此时你的心情是崩溃的。
于是我翻看官方文档,尝试了以下方法:
nuxt.config.js
1
2
3performance: {
prefetch: false
}
不管用!
1 | build:{ |
不管用!
1 | render: { |
不管用!
后来看到几天前的一个commit add render.resourceHints option,意思是可以通过这种方式解决:
1 | render: { |
最后,nuxt虽然现在还有不少坑,但我觉得还是值得去尝试的,而且我已经开始用于生产环境,希望nuxt能继续完善,这样我就无憾了。