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

2020-06-14 06:25:04易采站长站整理
官方有相关示例vue-hackernews-2.0

开发环境搭建

我所在的项目使用

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


const fs = require('fs')
const path = require( 'path' );
const webpack = require( 'webpack' );
const koaWpDevMiddleware = require( 'koa-webpack' );
const MFS = require('memory-fs');
const appSSR = require('./../../app.ssr.js');

let wpConfig;
let clientConfig, serverConfig;
let wpCompiler;
let clientCompiler, serverCompiler;

let clientManifest;
let bundle;

// 生成服务端bundle的webpack配置
if ((fs.existsSync(path.resolve(cwd,'webpack.server.config.js')))) {
serverConfig = require(path.resolve(cwd, 'webpack.server.config.js'));
serverCompiler = webpack( serverConfig );
}

// 生成客户端clientManifest的webpack配置
if ((fs.existsSync(path.resolve(cwd,'webpack.client.config.js')))) {
clientConfig = require(path.resolve(cwd, 'webpack.client.config.js'));
clientCompiler = webpack(clientConfig);
}

if (serverCompiler && clientCompiler) {
let publicPath = clientCompiler.output && clientCompiler.output.publicPath;

const koaDevMiddleware = await koaWpDevMiddleware({
compiler: clientCompiler,
devMiddleware: {
publicPath,
serverSideRender: true
},
});

app.use(koaDevMiddleware);

// 服务端渲染生成clientManifest

app.use(async (ctx, next) => {
const stats = ctx.state.webpackStats.toJson();
const assetsByChunkName = stats.assetsByChunkName;
stats.errors.forEach(err => console.error(err));
stats.warnings.forEach(err => console.warn(err));
if (stats.errors.length) {
console.error(stats.errors);
return;
}
// 生成的clientManifest放到appSSR模块,应用程序可以直接读取
let fileSystem = koaDevMiddleware.devMiddleware.fileSystem;
clientManifest = JSON.parse(fileSystem.readFileSync(path.resolve(cwd,'./dist/vue-ssr-client-manifest.json'), 'utf-8'));
appSSR.clientManifest = clientManifest;
await next();
});

// 服务端渲染的server bundle 存储到内存里
const mfs = new MFS();
serverCompiler.outputFileSystem = mfs;
serverCompiler.watch({}, (err, stats) => {
if (err) {
throw err;
}