去了一家公司面试,问了半天技术,答基础不错(因为我没有工作经验).回复说我司非常依赖 SSR,对 SEO 要求很高,搜索引擎排名必须第一,要求我必须尽快做出一份 demo 出来满足他们的最低要求.那么问题来了,我对 SSR 基本只是一知半解,怎么用完全属于白板啊.当时周五,那么只剩周六日两天了,也就是说,两天从不知 SSR 为何物到搞出一个 demo.压力好大.回去路上就开始上网查文档.我一看,这是啥,这又是啥.完全不知所云啊.
//创建渲染器 functioncreateRenderer(bundle, options) { // 调用vue-server-renderer的createBundleRenderer方法创建渲染器, //并设置HTML模板,以后后续将服务端预取的数据填充至模板中 returncreateBundleRenderer( bundle, Object.assign(options, { // for component caching //设置一个缓存 cache: LRU({ max: 1000, maxAge: 1000 * 60 * 15, }), // this is only needed when vue-server-renderer is npm-linked basedir: resolve("./dist"), // recommended for performance runInNewContext: false, }) ); }
let renderer; let readyPromise; //模板路径 const templatePath = resolve("./src/index.template.html"); if (isProd) { //生产环境: //webpack结合vue-ssr-webpack-plugin插件生成的server bundle //服务端渲染的HTML模板 const template = fs.readFileSync(templatePath, "utf-8"); //生产环境的时候这里已经打包好了这个json文件可以直接调用 const bundle = require("./dist/vue-ssr-server-bundle.json");
//client manifests是可选项,允许渲染器自动预加载,渲染添加<script>标签
// The client manifests are optional, but it allows the renderer // to automatically infer preload/prefetch links and directly add <script> // tags for any async chunks used during render, avoiding waterfall requests. const clientManifest = require("./dist/vue-ssr-client-manifest.json"); //vue-server-renderer创建bundle渲染器并绑定server bundle renderer = createRenderer(bundle, { template, clientManifest, }); } else { // 开发环境下,使用dev-server来通过回调把生成在内存中的bundle文件传回 // 通过dev server的webpack-dev-middleware和webpack-hot-middleware实现客户端代码的热更新 //以及通过webpack的watch功能实现服务端代码的热更新
// In development: setup the dev server with watch and hot-reload, // and create a new renderer on bundle / index template update. readyPromise = require("./build/setup-dev-server")( app, templatePath, (bundle, options) => { // 基于热更新,回调生成最新的bundle渲染器 renderer = createRenderer(bundle, options); } ); }
// since this app has no user-specific content, every page is micro-cacheable. // if your app involves user-specific content, you need to implement custom // logic to determine whether a request is cacheable based on its url and // headers. // 1-second microcache. // https://www.nginx.com/blog/benefits-of-microcaching-nginx/
// read template from disk and watch template = fs.readFileSync(templatePath, "utf-8"); chokidar.watch(templatePath).on("change", () => { template = fs.readFileSync(templatePath, "utf-8"); console.log("index.html template updated."); update(); });
//客户端热加载服务 // modify client config to work with hot middleware clientConfig.entry.app = [ "webpack-hot-middleware/client", clientConfig.entry.app, ]; clientConfig.output.filename = "[name].js"; clientConfig.plugins.push( new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin() );