首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用服务器端渲染(SSR)的React应用程序中的Brotli

使用服务器端渲染(SSR)的React应用程序中的Brotli
EN

Stack Overflow用户
提问于 2019-02-17 12:07:22
回答 1查看 1.6K关注 0票数 3

我目前正在使用react中的SSR连接一个应用程序。然而,我遇到了服务器不能以Brotli压缩文件格式返回响应的问题。我确实看到我的br文件是由webpack在我的客户端webpack配置文件中生成的。但是我的服务器在将br文件返回给我的客户端时不能接受。仅供参考……我也让我的webpack为客户端生成gz文件。我试图在br模式下返回的文件是client_bundle.js文件和app.css。

正如您将在我的server.js文件中看到的那样,我以HTML string格式发回一个响应。我已经尝试更改我的链接和脚本标记以返回app.css.br和client_bundle.js.br,但没有效果。

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

仅供参考...我在我的server.js文件中使用了nodejs,express-static-zip。此外,我正在使用压缩的-webpack插件和brotli-webpack-插件来生成app.css和client_bundle.js的br和gz文件。另一个附注是,我将客户端文件构建到build/public中,将服务器文件构建到build中。

谢谢你的帮助。

webpack.client.js

代码语言:javascript
复制
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
      })
  ]
};

Server.js

代码语言:javascript
复制
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);
});

EN

回答 1

Stack Overflow用户

发布于 2019-02-22 00:47:57

您正在压缩Br和Gzip格式的客户端文件,这看起来是正确的,因为您的应用程序是从build/public为它们提供服务的。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54730009

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档