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

Implement fetch hook #73

Merged
merged 2 commits into from
Oct 21, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ This includes support for:
* Importing JSON
* Importing Web Assembly (note, there is an [open issue on how to handle the 4KB imposed limit](https://github.com/guybedford/es-module-shims/issues/1))

In addition a custom [fetch hook](#fetch-hook) can be implemented allowing for streaming in-browser transform workflows.

Because we are still using the native module loader the edge cases work out comprehensively, including:

* Live bindings in ES modules
Expand Down Expand Up @@ -158,6 +160,36 @@ This matches the specification for ES module workers, supporting all features of

> Module workers are only supported in browsers that provide dynamic import in worker environments, which is only Chrome currently.

### Fetch Hook

The ES Module Shims fetch hook can be used to implement transform plugins.

For example:

```js
importShim.fetch = async function (url) {
const response = await fetch(url);
if (response.url.endsWith('.ts')) {
const source = await response.body();
const transformed = tsCompile(source);
return new Response(URL.createObjectURL(new Blob([transformed], { type: 'application/javascript' })), { status: 200 });
guybedford marked this conversation as resolved.
Show resolved Hide resolved
}
return response;
};
```

Because the dependency analysis applies by ES Module Shims takes care of ensuring all dependencies run through the same fetch hook,
the above is all that is needed to implement custom plugins.

Streaming support can be handled through the above as well, although most compilers likely want synchronous sources as in the above.

#### Plugins

Since the Fetch Hook is very new, there are no plugin examples of it yet, but it should be easy to support various workflows
such as TypeScript and new JS features this way.

If you work on something here please do share to link to from here.

## Implementation Details

### Import Rewriting
Expand Down
3 changes: 2 additions & 1 deletion src/es-module-shims.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Object.defineProperties(importShim, {
l: { value: undefined, writable: true },
e: { value: undefined, writable: true }
});
importShim.fetch = url => fetch(url);

let lastLoad;
function resolveDeps (load, seen) {
Expand Down Expand Up @@ -161,7 +162,7 @@ function getOrCreateLoad (url, source) {

load.f = (async () => {
if (!source) {
const res = await fetch(url);
const res = await importShim.fetch(url);
if (!res.ok)
throw new Error(`${res.status} ${res.statusText} ${res.url}`);

Expand Down
30 changes: 30 additions & 0 deletions test/fetch-hook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

suite('Fetch hook', () => {
importShim.fetch = async function (url) {
if (!url.endsWith('json-or-js.js'))
return fetch(url);
const response = await fetch(url);
const reader = response.body.getReader();
console.log('--');
return new Response(new ReadableStream({
async start (controller) {
let done, value;
while (({ done, value } = await reader.read()) && !done) {
controller.enqueue(value);
}
controller.close();
}
}), {
status: 200,
statusText: 'CRAP',
headers: {
"Content-Type": "application/json"
}
});
}
test('Should hook fetch', async function () {
var m = await importShim('./fixtures/json-or-js.js');
assert(m.default);
assert.equal(m.default.a, 'b');
});
});
1 change: 1 addition & 0 deletions test/fixtures/json-or-js.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "a": "b" }
4 changes: 2 additions & 2 deletions test/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
throw new Error(msg);
};

const suites = ['browser-modules'];
const suites = ['browser-modules', 'fetch-hook'];
function runNextSuite () {
mocha.suite.suites.shift();
mocha.suite.suites = [];
const suite = suites.shift();
if (suite)
importShim('./' + suite + '.js')
Expand Down