Skip to content

Commit

Permalink
add encode and decode utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
jescalan committed May 12, 2017
1 parent 3e5f8a5 commit 33a000c
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 57 deletions.
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,56 @@ render(vdom, document.body, sortableEl)

And that's it! You'll see no visual difference, as preact won't re-render existing html, but it will remove the `data-ssr` property and layer on the javascript interaction as soon as it loads. Perfect!

### Passing Complex Data Into Components

You might find yourself in a situation in which you want to pass a large js object into your component at some point. This works fluidly with client-only react, since its javascript -> javascript, but when you are rendering as static, the data is written as static and transmitted via http before being consumed by javascript. This causes two issues.

First, html is parsed such that attribute values start and end with quotes. So if you have something like `<div data="{ foo: "bar" }"></div>`, you now have a parsing issue. HTML parsers will think that as soon as it hits the second double quote, you are done with your attribute value, and now you've got screwed up data and invalid html.

Second, since you are going to be transmitting this data directly in your html, it is included directly in your http requests and will appear in your html. As such, it would be a benefit to compress the data to minimize size.

There are two ways that this can be accomplished. The first is to only pass data that you need into your component, attribute by attribute, as such:

```html
<my-component
something='xxx'
somethingElse='yyy'
wowMoreThings='zzz'
lastThing='aaa'
></my-component>
```

The second way is to serialize your full object, pass it in a single attribute, and deserialze on the other end. This library exposes simple and efficient serialization and deserialization functions that you can use for this purpose. Using [spike](https://spike.cf) as an example here:

```js
// app.js
const render = require('reshape-preact-ssr')
const MyComponent = require('./my-component')

module.exports = {
reshape: htmlStandards({
locals: { encode: render.encode, data: { foo: 'bar' } },
appendPlugins: [render({ 'my-component': MyComponent })]
})
}
```

```html
<!-- index.html -->
<my-component data='{{ encode(data) }}'></my-component>
```

```js
// my-component.js
const {h} = require('preact')
const {decode} = require('reshape-preact-ssr')

module.exports = ({ data }) => {
const _data = decode(data)
return (<p>JSON.stringify(_data)</p>)
}
```

### License & Contributing

- Details on the license [can be found here](LICENSE.md)
Expand Down
14 changes: 12 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module.exports = (components) => {
}, (node) => {
// encode/compress the original html structure
// this can be rehydrated later to reduce client/server duplication
const originalHtml = gzipSync(JSON.stringify(node)).toString('base64')
const originalHtml = encode(node)
return parse(render(toVnode(components, node, originalHtml)))
})
}
Expand All @@ -21,7 +21,7 @@ module.exports = (components) => {
// element names to values as preact components, provides a full rehydrated
// vdom object representing the initial state before server rendering
module.exports.hydrateInitialState = (encoded, components) => {
return toVnode(components, JSON.parse(gunzipSync(Buffer.from(encoded, 'base64'))))
return toVnode(components, decode(encoded))
}

function toVnode (components, node, originalHtml) {
Expand All @@ -47,3 +47,13 @@ function toVnode (components, node, originalHtml) {
return h(name, props)
}
}

function encode (data) {
return gzipSync(JSON.stringify(data)).toString('base64')
}
module.exports.encode = encode

function decode (data) {
return JSON.parse(gunzipSync(Buffer.from(data, 'base64')))
}
module.exports.decode = decode
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"bugs": "https://github.com/reshape/reshape-preact-ssr/issues",
"dependencies": {
"preact": "^8.1.0",
"preact-render-to-string": "^3.6.1",
"preact-render-to-string": "^3.6.2",
"reshape-parser": "^0.2.1",
"reshape-plugin-util": "^0.2.1"
},
Expand All @@ -23,8 +23,8 @@
],
"devDependencies": {
"ava": "^0.19.1",
"codecov": "^2.1.0",
"nyc": "^10.2.0",
"codecov": "^2.2.0",
"nyc": "^10.3.2",
"reshape": "^0.4.1",
"snazzy": "^7.0.0",
"standard": "^10.0.2"
Expand Down
7 changes: 7 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,10 @@ test('initial state rehydration', (t) => {
t.is(rendered, '<p>the value of foo is &quot;bar&quot;</p>')
})
})

test('encode and decode', (t) => {
const data = JSON.stringify({ foo: 'bar' })
const encoded = ssr.encode(data)
const decoded = ssr.decode(encoded)
t.is(data, decoded)
})
99 changes: 47 additions & 52 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -884,9 +884,9 @@ code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"

codecov@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/codecov/-/codecov-2.1.0.tgz#25f48f9e9aa7473b61c5a9a934d595420a71cade"
codecov@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/codecov/-/codecov-2.2.0.tgz#2d06817ceb8891eca6368836d4fb6bf6cc04ffd1"
dependencies:
argv "0.0.2"
request "2.79.0"
Expand Down Expand Up @@ -1038,7 +1038,7 @@ [email protected]:
dependencies:
ms "0.7.1"

debug@^2.1.1, debug@^2.2.0:
debug@^2.1.1, debug@^2.2.0, debug@^2.6.3:
version "2.6.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.6.tgz#a9fa6fbe9ca43cf1e79f73b75c0189cbb7d6db5a"
dependencies:
Expand Down Expand Up @@ -2136,49 +2136,50 @@ isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"

istanbul-lib-coverage@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.0.2.tgz#87a0c015b6910651cb3b184814dfb339337e25e1"
istanbul-lib-coverage@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz#caca19decaef3525b5d6331d701f3f3b7ad48528"

