进阶 Vue 2x + Webpack 3x + Nodejs 多页面项目框架(下

  不过,文档写得并不详细,也没看到文档对应的代码在哪里;而例子呢,下载后无法运行(2017年12月上旬),也是有点麻烦。

  •Nodejs运行vue组件输出html片段:这一步,可以理解为虚拟dom运行在Nodejs环境,换算出html的字符串,很好理解。

  •Nodejs把html片段拼接到整个HTML上:这里跟客户端版本略有不同,上一篇文章中,我们针对多页面生成了多个html,而这里因为有了Nodejs的动态输出能力,就没必要生成多个html了,只需要每次把动态部分拼接到模版html上即可。

  •对HTML注入数据:上一步有了HTML,但这个html只是死的字符串,到了浏览器解析后只能是普通的dom,无法启动vue还原为虚拟dom。那么就需要原始的数据,好让客户端重建对应的虚拟dom。

  •浏览器运行vue重建虚拟dom:这一步跟之前纯前端的vue架构类似,不同的是,vue会识别到div已经是服务器渲染好的,并不需要重新渲染dom结构,只需要重建虚拟dom,备好数据,绑定事件即可。

  那么从已有的多页面Vue框架出发,要做成多页面nodejs直出,我们需要解决几个问题。

  从之前的纯浏览器运行建模+渲染,到现在拆分两个过程:Nodejs输出结构、浏览器端重建虚拟dom和绑定事件,这里必然需要修改已有的webpack打包配置。

  这个组件分为client-plugin和server-plugin,分别用于客户端和Nodejs部分的打包。针对这个情况,我们需要把webpack文件修改一下,把基础部分抽离出来,把多余部分去除(例如生成html的HtmlWebpackPlugin)。

  跟webpack-simple原型项目的配置没什么差异。主要是去掉了entry的配置,因为针对nodejs和客户端将有新的入口文件。

  原来客户端渲染是直接new Vue(),而这里改为export一个工厂方法,好让后续服务器和客户端分别用各自的方式创建。这里有个题外话,import css不能写在这了,会导致nodejs运行时缺少document对象而报错,需要写到vue文件中。

  就是简单创建Vue实例,然后返回。这个函数接受context参数,是vue-server-renderer传入的,往context中塞数据,可以作用于最终生成的HTML,例如注入数据,这个稍后再说明。

  跟服务器的略有不同,这个是针对浏览器运行的代码,创建Vue实例后,就手工挂载到已存在的节点#app上。

  2、创建render函数,接受req和res(例如用于express),使用renderToString方法,简单把整个网页拼装好返回。其中context是作用于模版html的参数对象,用法跟普通的模版引擎类似。

  vue-server-renderer会自动向模版填充js和css的外链。这个是默认的行为,如果想要把各种js和css做特殊处理,或输出更多内容,可以参考手工注入:

  跟上一篇文章完成的架构不一样,这里不通过webpack-dev-server启动,所以没有热更新的功能。对于实际开发而言,每次修改都要build再run,肯定太麻烦。

  我们自己主要需要修改server.js,判断是否开发环境。如果是,则使用dev-server特殊的renderer。

  到这里,我们实现了一个没有动态数据的SSR版本,方便初学者对整个概念的理解。

  接下来,我们在已有基础上,再实现动态数据。这里列出我认为比较简单易懂的两种方式和相应例子,可能实现的方式有更多。

  先考虑没有Vuex的情况,只是简单粗暴的组件式从上往下传递数据。这个情况适合一些简单页面,纯粹的展示信息和几个简单的点击处理。

  vue的写法从原来固定data,改为从父节点传入的props标签(appData)获取数据。

  最后在client的代码中,拿到这个全局对象,并赋值给Vue。。。完成。。。

  这里建了一个例子,模拟初始化时获取数据,然后再返回给Server去渲染。

  上述代码使用了page2Data别名,利用webpack的alias功能,可以快速实现一份代码,同时对接浏览器和服务器不同的数据获取方式。这也许就是“同构”的一种思路吧,有利于客户端做一些刷新逻辑时,不需要整个页面重载。

  初始化时,调用store的方法,获得数据后再返回渲染。跟不用Vuex类似,数据也是塞到context.state中。

  上边提到的例子都只针对一个页面,因为webpack后,生成的vue-ssr-client-manifest.json等都只有一份。我们需要做一些优化。

  既然是多页面Nodejs,那肯定需要一个路由表。我们可以在路由表中配置访问url(express正则)和代码目录。

  然后根据每个页面,动态生成相应的webpack配置,用于build和dev-server。

  filename这个字段官方文档是没有的,不过,node_modules基本都能找到源码,可以发现有这个动态设置的办法。

  通过上述配置,让浏览器使用的js和服务器打包后的json文件分开,便于设置访问权限,防止服务器信息泄漏。

  server是express实例,设置路由时,创建闭包,每个处理器都能带上对应的pageKey,从而访问对应的renderer。

  至此,一个多页面VueSSR就完成了,后续可以根据项目的具体情况添加实际的Vue组件和插件。

相关阅读