I'm deploying a React App using Cloudfront and S3 and I would like to enable brotli for compression. I've seen some tutorials that address this problem using lambda@edge. The behavior configuration for my Cloudfront distribution is the following
I also have the 'Compress Objects Automatically' option set to 'No'. I have associated the two following lambda functions for origin requests and viewer requests, respectively:
- origin request:
'use strict';
/**
* Funciton registered on 'Origin Request' CloudFront Event
*/
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
console.log(JSON.stringify(request));
const headers = request.headers;
const isBr = headers['x-compression'] && headers['x-compression'][0].value === "br";
const isGzip = headers['x-compression'] && headers['x-compression'][0].value === "gzip";
/**
* Update request path based on custom header
*/
let extension = "";
if(isBr)
extension = ".br";
else if(isGzip)
extension = ".gzip";
request.uri = request.uri + extension;
callback(null, request);
};
- viewer request:
'use strict';
/**
* Funciton registered on 'Viewer Request' CloudFront Event
*/
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
console.log(JSON.stringify(request));
/**
* Detect if brotli is supported by the browser.
* Pass a custom header x-compression to be captured by the lambda in the origin-request phase.
*/
if(headers['accept-encoding'] && headers['accept-encoding'][0].value.indexOf('br') > -1) {
headers['x-compression'] = [{
key: 'X-Compression',
value: 'br'
}];
}
else if(headers['accept-encoding'] && headers['accept-encoding'][0].value.indexOf('gzip') > -1){
headers['x-compression'] = [{
key: 'X-Compression',
value: 'gzip'
}];
}
callback(null, request);
};
When I tried to open the app using Cloudfront's domain name in the browser in throws an Uncaught SyntaxError: illegal character in bundle.js:1. However, when I use S3's endpoint for opening the app it works perfectly. The following is my webpack.config.js
:
const path = require('path');
const autoprefixer = require('autoprefixer');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
chunkFilename: '[id].js',
publicPath: ''
},
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: {
localIdentName: "[name]__[local]___[hash:base64:5]",
},
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
autoprefixer({})
]
}
}
]
},
{
test: /\.(png|jpe?g|gif)$/,
loader: 'url-loader?limit=10000&name=img/[name].[ext]'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: __dirname + '/src/index.html',
filename: 'index.html',
inject: 'body'
}),
new CompressionPlugin({
filename: '[path].gz',
threshold: 0,
minRatio: 2,
test: /\.(js|css)$/i
}),
new CompressionPlugin({
filename: '[path].br',
algorithm: 'brotliCompress',
threshold: 0,
minRatio: 2,
test: /\.(js|css)$/i,
compressionOptions: {level: 11}
})
]
};
I've placed my code in this GitHub repo (I've also uploaded the dist/ directory which is the one I upload to S3 for the deployment). I'm new to this technologies so I ran out of ideas. I also tried adding .html and .png extensions to the plugins constructors in the Webpack configuration file but that didn't work either. Any help would be appreciated, thanks in advance