从零开始构建react应用(五)同构之服务端渲染
前言上文讲到使用react进行客户端渲染页面,这次讲解在服务端利用前端react的代码来渲染页面并输出到客户端,即构建同构应用。
利用ts实现纯脚本组件的同构当我们的组件不包含样式,图片等服务端无法直接解析处理的时候,我们可以直接利用ts的tsc命令将组件编译成相应的js,服务端则可以直接运行该js得到渲染的结果,当然这种情况实际并不存在,这里只是作为例子来讲解。 服务端bundle.tsx我们在server目录下新建bundle.tsx将其作为前端react组件的一个打包入口文件。我们通过将它打包,并在服务端执行得到我们需要的渲染结果。 // ./src/server/bundle.tsx import * as React from 'react'; /* tslint:disable-next-line no-submodule-imports */ import { renderToString } from 'react-dom/server'; import App from '../client/component/app'; export default { render() { return renderToString(<App />); },}; 可以看到,我们直接将客户端的App组件引入,并输出一个拥有render方法的对象,在服务端入口文件中我们只需要引入该bundle对象,并调用其render方法就可以得到渲染出的html字符串了。
// ./src/server/index.tsx ... router.get('/*',(ctx: Koa.Context,next) => { // 配置一个简单的get通配路由 const html = bundle.render(); // 获得渲染出的html字符串 ctx.type = 'html'; ctx.body = ` ... <div id="app">${html}</div> ... `; next(); }); ...
客户端/服务端渲染对比在chrome中打开 客户端渲染: 服务端渲染: 显而易见,服务端渲染会直接输出组件渲染的内容,浏览器在接收到这些内容后就会直接绘制呈现给我们,而客户端渲染会在react框架初始化完毕之后再进行,所以对比两种情况,客户端渲染时白屏时间会更长一些,且刷新页面时会有闪烁的感觉。 利用webpack实现非纯脚本组件的同构在我们实际开发环境中,必然存在组件里引用样式文件,引用图片的情况,这种情况下ts并不具备webpack相应的将这些资源转换为js可处理的功能,所以我们需要使用webpack来处理服务端的bundle.tsx文件,使得服务端可以运行打包后的js文件。 服务端bundle.tsx的webpack配置文件在客户端,像react这样的库,webpack会把它打包到输出的js文件里,而在服务端我们并不需要这么做,所以配置文件和客户端有很大不同。 // ./src/webpack/server.ts import * as path from 'path'; import * as webpack from 'webpack'; import * as nodeExternals from 'webpack-node-externals'; import { cloneDeep } from 'lodash'; // lodash提供的深度复制方法cloneDeep // 客户端+服务端全环境公共配置baseConfig,项目根目录路径baseDir,获取tsRule的方法getTsRule import baseConfig,{ baseDir,getTsRule } from './base'; const serverBaseConfig: webpack.Configuration = cloneDeep(baseConfig); // 服务端全环境公共配置 serverBaseConfig.entry = { // 入口属性配置 'server-bundle': [ './src/server/bundle.tsx',],}; serverBaseConfig.externals = [nodeExternals()],serverBaseConfig.node = { __dirname: true,__filename: true,}; serverBaseConfig.target = 'node'; serverBaseConfig.output.libraryTarget = 'commonjs2'; const serverDevConfig: webpack.Configuration = cloneDeep(serverBaseConfig); // 服务端开发环境配置 serverDevConfig.cache = false; // 禁用缓存 serverDevConfig.output.filename = '[name].js'; // 使用源文件名作为打包后文件名 (serverDevConfig.module as webpack.NewModule).rules.push( getTsRule('./src/webpack/tsconfig.server.json'),); serverDevConfig.plugins.push( new webpack.NoEmitOnErrorsPlugin(),// 编译出错时跳过输出阶段,以保证输出的资源不包含错误。 ); const serverProdConfig: webpack.Configuration = cloneDeep(serverBaseConfig); // 服务端生产环境配置 // TODO 服务端生产环境配置暂不处理和使用 export default { development: serverDevConfig,production: serverProdConfig,};
|
- ruby-on-rails – Capybara Rspec测试可能对AJAX失败 – 测
- ruby-on-rails – Rails 4 ActionMailer with gmail Net ::
- c# – 使用ErrorProvider和验证事件进行表单验证
- c# – 如何为dev / stage / production维护单独的web服务
- ruby-on-rails – Rails ActiveRecord :: StatementInvalid
- It is a great start
- 深入入门正则表达式(java) - 2 - 基本实例
- c# – 使用实体框架,首选方式?
- c# – 如何修复嵌套winform控件闪烁问题
- Codeforces 1228C. Primes and Multiplication