【问题标题】:Brotli in a React application using server side rendering(SSR)使用服务器端渲染(SSR)的 React 应用程序中的 Brotli
【发布时间】:2019-07-10 19:37:34
【问题描述】:

我目前正在用 SSR 连接一个应用程序。不过,我是 服务器有问题没有在 Brotli 中返回响应 压缩文件格式。我确实看到我的 br 文件正在生成 通过我的客户端 webpack 配置文件中的 webpack。但是我的服务器没有 继续将 br 文件返回给我的客户。仅供参考....我也有我的 客户端的 webpack 也会生成 gz 文件。我试图以 br 模式返回的文件是 client_bundle.js 文件和 app.css。

正如您将在我的 server.js 文件中看到的那样,我发回了一个 HTML 字符串格式的响应。我试过改变我的链接和 脚本标签返回 app.css.br 和 client_bundle.js.br 但无济于事。

你知道我可能做错了什么以及为什么我的服务器不会返回吗 和/或客户端不会获取 CSS 和 JS 的 br 文件?

仅供参考....我在 server.js 文件中使用 nodejs,express-static-zip。在 另外,我正在使用 compression-webpack-plugin 和 brotli-webpack-plugin 为 app.css 和 client_bundle.js 生成 br 和 gz 文件。其他 旁注,我正在将我的客户端文件构建到 build/public 和我的服务器中 文件进入构建。

感谢您的帮助。

webpack.client.js

const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const webpack = require("webpack");
const autoprefixer = require("autoprefixer");
const CompressionPlugin = require("compression-webpack-plugin");
const BrotliPlugin = require("brotli-webpack-plugin");

module.exports = {
    mode:"development",
  optimization: {
    usedExports: true
  },
  entry: "./src/client/client.js",
  output: {
    filename: "client_bundle.js",
    path: path.resolve(__dirname, "build/public/"),
    publicPath: "/build/public/"
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: "babel-loader",
        exclude: "/node_modules"
      },
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: ["css-loader", "postcss-loader", "sass-loader"]
        })
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: [
          {
            loader: "file-loader",
            options: {
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin({
        filename: "app.css"
    }),
      new CompressionPlugin({
          filename: '[path].gz[query]'
      }),
      new BrotliPlugin({
          asset: '[path].br[query]',
          test: /\.(js|css|html|svg)$/,
          threshold: 10240,
          minRatio: 0.8
      })
  ]
};

服务器.js

import express from "express";
import cors from "cors";
import React from "react";
import { renderToString } from "react-dom/server";
import { Provider } from "react-redux";
import { StaticRouter, matchPath } from "react-router-dom";
import serialize from "serialize-javascript";
import routes from "../shared/routes";
import configureStore from "../shared/configureStore";
import App from "../shared/app";
import "source-map-support/register";
import http from "http";
import reload from "reload";
import expressStaticGzip from "express-static-gzip";

const app = express();
const PORT = process.env.PORT || 3000;

app.use(cors());
app.use("/build/public", expressStaticGzip('/build/public', {
    enableBrotli: true,
    orderPreference: ['br', 'gz'],
    setHeaders: function (res, path) {
        res.setHeader("Cache-Control", "public, max-age=31536000");
    }
}));
app.use(express.static("build/public"));

var server = http.createServer(app);
reload(app);
      acc.push(Promise.resolve(store.dispatch(route.component.initialData())));
    }
    return acc;
  }, []);
   const currentRoute = routes.find(route => matchPath(req.url, route));
   const requestInitialData =
   currentRoute.component.initialData && currentRoute.component.initialData();
  Promise.all(promises)
    .then(() => {
      const context = {};
      const markup = renderToString(
        <Provider store={store}>
          <StaticRouter location={req.url} context={context}>
            <App />
          </StaticRouter>
        </Provider>
      );

      const initialData = store.getState();
      res.send(`
        <!DOCTYPE html>
        <html>
          <head>
            <basehref="/">
            <title>Sample</title>
            <link rel="stylesheet" href="app.css.br">
          </head>

          <body>
            <div id="root">${markup}</div>
             <script src="client_bundle.js.br"></script>
             <script src="/reload/reload.js"></script>
            <script>window.__initialData__ = ${serialize(initialData)}</script>
          </body>
        </html>
      `);
    })
    .catch(next);
});

app.listen(PORT, () => {
  console.log("App running,", PORT);
});

【问题讨论】:

    标签: javascript node.js reactjs webpack brotli


    【解决方案1】:

    您正在压缩 Br 和 Gzip 中的客户端文件,这看起来是正确的,因为您的应用正在从 build/public 提供这些文件。

    但是服务器端渲染,它的响应是一个 HTML 页面,看起来并没有使用 Brotli 或 Gzip 进行压缩。因此,浏览器访问您的服务器,它以未压缩的 HTML 响应进行响应,然后在 React 进行水合之前下载 Brotli 压缩文件。

    【讨论】:

      猜你喜欢
      • 2021-11-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-05
      • 2018-06-05
      • 1970-01-01
      • 2018-05-10
      • 2016-08-16
      • 1970-01-01
      相关资源
      最近更新 更多