简体   繁体   English

在 React 服务器中提供 gzip 文件

[英]Serving gzip files in React server

I'm having trouble actually serving a gzip compression of my bundle.js file in React.我在 React 中实际提供 bundle.js 文件的 gzip 压缩时遇到了问题。 I am trying to reduce the size of this dramatically, and I have done uglify and dedupe, etc... and it's gone down from 2.9mb to 2.6mb which is really weird to me.我正在尝试大幅减小它的大小,并且我已经完成了 uglify 和 dedupe 等......它从 2.9mb 下降到 2.6mb,这对我来说真的很奇怪。 I am now using the compression plugin and I get an outputted gzip file, but now I'm still serving the bundle.js and not the bundle.js.gz.我现在正在使用压缩插件并得到一个输出的 gzip 文件,但现在我仍在服务 bundle.js 而不是 bundle.js.gz。

I don't want to use the compression middleware from express, because I'm doing the gzip in the build process.我不想使用 express 的压缩中间件,因为我在构建过程中执行了 gzip。 Anyways, here is my distServer file:无论如何,这是我的 distServer 文件:

import express from 'express';
import path from 'path';
import open from 'open';

/* eslint-disable no-console */

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


app.use(express.static('dist'));

app.get('*.js', function(req, res, next) {
 req.url = req.url + '.gz';
 res.set('Content-Encoding', 'gzip');
 res.set('Content-Type', 'text/javascript');
 next();
});

app.get('*.css', function(req, res, next) {
 req.url = req.url + '.gz';
 res.set('Content-Encoding', 'gzip');
 res.set('Content-Type', 'text/css');
 next();
});

app.get('*', function(req, res) {
  res.sendFile(path.join( __dirname, '../dist/index.html'));
});

app.listen(port, function(err) {
  if (err) {
    console.log(err);
  } else {
    open(`http://localhost:${port}`);
  }
});

And my webpack config is:我的 webpack 配置是:

import webpack from 'webpack';
import path from 'path';
import ExtractTextPlugin from 'extract-text-webpack-plugin';

var CopyWebpackPlugin = require('copy-webpack-plugin');
var CompressionPlugin = require("compression-webpack-plugin");
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

export default {
  devtool: 'source-map',
  noInfo: false,
  entry: [
    './src/index'
  ],
  target: 'web',
  output: {
    path: __dirname + '/dist', // Note: Physical files are only output by the production build task `npm run build`.
    publicPath: '/',
    filename: 'bundle.js'
  },
  plugins: [
    // new BundleAnalyzerPlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.DefinePlugin({
      'process.env': {NODE_ENV: '"production"'}
    }),
    new ExtractTextPlugin('styles.css'),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      mangle: true,
      compress: {
        warnings: false, // Suppress uglification warnings
        pure_getters: true,
        unsafe: true,
        unsafe_comps: true,
        screw_ie8: true
      },
      output: {
        comments: false,
      },
      exclude: [/\.min\.js$/gi] // skip pre-minified libs
    }),
    new CopyWebpackPlugin([
      { from: 'src/robots.txt', to: 'robots.txt' },
      { from: 'src/sitemap.xml', to: 'sitemap.xml' }
    ], {
      copyUnmodified: true
    }),
    new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]),
    new CompressionPlugin({
      asset: "[path].gz[query]",
      algorithm: "gzip",
      test: /\.js$|\.css$|\.html$/,
      threshold: 10240,
      minRatio: 0
    })
  ],
  module: {
    loaders: [
      {test: /\.js$/, include: path.join(__dirname, 'src'), loaders: ['babel']},
      {test: /(\.css)$/, loader: ExtractTextPlugin.extract("css?sourceMap")},
      {test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'},
      {test: /\.(woff|woff2)$/, loader: 'url?prefix=font/&limit=5000'},
      {test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream'},
      {test: /\.(jpe?g|png|gif|svg)$/i, loader: "url?limit=10000"},
      {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml'},
      {
        test: /favicon\.ico$/,
        loader: 'url',
        query: {
          limit: 1,
          name: '[name].[ext]',
        },
      }
    ]
  }
};

I thought the app.get functions would bring in those gzip files as needed, but I might be missing a step?我以为 app.get 函数会根据需要引入那些 gzip 文件,但我可能漏掉了一个步骤? Also, in my index.html file, do I need to omit the script tag bringing in the bundle file all together?另外,在我的 index.html 文件中,我是否需要省略将捆绑文件一起引入的脚本标签?

Any guidance and thoughts would be appreciated!任何指导和想法将不胜感激!

You should put your static listing after the middleware您应该将静态列表放在中间件之后

import express from 'express';
import path from 'path';
import open from 'open';

/* eslint-disable no-console */

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


app.get('*.js', function(req, res, next) {
 req.url = req.url + '.gz';
 res.set('Content-Encoding', 'gzip');
 res.set('Content-Type', 'text/javascript');
 next();
});

app.get('*.css', function(req, res, next) {
 req.url = req.url + '.gz';
 res.set('Content-Encoding', 'gzip');
 res.set('Content-Type', 'text/css');
 next();
});

app.use(express.static('dist'));

app.get('*', function(req, res) {
  res.sendFile(path.join( __dirname, '../dist/index.html'));
});

app.listen(port, function(err) {
  if (err) {
    console.log(err);
  } else {
    open(`http://localhost:${port}`);
  }
});

It sounds like you first want to verify if you even are serving the gzipped files, which is easily done through Chrome DevTools.听起来您首先想要验证您是否正在提供 gzip 文件,这可以通过 Chrome DevTools 轻松完成。

Open up Chrome DevTools, go to the performance tab and profile your website.打开 Chrome DevTools,转到performance选项卡并分析您的网站。 After it's loaded, check the network requests section and find the Javascript files you want to verify are being gzipped.加载后,检查网络请求部分并找到您要验证的 Javascript 文件是否正在 gzip 压缩。 If done correctly, you'll see something like this , where the encoded data is the size of the (hopefully compressed) data sent over the wire, and the decoded body is the size of the uncompressed data.如果操作正确,您会看到类似这样的内容,其中encoded data是通过网络发送的(希望是经过压缩的)数据的大小,而decoded body是未压缩数据的大小。

If the two are equal, then you could be gzipping correctly, but not sending it over.如果两者相等,那么您可以正确压缩,但不会发送。

My recommendation to you is to handle this at a reverse proxy level, ideally with the NGINX gzip static module to serve the gzipped files.我对您的建议是在反向代理级别处理此问题,最好使用NGINX gzip 静态模块来提供 gzip 文件。 You really should be using NGINX to serve static content anyway, as it will take load off of your node server.无论如何,你真的应该使用 NGINX 来提供静态内容,因为它会减轻你的节点服务器的负载。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM