【问题标题】:Prerender React app as static HTML将 React 应用程序预渲染为静态 HTML
【发布时间】:2018-08-24 12:40:41
【问题描述】:

我有一个交互式登录页面(单页 - 没有反应路由器)。此登录页面需要上传到您只需粘贴 HTML 的 CMS - 这意味着我不需要 <html> <head> <body> 标记,并且 JavaScript 文件是单独上传的。目前,我只需将<div id="react-root"></div> 粘贴到 CMS 中并上传我捆绑的 JavaScript 文件,页面就可以工作了。

但是,反馈是该页面现在需要在所有搜索引擎上都可以抓取。这意味着我需要基本上渲染通过 react 生成的初始 HTML 以粘贴到 CMS 中,并让页面仍然按预期工作。

我正在尝试让我的构建命令将呈现的 HTML 输出到 index.html 文件中,我可以将代码复制并粘贴到 CMS 中。 (我的 bundle.js 文件工作正常)。

webpack.common.js

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
        ]
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader'
        ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          'file-loader'
        ]
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader"
      },
    ]
  },
  plugins: [
    new CleanWebpackPlugin(['dist'])
  ],
};

webpack.prod.js

const webpack = require('webpack');
const merge = require('webpack-merge');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const common = require('./webpack.common.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = merge(common, {
  plugins: [
    new UglifyJSPlugin(),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production')
    }),
    new HtmlWebpackPlugin({
      inject: false,
      template: require('./src/template.js'),
    })
  ]
});

template.js

const React = require('react');
const ReactDOMServer = require('react-dom/server');
const LandingPage = require('./App.js');
const html = ReactDOMServer.renderToString(LandingPage);

module.exports = function () {
  return ReactDOM.hydrate(html, document.getElementById('lp-root'));
};

所以我使用 react-dom-server 来渲染ToString。这是最好的方法吗?如果是这样,这种方式不起作用,因为 HtmlWebpackPlugin 无法处理登录页面(导入和导出)中使用的 ES6 语法 - 无论如何?

【问题讨论】:

    标签: javascript reactjs webpack html-webpack-plugin react-server


    【解决方案1】:

    这种方法似乎是正确的。
    但是,您可能需要 babel 转译器来将您的代码从 ES6 语法转换。
    尝试在 webpack 配置中为 js/jsx 文件添加新规则。
    像这样:

      {
        test: /js$/,
        exclude: /(node_modules)/,
        loader: "babel-loader",
        query: { presets: ["react", "es2016", "es2015"], plugins: ["transform-class-properties"] },
      },
    

    它会在使用前正确转译您的代码。

    希望对您有所帮助。 如有任何疑问,请回复。

    【讨论】:

    • 我的配置中确实有 babel(我已经用用于产品和开发的通用 webpack 配置更新了我的问题)。但是我仍然收到语法错误“import”,所以 HtmlWebpackPlugin 似乎超出了 bable 的范围?
    • 你还需要给 babel config 提供预设和插件。 Babel 只是一个转译器。您还需要提供 babel 用来将新语法转换为浏览器可读格式的插件。例如,我在答案中提供的查询预设了 es2016。它将帮助 babel 将 es2016 语法转换为浏览器可读格式。尝试为 js/jsx 文件添加上述查询。
    猜你喜欢
    • 2017-06-07
    • 1970-01-01
    • 1970-01-01
    • 2017-06-20
    • 1970-01-01
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多