React 同构设置动态CDN

557 阅读3分钟

什么是同构

简单理解为: 同一套源码通过编译之后,可以在浏览器运行,也可以在服务端运行。

比如,react app的源码经过打包之后,在服务端运行的代码可以在服务端生成html标签字符串,这些字符串传输到浏览器端直接使用,客户端的代码就不需要重新生成字符串了,只需要执行事件绑定或者其它side effect的方法。这也是 水合(hydrate) 的含义。

动态CDN是什么意思, 为什么使用动态CDN

什么是动态CDN: 静态资源在不同的执行环境中使用不同的CDN。比如测试环境静态资源CDN是test-st.360buy.com 然后生产环境会变成 st.360buy.com。

为什么使用动态CDN

1、通常网站的主域名与静态资源域名是不相同的。比如 京东网址是:www.jd.com ,而静态资源的域名是: misc.360buyimg.com。

2、而开发周期通常分为Local(本地)、Test(测试)、Production(生产)等不同的环境。当代码在不同的环境运行时,往往静态资源域名也不一样。比如测试域名可能是test-misc.360buyimg.com,而生产环境域名是 misc.360bugimg.com。所以这时通过不同的运行环境来动态生成对应的CDN就十分有必要了。

其中静态资源包括:

  • CSS文件
  • JS文件
  • CSS背景图
  • Image(通过img标签引用的资源)
  • Font文件

到这里读者通常会有两个疑问。

  1. 通过webpack.config的output.publicPath配置CDN不就行了吗?
  2. 页面在服务端渲染的时候不同的环境下发不同的CDN不就行了吗,类似 <script src=${CDN}/app.js />?

通过webpack 配置output.publicPath的缺点

配置webpack output.publicPath,只能给不同的环境打包对应的资源。也就是说测试环境与生产环境的静态资源需要分开打包。无法做到打包同一份代码,在不同的环境运行,根据运行时来自动加载对应的CDN。

页面在服务端渲染的时候不同的环境下发不同的CDN的缺点

这种情况只能解决,入口文件的CDN地址。比如入口文件是app.js可以 <script src=`${CDN}/app.js` />; 但是通过代码分割 **按需加载的组件、Image(通过img 标签引用的大图资源)** 这些资源的CDN是默认使用的主域名。

webpack配置主要注意事项 (基于webpack5, webpack4请参考webpack-require-from这个插件):

打包Browser端的webpack设置:output.publicPath: 'auto'。

image.png

打包Server端的webpack设置:在ReactDOM.renderToPipeableStream之前对__webpack_public_path__ 赋值。webpack 暴露了一个名为 __webpack_public_path__ 的全局变量。

image.png 像上图那样对__webpack_public_path__赋值,在node端生成html string的时候,按需加载的静态资源比如图片、JS文件等都会自动使用这个全局变量。

注意事项

服务端渲染配置动态CDN没有这么完美,还有一些坑点。

1、生成ssr使用的js和browser使用的js的静态资源名字算法要一致。比如browser的png使用file-loader,而ssr使用的是 type: asset (type asset是webpack5新增加的功能,这样可以代替配置file-loader处理图片),这样生成的文件名子很有可能不一致,然后造成在node server端生成的字符串与browser端不匹配,这样就hydrate(水合)失败。 2、使用browser端的webpack设置 output.publicPath: 'auto';这个静态资源生成的文件地址会复杂一点,这块需要 type:asset需要通过generator.filename来配置与browser匹配的地址。使用file-loader需要通过postTransformPublicPath这个方法来配置与browser匹配的地址。

这块很抽象,请查看案例。重点看一下 webpack.config.js与webpack.ssr.js里面的图片 svg loader的配置。

参考案例:

github.com/getOnce/SSR…

注意查看webpack.config.js里面的output、ssr.tsx的__webpack_public_path__、webpack.ssr里面的图片地址转化

webpack官方介绍: webpack.docschina.org/guides/publ…