Skip to content

Commit

Permalink
feat: remove lz compression (#654)
Browse files Browse the repository at this point in the history
We've wanted to remove LZ compression for c2 years. #155

it is 5%+ of the bundle size.

Let's remove it

compression options are provided by decide, decide returns a harcoded list, and the library prefers gzip if it is present. So this can only negatively affect people using very, very old self-hosted versions and the latest pothog-js. And even then it would mean they would switch from lz64 to base64 so things would carry on working.
  • Loading branch information
pauldambra authored May 31, 2023
1 parent 9f6e0bd commit fcdd0b9
Show file tree
Hide file tree
Showing 12 changed files with 64 additions and 606 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ coverage
react/dist
test-result.json
yarn-error.log
/.eslintcache
stats.html
.eslintcache
44 changes: 2 additions & 42 deletions cypress/e2e/capture.cy.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/// <reference types="cypress" />
import { version } from '../../package.json'

import { getBase64EncodedPayload, getGzipEncodedPayload, getLZStringEncodedPayload } from '../support/compression'
import { getBase64EncodedPayload, getGzipEncodedPayload } from '../support/compression'

const urlWithVersion = new RegExp(`&ver=${version}`)

describe('Event capture', () => {
given('options', () => ({}))
given('sessionRecording', () => false)
given('supportedCompression', () => ['gzip', 'lz64'])
given('supportedCompression', () => ['gzip-js'])

// :TRICKY: Use a custom start command over beforeEach to deal with given2 not being ready yet.
const start = ({ waitForDecide = true } = {}) => {
Expand Down Expand Up @@ -332,47 +332,7 @@ describe('Event capture', () => {
})

describe('decoding the payload', () => {
it('contains the correct headers and payload after an event', () => {
start()

// Pageview will be sent immediately
cy.wait('@capture').should(({ request, url }) => {
expect(request.headers).to.eql({
'Content-Type': 'application/x-www-form-urlencoded',
})

expect(url).to.match(urlWithVersion)
const captures = getBase64EncodedPayload(request)

expect(captures['event']).to.equal('$pageview')
})

cy.get('[data-cy-custom-event-button]').click()
cy.get('[data-cy-custom-event-button]').click()
cy.phCaptures().should('have.length', 5)
cy.phCaptures().should('include', '$autocapture')
cy.phCaptures().should('include', 'custom-event')

cy.wait('@capture').should(({ request, url }) => {
expect(request.headers).to.eql({
'Content-Type': 'application/x-www-form-urlencoded',
})

expect(url).to.match(urlWithVersion)
const captures = getLZStringEncodedPayload(request)

expect(captures.map(({ event }) => event)).to.deep.equal([
'$autocapture',
'custom-event',
'$autocapture',
'custom-event',
])
})
})

describe('gzip-js supported', () => {
given('supportedCompression', () => ['gzip-js'])

it('contains the correct payload after an event', () => {
start()
// Pageview will be sent immediately
Expand Down
6 changes: 0 additions & 6 deletions cypress/support/compression.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
import * as fflate from 'fflate'
import { LZString } from '../../src/lz-string'

export function getBase64EncodedPayload(request) {
const data = decodeURIComponent(request.body.match(/data=(.*)/)[1])
return JSON.parse(Buffer.from(data, 'base64'))
}

export function getLZStringEncodedPayload(request) {
const data = decodeURIComponent(request.body.match(/data=(.*)&compression=lz64/)[1])
return JSON.parse(LZString.decompressFromBase64(data))
}

export async function getGzipEncodedPayload(requestBody) {
const data = new Uint8Array(await requestBody.arrayBuffer())
const decoded = fflate.strFromU8(fflate.decompressSync(data))
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"prettier": "^2.7.1",
"rollup": "^2.77.0",
"rollup-plugin-dts": "^4.2.2",
"rollup-plugin-visualizer": "^5.9.0",
"rrweb": "^1.1.3",
"rrweb2": "npm:[email protected]",
"sinon": "9.0.2",
Expand Down
2 changes: 2 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import typescript from '@rollup/plugin-typescript'
import dts from 'rollup-plugin-dts'
import pkg from './package.json'
import terser from '@rollup/plugin-terser'
import { visualizer } from 'rollup-plugin-visualizer'

const extensions = ['.js', '.jsx', '.ts', '.tsx']
const plugins = [
Expand All @@ -17,6 +18,7 @@ const plugins = [
presets: ['@babel/preset-env'],
}),
terser({ toplevel: true }),
visualizer(),
]

export default [
Expand Down
12 changes: 0 additions & 12 deletions src/__tests__/__snapshots__/compression.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,3 @@ Array [
},
]
`;

exports[`compressData() handles lz64 1`] = `
Array [
Object {
"compression": "lz64",
"data": "N4IgNghgTg5gpgfQNZwJ4gFwggIwMa4H6EnFlEWmXlW033WN1MPNusctfvec/99BvYQJFDRE8VLEzJs6XMULl81UrUr1WzTo17t+3QeNHTh8yYtnLN63asPbj+09cv3zz8xABfIA",
},
Object {
"method": "POST",
},
]
`;
21 changes: 9 additions & 12 deletions src/__tests__/compression.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,18 @@ describe('decideCompression()', () => {
})

it('returns gzip-js if all compressions supported', () => {
given('compressionSupport', () => ({ lz64: true, 'gzip-js': true }))
given('compressionSupport', () => ({
'gzip-js': true,
'a different thing that is either deprecated or new': true,
}))

expect(given.subject).toEqual('gzip-js')
})

it('returns lz64 if supported', () => {
given('compressionSupport', () => ({ lz64: true, 'gzip-js': false }))
it('returns base64 if only unexpected compression is received', () => {
given('compressionSupport', () => ({ 'the new compression that is not supported yet': true }))

expect(given.subject).toEqual('lz64')
expect(given.subject).toEqual('base64')
})
})

Expand All @@ -37,12 +40,6 @@ describe('compressData()', () => {
expect(given.subject).toMatchSnapshot()
})

it('handles lz64', () => {
given('compression', () => 'lz64')

expect(given.subject).toMatchSnapshot()
})

it('handles gzip-js', () => {
given('compression', () => 'gzip-js')

Expand All @@ -67,7 +64,7 @@ describe('Payload Compression', () => {
_prepare_callback: sandbox.spy((callback) => callback),
_send_request: sandbox.spy((url, params, options, callback) => {
if (url === 'https://test.com/decide/?v=3') {
callback({ config: { enable_collect_everything: true }, supportedCompression: ['lz64'] })
callback({ config: { enable_collect_everything: true }, supportedCompression: ['gzip-js'] })
} else {
throw new Error('Should not get here')
}
Expand Down Expand Up @@ -112,7 +109,7 @@ describe('Payload Compression', () => {
it('should save supported compression in instance', () => {
new Decide(lib).call()
autocapture.init(lib)
expect(lib.compression).toEqual({ lz64: true })
expect(lib.compression).toEqual({ 'gzip-js': true })
})
})
})
7 changes: 1 addition & 6 deletions src/compression.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { LZString } from './lz-string'
import { gzipSync, strToU8 } from 'fflate'
import { _base64Encode } from './utils'
import { Compression, CompressionData, XHROptions } from './types'

export function decideCompression(compressionSupport: Partial<Record<Compression, boolean>>): Compression {
if (compressionSupport[Compression.GZipJS]) {
return Compression.GZipJS
} else if (compressionSupport[Compression.LZ64]) {
return Compression.LZ64
} else {
return Compression.Base64
}
Expand All @@ -18,9 +15,7 @@ export function compressData(
jsonData: string,
options: XHROptions
): [CompressionData | Uint8Array, XHROptions] {
if (compression === Compression.LZ64) {
return [{ data: LZString.compressToBase64(jsonData), compression: Compression.LZ64 }, options]
} else if (compression === Compression.GZipJS) {
if (compression === Compression.GZipJS) {
// :TRICKY: This returns an UInt8Array. We don't encode this to a string - returning a blob will do this for us.
return [
gzipSync(strToU8(jsonData), { mtime: 0 }),
Expand Down
Loading

0 comments on commit fcdd0b9

Please sign in to comment.