React SSR 实践过程(二)

1,358 阅读2分钟

前言

前面已经把react ssr环境配置,数据同构,路由同构弄好了,接下来需要对资源进行处理。因为一个项目,不可能只有html js嘛,所以还需要对常用的资源处理一下。

css资源处理

css的写法还是挺多的,我这里就处理两种比较常见的情况:

  • css in js,例子是:styled-components
  • css直接引入

css in js

css in js的方法库还是挺多的,styled-components也挺好用的,如果没用过可以试试。

styled-components

安装依赖

$ npm i styled-components -D

先定义一个Div在组件中使用

import styled from 'styled-components';
const Div = styled.div`
  font-size: 20px;
  color: blue;

  span {
    color: red;
    font-size: 18px;
  }
`;
const Index = (props) => {
  ...
  return (
    <Div>
      page: Fruit
      <span>I am {info.name}</span>
    </Div>
  )
};

在服务端,可以使用styled-components导出的ServerStyleSheet对象,实例化对象后,主要使用两种方法:collectStylesgetStyleTags,顾名思义,就是收集样式和导出样式标签。

import { ServerStyleSheet } from 'styled-components';

export default async (req, res, next) => {
  ...
  const reactStr = renderToString(
    sheet.collectStyles(  // 收集样式
      <StaticRouter location={path} context={context}>
        <App />
      </StaticRouter>
    )
  );

  const htmlInfo = {
    reactStr,
    initialData: JSON.stringify(initialData),
    styles: sheet.getStyleTags()    //导出样式标签 <style>
  };
  ...
}

至此css in js (styled-components) ssr就完成了。

完整代码(ssr-css-in-js)

css资源处理

安装依赖

$ npm i css-loader mini-css-extract-plugin -D

css-loader是处理css文件用的,如果直接用styled-loader继续处理的话,是将样式处理放到js中,通过dom处理写入样式。但是,由于现在采用的是ssr,便不能如此。当然可以用isomorphic-style-loader在服务端就把样式写入head上,也是没问题的。而mini-css-extract-plugin是用来把css资源整合成css文件用的。

客户端webpack配置文件需要添加以下内容:

{ // ...
  module: {
    rules: [{
      test: /.css$/,
      use: [MiniCssExtractPlugin.loader, 'css-loader']
    }]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'index.css'
    }),
  ]
}

虽然客户端已经配置好了,也把css文件生成资源了,但是服务端编译的时候,会引入css资源,那么需要解决这个问题。因为服务端直出内容的时候,会携带客户端生成的css文件,那么服务端就不需要在编译的时候引入css文件。

解决办法:

  • loader进行处理
  • plugin进行处理
  • babel plugin处理

方法是挺多的,我是直接写了一个loader直接返回null即可。

module.exports = () => {  // ssr-css/webpack/loader/css-remove-loader.js
  return 'module.exports = null';
};

loader的话,以上一个loader处理结果作为参数,若本身是最后一个处理者,那么自身需要返回javascript code

然后我们在服务端webpack添加配置这个loader

{ // ...
  module: {
    rules: [{
      test: /.css$/,
      loader: './webpack/loader/css-remove-loader'
    }]
  },
} 

最后在我们的html拼接函数上,添加css资源引用。

<link rel="stylesheet" href="/index.css"></link>

目前只是简单处理了css资源,假设css资源非常大,那么需要进行分割,不然每次修改一个page的文件,就要导致css文件缓存失效,不太友好。

完整代码(ssr-css)

图片资源处理

安装依赖

$ npm i url-loader file-loader -D

url-loader作用是让我们对小图片资源转化成data bse64,对于大图片资源采用file-loader去处理。

webpack.base配置文件中加入一下内容

{ // ...
  test: /\.(jpg|png|jpeg)$/,
  use: [{
    loader: 'url-loader',
    options: {
      limit: 10240, 
      name: 'img/[name].[hash:7].[ext]', 
      esModule: false 
    }
  }]
}

optimization处理

因为目前,js文件是整合成了一个main.js,不是很友好。因为里面包含了很多,长时间不变的内容,比如react react-dom等等 ,那么我们每次修改js的时候,都会使其缓存失效,重新请求,是不合理的。

那么针对这个问题,webpack有提供optimization优化,可以通过这个字段,进行提取代码操作。

{ // ...
  optimization: {
    splitChunks: {
      cacheGroups: {
        libs: {
          test: /node_modules/, // 我们对依赖进行分包处理
          chunks: 'initial',
          name: 'libs'
        }
      }
    }
  }
}

那么客户端在编译打包后,就会多出一个libs.index.js文件,html拼接函数同样也需要引入这个文件。

<script type="text/javascript" src="/libs.index.js"></script>

完整代码(ssr-handle)

其他章节:

React SSR 实践过程(一)

React SSR 实践过程(三)