至此,多级路由的渲染就完成啦 。
part7: css的服务端渲染思路(context钩子变量)一、客户端项目中引入CSS还是以Home组件为例
//Home/style.cssbody {background: gray;}复制代码
现在,在Home组件代码中引入:
import styles from './style.css';复制代码
要知道这样的引入CSS代码的方式在一般环境下是运行不起来的,需要在webpack中做相应的配置 。首先安装相应的插件 。
npm install style-loader css-loader --D复制代码
//webpack.client.jsconst path = require('path');const merge = require('webpack-merge');const config = require('./webpack.base');const clientConfig = {mode: 'development',entry: './src/client/index.js',module: {rules: [{test: /.css?$/,use: ['style-loader', {loader: 'css-loader',options: {modules: true}}]}]},output: {filename: 'index.js',path: path.resolve(__dirname, 'public')},}module.exports = merge(config, clientConfig);复制代码
//webpack.base.js代码,回顾一下,配置了ES语法相关的内容module.exports = {module: {rules: [{test: /.js$/,loader: 'babel-loader',exclude: /node_modules/,options: {presets: ['@babel/preset-react',['@babel/preset-env', {targets: {browsers: ['last 2 versions']}}]]}}]}}复制代码
好,现在在客户端CSS已经产生了效果 。
文章插图
可是打开网页源代码:
文章插图
咦?里面并没有出现任何有关CSS样式的代码啊!那这是什么原因呢?很简单,其实我们的服务端的CSS加载还没有做 。接下来我们来完成CSS代码的服务端的处理 。
二、服务端CSS的引入首先,来安装一个webpack的插件,
npm install -D isomorphic-style-loader复制代码
然后再webpack.server.js中做好相应的css配置://webpack.server.jsconst path = require('path');const nodeExternals = require('webpack-node-externals');const merge = require('webpack-merge');const config = require('./webpack.base');const serverConfig = {target: 'node',mode: 'development',entry: './src/server/index.js',externals: [nodeExternals()],module: {rules: [{test: /.css?$/,use: ['isomorphic-style-loader', {loader: 'css-loader',options: {modules: true}}]}]},output: {filename: 'bundle.js',path: path.resolve(__dirname, 'build')}}module.exports = merge(config, serverConfig);复制代码
它做了些什么事情?再看看这行代码:
import styles from './style.css';复制代码
引入css文件时,这个isomorphic-style-loader帮我们在styles中挂了三个函数 。输出styles看看:文章插图
现在我们的目标是拿到CSS代码,直接通过styles._getCss即可获得 。
那我们拿到CSS代码后放到哪里呢?其实react-router-dom中的StaticRouter中已经帮我们准备了一个钩子变量context 。如下
//context从外界传入<StaticRouter location={req.path} context={context}><div>{renderRoutes(routes)}</div></StaticRouter>复制代码
这就意味着在路由配置对象routes中的组件都能在服务端渲染的过程中拿到这个context,而且这个context对于组件来说,就相当于组件中的props.staticContext 。并且,这个props.staticContext只会在服务端渲染的过程中存在,而客户端渲染的时候不会被定义 。这就让我们能够通过这个变量来区分两种渲染环境啦 。现在,我们需要在服务端的render函数执行之前,初始化context变量的值:
let context = { css: [] }复制代码
我们只需要在组件的componentWillMount生命周期中编写相应的逻辑即可:componentWillMount() {//判断是否为服务端渲染环境if (this.props.staticContext) {this.props.staticContext.css.push(styles._getCss())}}复制代码
服务端的renderToString执行完成后,context的CSS现在已经是一个有内容的数组,让我们来获取其中的CSS代码://拼接代码const cssStr = context.css.length ? context.css.join('n') : '';复制代码
现在挂载到页面://放到返回的html字符串里的header里面<style>${cssStr}</style>复制代码
文章插图
网页源代码中看到了CSS代码,效果也没有问题 。CSS渲染完成!
推荐阅读
- 吃什么补血 中医教你补气血
- 教你煮饺子的方法,煮出的饺子更好吃 怎么煮饺子
- 教你怎样调配花草茶,润肤花草茶
- 从草本植物角度科学的认识百合花茶,四大步骤教你如何简易而快速的冲泡百合花茶
- 手把手教你进行pip换源,让你的Python库下载嗖嗖的
- 今日头条如何发文才有收益?新人朋友请看过来,教你一步步操作
- 教你安全配花茶,花茶的感官鉴赏
- 百合花茶搭配,四大步骤教你如何简易而快速的冲泡百合花茶
- 13个护发误区大扫盲,教你掌握正确洗护方法
- 黑苦荞茶什么牌子纯正,四大步骤教你如何简易而快速的冲泡百合花茶