Universal Javascript And
Bad Jokes
It's a tradition.....
Sam Clark
Iced Development
DevOps/Frontend/Backend/Slacker
@samrocksc
samrocksc@gmail.com
Why Universal Is Good
- Shorter Dependency Lists
- It's thoughtful and considerate
- It's good for junior devs!
- Robotics Libraries for the Browser(Johnny5/Noble)
- Telling people your a 1337 fUlLSt4Ck d3v
Things We Can Do
Browser
- the global is typically window
- require doesn't exist
- processes response objects differently
Node
- handles buffers differently
- Doesn't have a pre-defined `window` object
- There is no DOM
- Heavily module dependent
- Processes responses differently
Look Out For
- What libraries are handling what
- Known Differences
- Unknown Differences
Planning for Unknown Differences
Howard
Wrapping isomorphic-fetch
https://github.com/samrocksc/howard
Goals
- Error Handling Differences
- Request API for both frontend/backend
- Extensibility
- Return a promise
- Ease of use with modern frontend API's
- Still utilize fetch's super easy request interface
Base Usage
const { default: howard, json } = require('howard');
json(howard('https://swapi.co/api/people/1/'))
.then((res) => {
console.log('res', res);
return res;
});
isomorphic-fetch
- Only has two dependencies
- Returns a promise
node-fetch
A library aimed at bringing node into consistency with window.fetch
fetch-ponyfill
Aims to build and be compliant with the whatwg fetch spec
Basic Howard
function howard(path, options) {
if (options && options.body && !options.method) {
options.method = 'POST';
}
return fetch(path, options);
}
Handling Differences
function formData(response) {
return Promise.resolve(response)
.then((res) => {
if (typeof res.formData === 'function') {
return res.formData();
}
return Promise.reject(new Error('Method not implemented'));
});
}
...other ways
if (typeof options.body === 'object' && !(global.FormData && options.body instanceof FormData))
TESTING!!
Testing Deps
- mocha-puppeteer
- fetch-mock
- expect(easier for promise resolves)
Typical Test Harness
// Form Data
it('handle formData()', function() {
if (isNode) {
this.skip();
}
const data = new FormData();
data.append('testing', 'this')
fetchMock.getOnce(config.url + '/form', { body: data, sendAsJson: false })
const request = formData(howard(config.url + '/form'))
return expect(request).resolves.toEqual(data);
});
Skipping With ifNode
const isNode = (process && process.release && process.release.name === 'node');
* For some reason this was one of the hardest things to figure out for me. TypeErrors thrown in this situation can throw a wrench in the entire application.
Testing Scripts
"test:browser": "mocha-puppeteer test",
"test": "cross-env BABEL_ENV=commonjs mocha --async-only --compilers js:babel-register --recursive",
Testing Node!
Testing Browser!
Conclusion
Isomorphic development isn't for every aspect of programming, but when something can be done universally, let's try to make that happen!
Open Bad Jokes Session
Universal Javascript AndBad Jokes
By Sam Clark
Universal Javascript AndBad Jokes
- 795