istanbul-lib-hook@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.5.tgz#6ca3d16d60c5f4082da39f7c5cd38ea8a772b88e"
istanbul-lib-hook@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.6.tgz#c0866d1e81cf2d5319249510131fc16dee49231f"
dependencies:
append-transform "^0.4.0"

istanbul-lib-instrument@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.0.tgz#b8e0dc25709bb44e17336ab47b7bb5c97c23f659"
istanbul-lib-instrument@^1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.1.tgz#169e31bc62c778851a99439dd99c3cc12184d360"
dependencies:
babel-generator "^6.18.0"
babel-template "^6.16.0"
babel-traverse "^6.18.0"
babel-types "^6.18.0"
babylon "^6.13.0"
istanbul-lib-coverage "^1.0.2"
istanbul-lib-coverage "^1.1.0"
semver "^5.3.0"

istanbul-lib-report@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.0.0.tgz#d83dac7f26566b521585569367fe84ccfc7aaecb"
istanbul-lib-report@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.0.tgz#444c4ecca9afa93cf584f56b10f195bf768c0770"
dependencies:
istanbul-lib-coverage "^1.0.2"
istanbul-lib-coverage "^1.1.0"
mkdirp "^0.5.1"
path-parse "^1.0.5"
supports-color "^3.1.2"

istanbul-lib-source-maps@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.1.1.tgz#f8c8c2e8f2160d1d91526d97e5bd63b2079af71c"
istanbul-lib-source-maps@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.0.tgz#8c7706d497e26feeb6af3e0c28fd5b0669598d0e"
dependencies:
istanbul-lib-coverage "^1.0.2"
debug "^2.6.3"
istanbul-lib-coverage "^1.1.0"
mkdirp "^0.5.1"
rimraf "^2.4.4"
rimraf "^2.6.1"
source-map "^0.5.3"

istanbul-reports@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.0.2.tgz#4e8366abe6fa746cc1cd6633f108de12cc6ac6fa"
istanbul-reports@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.0.tgz#1ef3b795889219cfb5fad16365f6ce108d5f8c66"
dependencies:
handlebars "^4.0.3"

Expand Down Expand Up @@ -2658,9 +2659,9 @@ number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"

nyc@^10.2.0:
version "10.2.2"
resolved "https://registry.yarnpkg.com/nyc/-/nyc-10.2.2.tgz#1b1c8ca4636d810cb3e281558dc9fcb08389f204"
nyc@^10.3.2:
version "10.3.2"
resolved "https://registry.yarnpkg.com/nyc/-/nyc-10.3.2.tgz#f27f4d91f2a9db36c24f574ff5c6efff0233de46"
dependencies:
archy "^1.0.0"
arrify "^1.0.1"
Expand All @@ -2672,12 +2673,12 @@ nyc@^10.2.0:
find-up "^1.1.2"
foreground-child "^1.5.3"
glob "^7.0.6"
istanbul-lib-coverage "^1.0.2"
istanbul-lib-hook "^1.0.5"
istanbul-lib-instrument "^1.7.0"
istanbul-lib-report "^1.0.0"
istanbul-lib-source-maps "^1.1.1"
istanbul-reports "^1.0.2"
istanbul-lib-coverage "^1.1.0"
istanbul-lib-hook "^1.0.6"
istanbul-lib-instrument "^1.7.1"
istanbul-lib-report "^1.1.0"
istanbul-lib-source-maps "^1.2.0"
istanbul-reports "^1.1.0"
md5-hex "^1.2.0"
merge-source-map "^1.0.2"
micromatch "^2.3.11"
Expand All @@ -2686,9 +2687,9 @@ nyc@^10.2.0:
rimraf "^2.5.4"
signal-exit "^3.0.1"
spawn-wrap "1.2.4"
test-exclude "^4.0.0"
yargs "^7.0.2"
yargs-parser "^4.0.2"
test-exclude "^4.1.0"
yargs "^7.1.0"
yargs-parser "^5.0.0"

oauth-sign@~0.8.1:
version "0.8.2"
Expand Down Expand Up @@ -2967,9 +2968,9 @@ pluralize@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45"

preact-render-to-string@^3.6.1:
version "3.6.1"
resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-3.6.1.tgz#3be5dfc4e917fbe619398374deaa5b8f717ddf7c"
preact-render-to-string@^3.6.2:
version "3.6.2"
resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-3.6.2.tgz#341ac493fb818ce7beac335417188b2ae8c585bb"
dependencies:
pretty-format "^3.5.1"

Expand Down Expand Up @@ -3340,7 +3341,7 @@ right-align@^0.1.1:
dependencies:
align-text "^0.1.1"

rimraf@2, rimraf@^2.2.8, rimraf@^2.3.3, rimraf@^2.4.4, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1:
rimraf@2, rimraf@^2.2.8, rimraf@^2.3.3, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
dependencies:
Expand Down Expand Up @@ -3647,9 +3648,9 @@ term-size@^0.1.0:
dependencies:
execa "^0.4.0"

test-exclude@^4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.0.3.tgz#86a13ce3effcc60e6c90403cf31a27a60ac6c4e7"
test-exclude@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.0.tgz#04ca70b7390dd38c98d4a003a173806ca7991c91"
dependencies:
arrify "^1.0.1"
micromatch "^2.3.11"
Expand Down Expand Up @@ -3937,19 +3938,13 @@ yallist@^2.0.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"

yargs-parser@^4.0.2:
version "4.2.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c"
dependencies:
camelcase "^3.0.0"

yargs-parser@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a"
dependencies:
camelcase "^3.0.0"

yargs@^7.0.2:
yargs@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
dependencies:
Expand Down

0 comments on commit 33a000c

Please sign in to comment.