加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

Vue服务端渲染实践 ——Web应用首屏耗时最优化方案

发布时间:2019-03-24 14:45:38 所属栏目:优化 来源:counterxing
导读:副标题#e# 随着各大前端框架的诞生和演变,SPA开始流行,单页面应用的优势在于可以不重新加载整个页面的情况下,通过ajax和服务器通信,实现整个Web应用拒不更新,带来了极致的用户体验。然而,对于需要SEO、追求极致的首屏性能的应用,前端渲染的SPA是糟糕

为了简化这些,你可以直接在创建renderer时提供一个页面模板。多数时候,我们会将页面模板放在特有的文件中:

  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3.   <head><title>Hello</title></head>  
  4.   <body>  
  5.     <!--vue-ssr-outlet-->  
  6.   </body>  
  7. </html> 

然后,我们可以读取和传输文件到Vue renderer中:

  1. const tpl = fs.readFileSync(path.resolve(__dirname, './index.html'), 'utf-8');  
  2. const renderer = vssr.createRenderer({  
  3.     template: tpl,  
  4. }); 

Webpack配置

然而在实际项目中,不止上述例子那么简单,需要考虑很多方面:路由、数据预取、组件化、全局状态等,所以服务端渲染不是只用一个简单的模板,然后加上使用vue-server-renderer完成的,如下面的示意图所示:

Vue服务端渲染实践 ——Web应用首屏耗时最优化方案

如示意图所示,一般的Vue服务端渲染项目,有两个项目入口文件,分别为entry-client.js和entry-server.js,一个仅运行在客户端,一个仅运行在服务端,经过Webpack打包后,会生成两个Bundle,服务端的Bundle会用于在服务端使用虚拟DOM生成应用程序的“快照”,客户端的Bundle会在浏览器执行。

因此,我们需要两个Webpack配置,分别命名为webpack.client.config.js和webpack.server.config.js,分别用于生成客户端Bundle与服务端Bundle,分别命名为vue-ssr-client-manifest.json与vue-ssr-server-bundle.json,关于如何配置,Vue官方有相关示例vue-hackernews-2.0

开发环境搭建

我所在的项目使用Koa作为Web Server Frame,项目使用koa-webpack进行开发环境的构建。如果是在产品环境下,会生成vue-ssr-client-manifest.json与vue-ssr-server-bundle.json,包含对应的Bundle,提供客户端和服务端引用,而在开发环境下,一般情况下放在内存中。使用memory-fs模块进行读取。

  1. const fs = require('fs')  
  2. const path = require( 'path' );  
  3. const webpack = require( 'webpack' );  
  4. const koaWpDevMiddleware = require( 'koa-webpack' );  
  5. const MFS = require('memory-fs');  
  6. const appSSR = require('./../../app.ssr.js');  
  7. let wpConfig;  
  8. let clientConfig, serverConfig;  
  9. let wpCompiler;  
  10. let clientCompiler, serverCompiler;  
  11. let clientManifest;  
  12. let bundle;  
  13. // 生成服务端bundle的webpack配置  
  14. if ((fs.existsSync(path.resolve(cwd,'webpack.server.config.js')))) {  
  15.   serverConfig = require(path.resolve(cwd, 'webpack.server.config.js'));  
  16.   serverCompiler = webpack( serverConfig );  
  17. }  
  18. // 生成客户端clientManifest的webpack配置  
  19. if ((fs.existsSync(path.resolve(cwd,'webpack.client.config.js')))) {  
  20.   clientConfig = require(path.resolve(cwd, 'webpack.client.config.js'));  
  21.   clientCompiler = webpack(clientConfig);  
  22. }  
  23. if (serverCompiler && clientCompiler) {  
  24.   let publicPath = clientCompiler.output && clientCompiler.output.publicPath;  
  25.   const koaDevMiddleware = await koaWpDevMiddleware({  
  26.     compiler: clientCompiler,  
  27.     devMiddleware: {  
  28.       publicPath,  
  29.       serverSideRender: true  
  30.     },  
  31.   });  
  32.   app.use(koaDevMiddleware);  
  33.   // 服务端渲染生成clientManifest  
  34.   app.use(async (ctx, next) => {  
  35.     const stats = ctx.state.webpackStats.toJson();  
  36.     const assetsByChunkName = stats.assetsByChunkName;  
  37.     stats.errors.forEach(err => console.error(err));  
  38.     stats.warnings.forEach(err => console.warn(err));  
  39.     if (stats.errors.length) {  
  40.       console.error(stats.errors);  
  41.       return;  
  42.     }  
  43.     // 生成的clientManifest放到appSSR模块,应用程序可以直接读取  
  44.     let fileSystem = koaDevMiddleware.devMiddleware.fileSystem;  
  45.     clientManifest = JSON.parse(fileSystem.readFileSync(path.resolve(cwd,'./dist/vue-ssr-client-manifest.json'), 'utf-8'));  
  46.     appSSR.clientManifest = clientManifest;  
  47.     await next();  
  48.   });  
  49.   // 服务端渲染的server bundle 存储到内存里  
  50.   const mfs = new MFS();  
  51.   serverCompiler.outputFileSystem = mfs;  
  52.   serverCompiler.watch({}, (err, stats) => {  
  53.     if (err) {  
  54.       throw err;  
  55.     }  
  56.     statsstats = stats.toJson();  
  57.     if (stats.errors.length) {  
  58.       console.error(stats.errors);  
  59.       return;  
  60.     }  
  61.     // 生成的bundle放到appSSR模块,应用程序可以直接读取  
  62.     bundle = JSON.parse(mfs.readFileSync(path.resolve(cwd,'./dist/vue-ssr-server-bundle.json'), 'utf-8'));  
  63.     appSSR.bundle = bundle;  
  64.   });  

渲染中间件配置

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读