webpack 开发环境可以使用proxyTable 来代理跨域,生产环境的话可以根据各自的服务器进行配置代理跨域就行了。在我们的项目config/index.js 文件下可以看到有一个proxyTable的属性,我们对其简单的改写
proxyTable: { '/api': { target: 'http://api.douban.com/v2', changeOrigin: true, pathRewrite: { '^/api': '' } } }
这样当我们访问
localhost:8080/api/movie
的时候 其实我们访问的是
这样便达到了一种跨域请求的方案。
至此,浏览器端的主要配置已经介绍完了,下面我们来看看运行的结果:
为了介绍浏览器渲染是怎么回事,我们运行一下npm run build 看看我们的发布版本的文件,到底是什么鬼东西....
run build 后会都出一个dist目录 ,我们可以看到里面有个index.html,这个便是我们最终页面将要展示的html,我们打开,可以看到下面:
观察好的小伙伴可以发现,我们并没有多余的dom元素,就只有一个div,那么页面要怎么呈现呢?答案是js append,对,下面的那些js会负责innerHTML。而js是由浏览器解释执行的,所以呢,我们称之为浏览器渲染,这有几个致命的缺点:
js放在dom结尾,如果js文件过大,那么必然造成页面阻塞。用户体验明显不好(这也是我我在公司反复被产品逼问的事情)
不利于SEO
客户端运行在老的JavaScript引擎上
对于世界上的一些地区人,可能只能用1998年产的电脑访问互联网的方式使用计算机。而Vue只能运行在IE9以上的浏览器,你可能也想为那些老式浏览器提供基础内容 - 或者是在命令行中使用 Lynx的时髦的黑客
基于以上的一些问题,服务端渲染呼之欲出....
二、服务器端渲染豆瓣电影
先看一张Vue官网的服务端渲染示意图
从图上可以看出,ssr 有两个入口文件,client.js 和 server.js, 都包含了应用代码,webpack 通过两个入口文件分别打包成给服务端用的 server bundle 和给客户端用的 client bundle. 当服务器接收到了来自客户端的请求之后,会创建一个渲染器 bundleRenderer,这个 bundleRenderer 会读取上面生成的 server bundle 文件,并且执行它的代码, 然后发送一个生成好的 html 到浏览器,等到客户端加载了 client bundle 之后,会和服务端生成的DOM 进行 Hydration(判断这个DOM 和自己即将生成的DOM 是否相同,如果相同就将客户端的vue实例挂载到这个DOM上, 否则会提示警告)。
具体实现:
我们需要vuex,需要router,需要服务器,需要服务缓存,需要代理跨域....不急我们慢慢来。
1.建立nodejs服务
首先我们需要一个服务器,那么对于nodejs,express是很好地选择。我们来建立一个server.js
const port = process.env.PORT || 8080 app.listen(port, () => { console.log(`server started at localhost:${port}`) })
这里用来启动服务监听 8080 端口。
然后我们开始处理所有的get请求,当请求页面的时候,我们需要渲染页面
app.get('*', (req, res) => { if (!renderer) { return res.end('waiting for compilation... refresh in a moment.') } const s = Date.now() res.setHeader("Content-Type", "text/html") res.setHeader("Server", serverInfo) const errorHandler = err => { if (err && err.code === 404) { res.status(404).end('404 | Page Not Found') } else { // Render Error Page or Redirect res.status(500).end('500 | Internal Server Error') console.error(`error during render : ${req.url}`) console.error(err) } } renderer.renderToStream({ url: req.url }) .on('error', errorHandler) .on('end', () => console.log(`whole request: ${Date.now() - s}ms`)) .pipe(res) })
然后我们需要代理请求,这样才能进行跨域,我们引入http-proxy-middleware模块:
const proxy = require('http-proxy-middleware');//引入代理中间件 /** * proxy middleware options * 代理跨域配置 * @type {{target: string, changeOrigin: boolean, pathRewrite: {^/api: string}}} */ var options = { target: 'http://api.douban.com/v2', // target host changeOrigin: true, // needed for virtual hosted sites pathRewrite: { '^/api': '' } }; var exampleProxy = proxy(options); app.use('/api', exampleProxy);
这样我们的服务端server.js便配置完成。接下来 我们需要配置服务端入口文件,还有客户端入口文件,首先来配置一下客户端文件,新建src/entry-client.js