研究SSR距现在有些年头了了,这里总结我当时踩过的和看到的坑,为同样在研究SSR的小伙伴节省时间成本,最重要的是怕自己忘了。。。
直奔主题
使用服务端渲染常见问题:
过滤CSS和图片文件
1 | // SSR环境对样式文件处理 |
或者使用ignore-loader
1
2
3
4
5
6
7
8
9
10
11
12{
test: /\.css$/,
use: [
'ignore-loader'
]
},
{
test: /\.less$/,
use: [
'ignore-loader'
]
},
客户端展示异常,服务端报错 window/alert/document is undefined
服务端没有
window/alert/document
这种东西,需要自行定义,建议方式引入第三方包jsdom
辅助定义
1 | //https://github.com/vuejs/vue-hackernews-2.0/issues/52#issuecomment-255594303 |
1 | const domino = require('domino'); |
引入Antd后matchMedia问题
1 | Error: matchMedia not present, legacy browsers require a polyfill |
解决办法:1
cnpm i -S jsdom whatwg-encoding matchmedia-polyfill
具体配置如上图片。
router中配置了scrollBehavior
,客户端正常,服务端报错scroll undefined
跟上个问题相同,需要在服务端重声明
1 | //fixed Not-implemented error |
mismatch
使用ssr会有检查服务端渲染出的结构与直接客户端渲染的结构是否相同,不同会报mismatch
。这种问题往往是因为比如table
结构没有tbody
之类的。
自己的一些业务操作也可能会产生两端的结构重复,比如我之前为了动态生成meta
用了mixin,在服务端用$ssrContext
配合操作,客户端则用的document
直接更改对应值,因此会出现一个页面有两个重复的meta
,造成mismatch
,解决方式是在客户端加判断,如果已经有的meta
就使用修改而不是增加
1 | if (meta) { |
区别终端类型
比如在PC端使用a链接作为入口,移动端使用b链接作为入口
客户端:使用navigator.userAgent
做判断,然后
1 | Vue.mixin({ |
服务端: 在server.js
的render
中通过req.headers['user-agent']
然后通过$ssrContext
传递
1 | if(context.agentID !== null && context.url === '/a/') { |
项目不在服务器对应位置的根目录而在二级目录
一般打包都打包到根目录,获取静态文件资源也从/开始,如果不是,怎么办呢?
其实也不难,把各种相关配置更改一下就好了,就是这些位置自己摸索到时候有些麻烦,尤其还是ssr,漏掉就可能造成项目起不来或白屏、报错、刷新404。
我这里列了一下要修改的位置(按文件顺序,假设二级目录名为dev):
build/setup-dev-server.js
中的webpack-hot-middleware
1 | clientConfig.entry.app = ['webpack-hot-middleware/client?path=/dec/__webpack_hmr', clientConfig.entry.app] |
webpack.base.config.js
的output
1 | output: { |
entry-client.js
的service worker
1 | if (process.env.NODE_ENV === 'production' && 'serviceWorker'in navigator) { |
template.html
的href
1 | <linkrel="shortcut icon"href="/dev/assets/images/favicon.ico"> |
server.js
的serve
1 | app.use(favicon('./src/assets/images/favicon.ico')) |
如果是非服务端渲染需要修改config/index.js
中assetsPublicPath
为/dev/