GX博客

分享个人 Full-Stack JavaScript 项目开发经验

create-react-app单页应用开发的服务器端数据注入解决方案

create-react-app是 React 官方维护的一套单页应用开发脚手架。它的更新速度比较快,很及时地适应了快速发展的前沿技术。由客户端渲染的单页应用开发模式往往适合于无需搜索引擎优化的后台管理系统,但正是这样的后台管理系统就更加需要服务器端的控制。本文将介绍 create-react-app 如何配合服务器端的数据注入。


为什么有些单页应用需要服务器端数据注入?

  1. 为了使首屏渲染更加流畅,可以预先在服务器端注入首屏渲染所需的动态数据。
  2. 在服务器端注入安全相关标记,如 CSRF 令牌、script 标签的 nonce 值等。

单页应用要实现服务器端数据注入需要解决的主要问题什么?

单页应用打包后生成的 index.html 包含哈希文件名的资源,我们需要在打包完成后同步生成一份最新的副本供服务器端使用,并且该副本能够用于数据注入。


1、首先,从安装最新版本的 create-react-app 开始:

npx create-react-app admin
cd admin
yarn install

2、将所有配置文件和传递依赖项复制到项目中:

npm run eject

3、安装 react-app-polyfill:

yarn add react-app-polyfill

在 index.js 的首行引入 polyfill:

import 'react-app-polyfill/ie9';

4、在 package.json 中配置代理和 browserslist

"proxy": "https://localhost",
"browserslist": {
  "production": [
    "last 2 versions",
    ">0.2%",
    "not op_mini all",
    "not dead",
    "ie 10"
  ],
  "development": [
    "last 2 versions",
    ">0.2%",
    "not op_mini all",
    "not dead",
    "ie 10"
  ]
},

5、在根目录创建 .env,设置高级配置环境变量

# HTTPS=true
PORT=3010
INLINE_RUNTIME_CHUNK=false
GENERATE_SOURCEMAP=false
PUBLIC_URL=/javascripts/admin

6、修改 config/paths.js 的打包文件生成目录 appBuild 到 nginx 托管目录

// appBuild: resolveApp('build'),
appBuild: '/usr/local/Cellar/nginx/1.17.0/public/www.leeguangxing.cn/javascripts/admin',

7、在 public/index.html 中设置替换标记:

<script id="inject">
    window._websiteMessage = {"website_zh_name":"GX博客"};
    window._lastLoginMessage = {"user_last_login_ip":"14.23.47.110"};
    window._csrf = '';
</script>

8、调整打包执行脚本 scripts/build.js,在打包成功后添加:

// ------------------- convert index.html to buildHtmlPage.js --------------------

const inputUrl = paths.appBuild + '/index.html';
const outputUrl = '../server/views/admin/buildHtmlPage.js';

const content = fs.readFileSync(inputUrl, {encoding: 'utf8'});

const contentAfterReplace = content.replace(
  /<script id="inject">.+?<\/script>/,
  "<script>window._websiteMessage = ${websiteMessage};window._lastLoginMessage = ${lastLoginMessage};window._csrf = '${csrf}';</script>"
);

fs.writeFileSync(
  outputUrl,
  `module.exports.buildHtmlPage = ({websiteMessage, lastLoginMessage, csrf}) => \`${contentAfterReplace}\`;`,
  'utf8'
);
console.log(chalk.green('buildHtmlPage.js created.\n'));

9、在 koa2 服务器端调用 buildHtmlPage.js

const {buildHtmlPage} = require("../../views/admin/buildHtmlPage");

这些配置所做的事情就是:设置项目的 API 代理地址和兼容浏览器列表;添加 polyfill;设置环境变量值;配置打包文件生成到 nginx 的托管目录;当打包完毕后,根据 index.html 的预设标记自动生成供服务器端使用的 buildHtmlPage.js。

版权声明:

本文为博主原创文章,若需转载,须注明出处,添加原文链接。

https://leeguangxing.cn/blog_post_68.html