Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for customizing compress encodings #657

Closed
wants to merge 9 commits into from

Conversation

arunoda
Copy link
Contributor

@arunoda arunoda commented Jan 4, 2017

Related: #555

By default we only do if for gzip.

For an example, here how to add support for bothbr and gzip compress encodings.

var zlib = require('zlib')
var iltorb = require('iltorb')

module.exports = {
  // Returns a map of compression streams for the types of encodings you want to support
  // Here's a list of common encoding types: https://goo.gl/ke7zOK

  // The first listed encoding has the higher priority over others.
  //  In this case, first it'll try to serve the `br` version if the browser supports it.
  //  Otherwise, it'll serve the gzipped version.
  compress: {
    br: function () {
      return iltorb.compressStream()
    },
    gzip: function () {
      // You can also return a promise which resolve a compression stream
      return new Promise(function (resolve) {
        resolve(zlib.createGzip())
      })
    }
  }
}

// Otherwise, it'll server gzipped version.
compress: {
br: function(filePath) {
return fs.createReadStream(filePath).pipe(iltorb.compressStream())
Copy link
Contributor

@nkzawa nkzawa Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should accept Promise instead of ReadableStream since errors might occur in the middle of compression process.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we capture it inside our code. We convert this into a promise.

Why I like this approach is, this is how most of the compression API works. So, it's pretty simple for the user. We handle the rest.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we capture it inside our code.

Actually, it doesn't capture all errors since errors are emitted on each stream. http://stackoverflow.com/questions/21771220/error-handling-with-node-js-streams

Additionally, we should consider the case you do something async inside the callback.

br (path) {
  something(path).then(() => {
    ..
  }).catch((err) => {
    // handle err
  })
}

Copy link
Contributor Author

@arunoda arunoda Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nkzawa so what what do get from the promise?

  • Stream
  • Nothing: Let them to write to the disk.

We can do something like this too:

{
  br: function(inputPath, outputPath) {
    return new Promise()
  }
}

Copy link
Contributor

@nkzawa nkzawa Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 That seems the simplest way.

Another idea is to accept only a transform stream.

    gzip: function() {
      return zlib.createGzip()
    }
  • We can catch all errors since other streams are prepared by us.
  • Maybe you can still do any async operations by wrapping them inside a stream.

I'm not so sure if this would cover all cases though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nkzawa I like that approach. And we can also also accept a promise from that function. (Which returns a stream)

@rauchg
Copy link
Member

rauchg commented Jan 5, 2017

What's br ?

@rauchg
Copy link
Member

rauchg commented Jan 5, 2017

Will leave this for post 2.0

@arunoda
Copy link
Contributor Author

arunoda commented Jan 6, 2017

@rauchg this is br: https://github.com/google/brotli (AKA: Realistic version of Pied Piper)

@arunoda
Copy link
Contributor Author

arunoda commented Jan 6, 2017

@nkzawa check now.

@rauchg
Copy link
Member

rauchg commented Jan 6, 2017 via email

@arunoda
Copy link
Contributor Author

arunoda commented Jan 6, 2017

@rauchg That's for the type of compress encodings we support.
Different browsers support different types of encodings. (They all do gzip, but if you get more optimizations, you need to do browser specific stuff like br)

We use this key (like 'br', 'gzip') to save the compressed file with that extension. Also we use this to detect which type of encodings we support and serve which is suits for the given browser.

See:
screen shot 2017-01-06 at 11 52 02 am

@msand
Copy link

msand commented Jan 6, 2017

Looks great, many thanks!

@rauchg
Copy link
Member

rauchg commented Jan 6, 2017

@arunoda should next do the accept-encoding parsing, or should we hand the header (or even request) to the function?

@msand
Copy link

msand commented Jan 6, 2017

@rauchg The compression is currently done statically on build, and next checks the supported and accepted encoding to decide what file to serve, which seems reasonable.

Compress on build: https://github.com/zeit/next.js/pull/657/files#diff-1634f71f56280340be4063732d469343R12
Choose encoding: https://github.com/zeit/next.js/pull/657/files#diff-bec864430eb5752a683c8798d0c6bd6cR146

</Link>

<Link href='/about'>
<a style={styles.a} >About</a>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be cool to use styled-jsx

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just wanna talk about this feature in this example.
Anyway, I don't mind using that too.

// In this case, first it'll try to serve the `br` version if the browser supports it.
// Otherwise, it'll serve the gzipped version.
compress: {
br: function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about compress the syntax to something like:

  br: iltorb.compressStream,
  gzip: () => new Promise(resolve => resolve(zlib.createGzip()))
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't is the same as right now except it should be br: iltorb.compressStream()?

If you are looking at ES2015 features, I didn't use them because we don't transpile the next.config.js.

@rauchg rauchg added this to the 2.1 milestone Jan 10, 2017
@timneutkens
Copy link
Member

@arunoda since we're moving to not use compression in next.js but let it be handled by the server, should this PR be closed?

@arunoda
Copy link
Contributor Author

arunoda commented Feb 9, 2017

Yeah! let's close this.

@arunoda arunoda closed this Feb 9, 2017
@arunoda arunoda deleted the custom-compress-type-support branch February 9, 2017 13:30
@lock lock bot locked as resolved and limited conversation to collaborators Jan 19, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants