Skip to content

Commit

Permalink
Use rollup to generate bundles for UMD, ESM and CJS (#63)
Browse files Browse the repository at this point in the history
Co-authored-by: Jack Clark

### What does this PR do?

Generates bundles for UMD, ESM and CommonJS. This brings with it support for browsers >= IE11. 

Whilst working on this we published a few version to `npm` with the `test` tag so that it could be tested. This [codepen](https://codepen.io/anon/pen/XGbdxR) has been created which uses the `UMD` build. We spun up a quick Create react app to test out `ESM` which worked great. The nextjs example app has also been updated locally to use the commonjs version. 

Our rollup config was heavily influenced by the one [in redux](https://github.com/reduxjs/redux/blob/master/rollup.config.js).

Bundle size has slightly increased but we now have increased browser support and our module is now tree shakeable, meaning potentially reduced size for end users.

*Important*
We now use Promises to write this library as transpiling from async/await is usually avoided in libraries as it's expensive. We opted instead to use untranspiled Promises and then inform the user they should provide an environment that includes Promises.

### Related issues

Resolves #11 

### Checklist

- [x] I have checked the [contributing document](../blob/master/CONTRIBUTING.md)
- [x] I have added or updated any relevant documentation
- [x] I have added or updated any relevant tests
  • Loading branch information
Joezo authored Feb 28, 2019
1 parent d89e405 commit ae154d3
Show file tree
Hide file tree
Showing 13 changed files with 296 additions and 87 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ node_modules
graphql-hooks-*.*.*.tgz
package-lock.json
/coverage
.DS_Store
lib
dist
es
45 changes: 45 additions & 0 deletions .size-snapshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"lib/graphql-hooks.js": {
"bundled": 11105,
"minified": 5606,
"gzipped": 1919
},
"es/graphql-hooks.js": {
"bundled": 10760,
"minified": 5314,
"gzipped": 1844,
"treeshaked": {
"rollup": {
"code": 67,
"import_statements": 21
},
"webpack": {
"code": 1069
}
}
},
"es/graphql-hooks.mjs": {
"bundled": 3954,
"minified": 3954,
"gzipped": 1521,
"treeshaked": {
"rollup": {
"code": 67,
"import_statements": 21
},
"webpack": {
"code": 1071
}
}
},
"dist/graphql-hooks.js": {
"bundled": 11352,
"minified": 5114,
"gzipped": 1921
},
"dist/graphql-hooks.min.js": {
"bundled": 5070,
"minified": 5070,
"gzipped": 1900
}
}
3 changes: 3 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ You can test the test coverage by running:
npm run test:coverage
```

**Important**
We don't use async/await in this library due to transpilation costs. Instead we use Promises and inform the user that they should provide a suitable environment.

## For Collaborators

Make sure to get a `:thumbsup:`, `+1` or `LGTM` from another collaborator before merging a PR. If you aren't sure if a release should happen, open an issue.
Expand Down
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
## Features

- 🥇 First-class hooks API
- ⚖️ _Tiny_ bundle: only 4kB (1.5 gzipped)
- ⚖️ _Tiny_ bundle: only 5.1kB (1.9 gzipped)
- 📄 Full SSR support: see [graphql-hooks-ssr](https://github.com/nearform/graphql-hooks-ssr)
- 🔌 Plugin Caching: see [graphql-hooks-memcache](https://github.com/nearform/graphql-hooks-memcache)
- 🔥 No more render props hell
Expand All @@ -25,6 +25,16 @@ or

`yarn add graphql-hooks`

## Support

- Latest 8 & 10 Node releases
- Browsers [`> 1%, not dead`](https://browserl.ist/?q=%3E+1%25%2C+not+dead)

Consider polyfilling:

- [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)
- [`fetch`](https://developer.mozilla.org/docs/Web/API/Fetch_API). NOTE: A custom implementation can also be provided instead of polyfilling, [see `GraphQLClient`](#GraphQLClient)

## Quick Start

First you'll need to create a client and wrap your app with the provider:
Expand Down Expand Up @@ -455,7 +465,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore -->

| [<img src="https://avatars1.githubusercontent.com/u/1939483?v=4" width="100px;" alt="Brian Mullan"/><br /><sub><b>Brian Mullan</b></sub>](https://twitter.com/bmullan91)<br />[💬](#question-bmullan91 "Answering Questions") [🐛](https://github.com/nearform/graphql-hooks/issues?q=author%3Abmullan91 "Bug reports") [💻](https://github.com/nearform/graphql-hooks/commits?author=bmullan91 "Code") [🖋](#content-bmullan91 "Content") [📖](https://github.com/nearform/graphql-hooks/commits?author=bmullan91 "Documentation") [💡](#example-bmullan91 "Examples") [🤔](#ideas-bmullan91 "Ideas, Planning, & Feedback") [🚧](#maintenance-bmullan91 "Maintenance") [👀](#review-bmullan91 "Reviewed Pull Requests") [⚠️](https://github.com/nearform/graphql-hooks/commits?author=bmullan91 "Tests") | [<img src="https://avatars0.githubusercontent.com/u/1485654?v=4" width="100px;" alt="Jack Clark"/><br /><sub><b>Jack Clark</b></sub>](https://jackdc.com)<br />[💬](#question-jackdclark "Answering Questions") [🐛](https://github.com/nearform/graphql-hooks/issues?q=author%3Ajackdclark "Bug reports") [💻](https://github.com/nearform/graphql-hooks/commits?author=jackdclark "Code") [🖋](#content-jackdclark "Content") [📖](https://github.com/nearform/graphql-hooks/commits?author=jackdclark "Documentation") [💡](#example-jackdclark "Examples") [🤔](#ideas-jackdclark "Ideas, Planning, & Feedback") [🚧](#maintenance-jackdclark "Maintenance") [👀](#review-jackdclark "Reviewed Pull Requests") [⚠️](https://github.com/nearform/graphql-hooks/commits?author=jackdclark "Tests") | [<img src="https://avatars1.githubusercontent.com/u/2870255?v=4" width="100px;" alt="Joe Warren"/><br /><sub><b>Joe Warren</b></sub>](http://twitter.com/joezo)<br />[💬](#question-Joezo "Answering Questions") [🐛](https://github.com/nearform/graphql-hooks/issues?q=author%3AJoezo "Bug reports") [💻](https://github.com/nearform/graphql-hooks/commits?author=Joezo "Code") [🖋](#content-Joezo "Content") [📖](https://github.com/nearform/graphql-hooks/commits?author=Joezo "Documentation") [💡](#example-Joezo "Examples") [🤔](#ideas-Joezo "Ideas, Planning, & Feedback") [🚧](#maintenance-Joezo "Maintenance") [👀](#review-Joezo "Reviewed Pull Requests") [⚠️](https://github.com/nearform/graphql-hooks/commits?author=Joezo "Tests") | [<img src="https://avatars1.githubusercontent.com/u/20181?v=4" width="100px;" alt="Simone Busoli"/><br /><sub><b>Simone Busoli</b></sub>](http://simoneb.github.io)<br />[💬](#question-simoneb "Answering Questions") [🐛](https://github.com/nearform/graphql-hooks/issues?q=author%3Asimoneb "Bug reports") [📖](https://github.com/nearform/graphql-hooks/commits?author=simoneb "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/842246?v=4" width="100px;" alt="jhey tompkins"/><br /><sub><b>jhey tompkins</b></sub>](https://jheytompkins.com)<br />[⚠️](https://github.com/nearform/graphql-hooks/commits?author=jh3y "Tests") [💬](#question-jh3y "Answering Questions") [🐛](https://github.com/nearform/graphql-hooks/issues?q=author%3Ajh3y "Bug reports") [💻](https://github.com/nearform/graphql-hooks/commits?author=jh3y "Code") [🖋](#content-jh3y "Content") |
| :---: | :---: | :---: | :---: | :---: |

Expand Down
20 changes: 17 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@
"name": "graphql-hooks",
"version": "3.1.1",
"description": "Graphql Hooks",
"main": "src/index.js",
"main": "lib/graphql-hooks.js",
"module": "es/graphql-hooks.js",
"unpkg": "dist/graphql-hooks.min.js",
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"prettier": "pretty-quick"
"prettier": "pretty-quick",
"build": "rollup -c",
"prepublishOnly": "npm run build"
},
"files": [
"dist",
"es",
"lib"
],
"keywords": [
"graphql",
"hooks",
Expand Down Expand Up @@ -36,7 +45,12 @@
"react": "16.8.3",
"react-dom": "16.8.3",
"react-hooks-testing-library": "0.3.4",
"react-testing-library": "6.0.0"
"react-testing-library": "6.0.0",
"rollup": "1.3.0",
"rollup-plugin-babel": "4.3.2",
"rollup-plugin-node-resolve": "4.0.1",
"rollup-plugin-size-snapshot": "0.8.0",
"rollup-plugin-terser": "4.0.4"
},
"dependencies": {},
"husky": {
Expand Down
107 changes: 107 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import nodeResolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';
import replace from 'rollup-plugin-replace';
import { terser } from 'rollup-plugin-terser';
import { sizeSnapshot } from 'rollup-plugin-size-snapshot';

import pkg from './package.json';

const external = [...Object.keys(pkg.peerDependencies || {})];

export default [
// CommonJS
{
input: 'src/index.js',
output: { file: 'lib/graphql-hooks.js', format: 'cjs', indent: false },
external,
plugins: [babel(), sizeSnapshot()]
},

// ES
{
input: 'src/index.js',
output: { file: 'es/graphql-hooks.js', format: 'es', indent: false },
external,
plugins: [babel(), sizeSnapshot()]
},

// ES for Browsers
{
input: 'src/index.js',
output: { file: 'es/graphql-hooks.mjs', format: 'es', indent: false },
external,
plugins: [
nodeResolve({
jsnext: true
}),
replace({
'process.env.NODE_ENV': JSON.stringify('production')
}),
terser({
compress: {
pure_getters: true,
unsafe: true,
unsafe_comps: true,
warnings: false
}
}),
sizeSnapshot()
]
},

// UMD Development
{
input: 'src/index.js',
output: {
file: 'dist/graphql-hooks.js',
format: 'umd',
name: 'GraphQLHooks',
indent: false
},
external,
plugins: [
nodeResolve({
jsnext: true
}),
babel({
exclude: 'node_modules/**'
}),
replace({
'process.env.NODE_ENV': JSON.stringify('development')
}),
sizeSnapshot()
]
},

// UMD Production
{
input: 'src/index.js',
output: {
file: 'dist/graphql-hooks.min.js',
format: 'umd',
name: 'GraphQLHooks',
indent: false
},
external,
plugins: [
nodeResolve({
jsnext: true
}),
babel({
exclude: 'node_modules/**'
}),
replace({
'process.env.NODE_ENV': JSON.stringify('production')
}),
terser({
compress: {
pure_getters: true,
unsafe: true,
unsafe_comps: true,
warnings: false
}
}),
sizeSnapshot()
]
}
];
21 changes: 21 additions & 0 deletions src/.babelrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const { NODE_ENV } = process.env;

module.exports = {
presets: [
[
'@babel/env',
{
targets: {
browsers: ['ie >= 11']
},
modules: false,
loose: true
}
]
],
plugins: [
// don't use `loose` mode here - need to copy symbols when spreading
'@babel/proposal-object-rest-spread',
NODE_ENV === 'test' && '@babel/transform-modules-commonjs'
].filter(Boolean)
};
4 changes: 2 additions & 2 deletions src/ClientContext.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const React = require('react');
import React from 'react';

const ClientContext = React.createContext();

ClientContext.displayName = 'ClientContext';

module.exports = ClientContext;
export default ClientContext;
92 changes: 46 additions & 46 deletions src/GraphQLClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,54 +93,54 @@ class GraphQLClient {
};
}

async request(operation, options = {}) {
let result;

try {
const response = await this.fetch(this.url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...this.headers
},
body: JSON.stringify({
query: operation.query,
variables: operation.variables,
operationName: operation.operationName
}),
...this.fetchOptions,
...options.fetchOptionsOverrides
});

if (!response.ok) {
const body = await response.text();
const { status, statusText } = response;
result = this.generateResult({
httpError: {
status,
statusText,
body
}
});
} else {
const { errors, data } = await response.json();
result = this.generateResult({
graphQLErrors: errors,
data
request(operation, options = {}) {
return this.fetch(this.url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...this.headers
},
body: JSON.stringify({
query: operation.query,
variables: operation.variables,
operationName: operation.operationName
}),
...this.fetchOptions,
...options.fetchOptionsOverrides
})
.then(response => {
if (!response.ok) {
return response.text().then(body => {
const { status, statusText } = response;
return this.generateResult({
httpError: {
status,
statusText,
body
}
});
});
} else {
return response.json().then(({ errors, data }) => {
return this.generateResult({
graphQLErrors: errors,
data
});
});
}
})
.catch(error => {
return this.generateResult({
fetchError: error
});
}
} catch (error) {
result = this.generateResult({
fetchError: error
})
.then(result => {
if (result.error && this.logErrors) {
this.logErrorResult({ result, operation });
}
return result;
});
}

if (result.error && this.logErrors) {
this.logErrorResult({ result, operation });
}

return result;
}
}

module.exports = GraphQLClient;
export default GraphQLClient;
Loading

0 comments on commit ae154d3

Please sign in to comment.