在 React 服务器中提供 gzip 文件
Posted
技术标签:
【中文标题】在 React 服务器中提供 gzip 文件【英文标题】:Serving gzip files in React server 【发布时间】:2017-12-09 09:55:03 【问题描述】:我实际上在 React 中对我的 bundle.js 文件进行 gzip 压缩时遇到了问题。我正在尝试显着减小它的大小,并且我已经完成了 uglify 和 dedupe 等操作……它从 2.9mb 下降到了 2.6mb,这对我来说真的很奇怪。我现在正在使用压缩插件,我得到了一个输出的 gzip 文件,但现在我仍然提供 bundle.js 而不是 bundle.js.gz。
我不想使用 express 的压缩中间件,因为我在构建过程中使用 gzip。无论如何,这是我的 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`);
);
我的 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]',
,
]
;
我认为 app.get 函数会根据需要引入这些 gzip 文件,但我可能缺少步骤?另外,在我的 index.html 文件中,我是否需要省略将捆绑文件一起引入的脚本标签?
任何指导和想法将不胜感激!
【问题讨论】:
使用压缩中间件github.com/expressjs/compression 我在上面写过我不想使用压缩中间件,因为我正在构建阶段构建 gzip。 【参考方案1】:你应该把你的静态列表放在中间件之后
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`);
);
【讨论】:
【参考方案2】:听起来您首先要验证您是否正在提供 gzip 压缩文件,这可以通过 Chrome DevTools 轻松完成。
打开 Chrome DevTools,转到 performance
标签并配置您的网站。加载后,检查网络请求部分并找到您要验证的 Javascript 文件正在被 gzip 压缩。如果操作正确,您将看到something like this,其中encoded data
是通过网络发送的(希望压缩的)数据的大小,decoded body
是未压缩数据的大小。
如果两者相等,那么您可以正确地 gzip 压缩,但不能发送。
我的建议是在反向代理级别处理此问题,最好使用 nginx gzip static module 来提供 gzip 压缩文件。无论如何,您确实应该使用 NGINX 来提供静态内容,因为它会减轻您的节点服务器的负载。
【讨论】:
以上是关于在 React 服务器中提供 gzip 文件的主要内容,如果未能解决你的问题,请参考以下文章
带有 webpack 的 Vue.js 不提供压缩的 GZIP .js 文件
SyntaxError:在使用gzip提供文件时,仅在firefox中抛出非法字符
webpack系列从零搭建 webpack4+react 脚手架