03源码结构
源码结构
避免状态单例
当编写纯客户端client-only 代码时,我们习惯于每次在新的上下文中取值。但node服务器是一个长期运行的进程,当我们的代码进入该进程时,它将进行一次取值并留存在内存中。这意味着如果创建一个单例对象,它将在每个传入的请求之间共享。
如示例,我们为每个请求创建一个新的根Vue实例,这与每个用户在自己的浏览器中使用新应用程序的实例类似。如果我们在多个请求之间使用一个共享的实例,很容易导致交叉请求状态污染(cross-request state pollution)。因此,我们不应该直接创建一个应用程序实例,而是应该暴露一个可以重复执行的工厂函数,为每个请求创建新的应用程序实例:
const Vue = require('vue')
export default function createApp(context) {
return new Vue({
data: {
url: context.url
},
template: `<div>访问的url是: {{url}}</div>`
})
}并将服务器代码变为:
const createApp = require('./app')
server.get('*', (req, res) => {
const context = {url: req.url}
const app = createApp(context)
renderer.renderToString(app, (err, html) => {
// 错误处理
res.end(html)
})
})同样的规则也适用于 router、store 和 event bus 实例。你不应该直接从模块导出并将其导入到应用程序中,而是需要在 createApp 中创建一个新的实例,并从根 Vue 实例注入。
在使用带有 { runInNewContext: true } 的 bundle renderer 时,可以消除此约束,但是由于需要为每个请求创建一个新的 vm 上下文,因此伴随有一些显著性能开销。
介绍构建步骤
到目前为止,我们还没有讨论过如何将相同的 Vue 应用程序提供给客户端。为了做到这一点,我们需要使用 webpack 来打包我们的 Vue 应用程序。事实上,我们可能需要在服务器上使用 webpack 打包 Vue 应用程序,因为:
通常 Vue 应用程序是由 webpack 和 vue-loader 构建,并且许多 webpack 特定功能不能直接在 Node.js 中运行(例如通过 file-loader 导入文件,通过 css-loader 导入 CSS)
尽管 Node.js 最新版本能够完全支持 ES2015 特性,我们还是需要转译客户端代码以适应老版浏览器。这也会涉及到构建步骤
<img src="https://cloud.githubusercontent.com/assets/499550/17607895/786a415a-5fee-11e6-9c11-45a2cfdf085c.png">
