From 6e27880d09628dea7db2386719b129971708d1e1 Mon Sep 17 00:00:00 2001 From: GrygrFlzr Date: Sat, 17 Apr 2021 22:23:03 +0700 Subject: [PATCH] Move server-side `fetch` responsibility to adapters instead of build step (#1066) * Move server-side fetch to adapters instead of build step * set global fetch in svelte-kit start * remove node-fetch from examples * lockfile Co-authored-by: Rich Harris --- .changeset/gorgeous-hounds-peel.md | 8 ++++ .../hn.svelte.dev/src/routes/[list]/rss.js | 39 +++++++++---------- examples/realworld.svelte.dev/package.json | 3 +- examples/realworld.svelte.dev/src/lib/api.js | 5 --- .../realworld.svelte.dev/svelte.config.cjs | 8 +--- packages/adapter-netlify/files/render.js | 7 ++++ packages/adapter-node/src/server.js | 8 ++++ packages/adapter-vercel/src/entry.js | 7 ++++ packages/kit/src/core/adapt/prerender.js | 1 + packages/kit/src/core/dev/index.js | 1 + packages/kit/src/core/node-fetch-global.js | 7 ++++ packages/kit/src/core/start/index.js | 1 + .../kit/src/runtime/server/page/load_node.js | 9 +---- pnpm-lock.yaml | 3 +- 14 files changed, 64 insertions(+), 43 deletions(-) create mode 100644 .changeset/gorgeous-hounds-peel.md create mode 100644 packages/kit/src/core/node-fetch-global.js diff --git a/.changeset/gorgeous-hounds-peel.md b/.changeset/gorgeous-hounds-peel.md new file mode 100644 index 000000000000..548f4ba3718e --- /dev/null +++ b/.changeset/gorgeous-hounds-peel.md @@ -0,0 +1,8 @@ +--- +'@sveltejs/adapter-netlify': patch +'@sveltejs/adapter-node': patch +'@sveltejs/adapter-vercel': patch +'@sveltejs/kit': patch +--- + +Move server-side fetch to adapters instead of build step diff --git a/examples/hn.svelte.dev/src/routes/[list]/rss.js b/examples/hn.svelte.dev/src/routes/[list]/rss.js index 9ddf8c730705..77deb67b00cb 100644 --- a/examples/hn.svelte.dev/src/routes/[list]/rss.js +++ b/examples/hn.svelte.dev/src/routes/[list]/rss.js @@ -1,5 +1,3 @@ -import fetch from 'node-fetch'; - const render = (list, items) => ` @@ -11,30 +9,31 @@ const render = (list, items) => ` Svelte HN (${list}) https://hn.svelte.dev/${list}/1 - ${items.map(item => ` - - ${item.title}${item.domain ? ` (${item.domain})` : ''} - https://hn.svelte.dev/item/${item.id} - link / ` : '' - }comments - ]]> - ${new Date(item.time * 1000).toUTCString()} - - `).join('\n')} + ${items + .map( + (item) => ` + + ${item.title}${item.domain ? ` (${item.domain})` : ''} + https://hn.svelte.dev/item/${item.id} + link / ` : '' + }comments + ]]> + ${new Date(item.time * 1000).toUTCString()} + + ` + ) + .join('\n')} `; export function get(req, res) { - const list = ( - req.params.list === 'top' ? 'news' : - req.params.list === 'new' ? 'newest' : - req.params.list - ); + const list = + req.params.list === 'top' ? 'news' : req.params.list === 'new' ? 'newest' : req.params.list; fetch(`https://api.hnpwa.com/v0/${list}/1.json`) - .then(r => r.json()) - .then(items => { + .then((r) => r.json()) + .then((items) => { const feed = render(list, items); return { body: feed, diff --git a/examples/realworld.svelte.dev/package.json b/examples/realworld.svelte.dev/package.json index 7263e2afc5d8..21efae26c2d4 100644 --- a/examples/realworld.svelte.dev/package.json +++ b/examples/realworld.svelte.dev/package.json @@ -15,7 +15,6 @@ "svelte": "^3.35.0" }, "dependencies": { - "cookie": "^0.4.1", - "node-fetch": "^2.6.1" + "cookie": "^0.4.1" } } diff --git a/examples/realworld.svelte.dev/src/lib/api.js b/examples/realworld.svelte.dev/src/lib/api.js index 58b93be8dbd1..ca753107c676 100644 --- a/examples/realworld.svelte.dev/src/lib/api.js +++ b/examples/realworld.svelte.dev/src/lib/api.js @@ -12,11 +12,6 @@ async function send({ method, path, data, token }) { opts.headers['Authorization'] = `Token ${token}`; } - const fetch = - typeof window !== 'undefined' - ? window.fetch - : await import('node-fetch').then((mod) => mod.default); - return fetch(`${base}/${path}`, opts) .then((r) => r.text()) .then((json) => { diff --git a/examples/realworld.svelte.dev/svelte.config.cjs b/examples/realworld.svelte.dev/svelte.config.cjs index 4640ea244365..ae50a7e01970 100644 --- a/examples/realworld.svelte.dev/svelte.config.cjs +++ b/examples/realworld.svelte.dev/svelte.config.cjs @@ -8,12 +8,6 @@ module.exports = { adapter: node(), // hydrate the
element in src/app.html - target: '#svelte', - - vite: { - ssr: { - noExternal: ['node-fetch'] - } - } + target: '#svelte' } }; diff --git a/packages/adapter-netlify/files/render.js b/packages/adapter-netlify/files/render.js index d9e90a795432..ccc2a98ea51f 100644 --- a/packages/adapter-netlify/files/render.js +++ b/packages/adapter-netlify/files/render.js @@ -2,6 +2,13 @@ import { URLSearchParams } from 'url'; import { render } from './app.mjs'; // eslint-disable-line import/no-unresolved +import fetch, { Response, Request, Headers } from 'node-fetch'; + +// provide server-side fetch +globalThis.fetch = fetch; +globalThis.Response = Response; +globalThis.Request = Request; +globalThis.Headers = Headers; export async function handler(event) { const { diff --git a/packages/adapter-node/src/server.js b/packages/adapter-node/src/server.js index 8625689d09e7..e144d29d7eaf 100644 --- a/packages/adapter-node/src/server.js +++ b/packages/adapter-node/src/server.js @@ -6,6 +6,14 @@ import sirv from 'sirv'; import { URL, fileURLToPath } from 'url'; // eslint-disable-next-line import/no-unresolved import { get_body } from '@sveltejs/kit/http'; +import fetch, { Response, Request, Headers } from 'node-fetch'; + +// provide server-side fetch +globalThis.fetch = fetch; +globalThis.Response = Response; +globalThis.Request = Request; +globalThis.Headers = Headers; + // App is a dynamic file built from the application layer. const __dirname = dirname(fileURLToPath(import.meta.url)); diff --git a/packages/adapter-vercel/src/entry.js b/packages/adapter-vercel/src/entry.js index 5af07aa6a0b3..72d4158dcf8a 100644 --- a/packages/adapter-vercel/src/entry.js +++ b/packages/adapter-vercel/src/entry.js @@ -1,6 +1,13 @@ import { URL } from 'url'; // eslint-disable-next-line import/no-unresolved import { get_body } from '@sveltejs/kit/http'; +import fetch, { Response, Request, Headers } from 'node-fetch'; + +// provide server-side fetch +globalThis.fetch = fetch; +globalThis.Response = Response; +globalThis.Request = Request; +globalThis.Headers = Headers; export default async (req, res) => { const { pathname, searchParams } = new URL(req.url || '', 'http://localhost'); diff --git a/packages/kit/src/core/adapt/prerender.js b/packages/kit/src/core/adapt/prerender.js index daba3491e6c9..8a66dd4c4aff 100644 --- a/packages/kit/src/core/adapt/prerender.js +++ b/packages/kit/src/core/adapt/prerender.js @@ -2,6 +2,7 @@ import { readFileSync, writeFileSync } from 'fs'; import { dirname, join, resolve as resolve_path } from 'path'; import { parse, pathToFileURL, resolve } from 'url'; import { mkdirp } from '../filesystem/index.js'; +import '../node-fetch-global.js'; /** @param {string} html */ function clean_html(html) { diff --git a/packages/kit/src/core/dev/index.js b/packages/kit/src/core/dev/index.js index 6b16cd4ba8fc..bf91715cfe46 100644 --- a/packages/kit/src/core/dev/index.js +++ b/packages/kit/src/core/dev/index.js @@ -14,6 +14,7 @@ import { get_body } from '../http/index.js'; import { copy_assets } from '../utils.js'; import svelte from '@sveltejs/vite-plugin-svelte'; import { get_server } from '../server/index.js'; +import '../node-fetch-global.js'; /** @typedef {{ cwd?: string, port: number, host: string, https: boolean, config: import('types/config').ValidatedConfig }} Options */ /** @typedef {import('types/internal').SSRComponent} SSRComponent */ diff --git a/packages/kit/src/core/node-fetch-global.js b/packages/kit/src/core/node-fetch-global.js new file mode 100644 index 000000000000..d0271ba0000e --- /dev/null +++ b/packages/kit/src/core/node-fetch-global.js @@ -0,0 +1,7 @@ +// @ts-nocheck +import fetch, { Response, Request, Headers } from 'node-fetch'; + +globalThis.fetch = fetch; +globalThis.Response = Response; +globalThis.Request = Request; +globalThis.Headers = Headers; diff --git a/packages/kit/src/core/start/index.js b/packages/kit/src/core/start/index.js index 01df0f66f704..4cc530f4cf8e 100644 --- a/packages/kit/src/core/start/index.js +++ b/packages/kit/src/core/start/index.js @@ -4,6 +4,7 @@ import sirv from 'sirv'; import { get_body } from '../http/index.js'; import { join, resolve } from 'path'; import { get_server } from '../server/index.js'; +import '../node-fetch-global.js'; /** @param {string} dir */ const mutable = (dir) => diff --git a/packages/kit/src/runtime/server/page/load_node.js b/packages/kit/src/runtime/server/page/load_node.js index 6fe2286502eb..c151d31d9bca 100644 --- a/packages/kit/src/runtime/server/page/load_node.js +++ b/packages/kit/src/runtime/server/page/load_node.js @@ -1,4 +1,3 @@ -import fetch, { Response } from 'node-fetch'; import { parse, resolve } from 'url'; import { normalize } from '../../load.js'; import { ssr } from '../index.js'; @@ -61,7 +60,6 @@ export async function load_node({ * @param {RequestInfo} resource * @param {RequestInit} opts */ - // @ts-ignore mismatch between client fetch and node-fetch fetch: async (resource, opts = {}) => { /** @type {string} */ let url; @@ -98,10 +96,7 @@ export async function load_node({ if (parsed.protocol) { // external fetch - response = await fetch( - parsed.href, - /** @type {import('node-fetch').RequestInit} */ (opts) - ); + response = await fetch(parsed.href, /** @type {RequestInit} */ (opts)); } else { // otherwise we're dealing with an internal fetch const resolved = resolve(request.path, parsed.pathname); @@ -127,7 +122,7 @@ export async function load_node({ // TODO we need to know what protocol to use response = await fetch( `http://${page.host}/${asset.file}`, - /** @type {import('node-fetch').RequestInit} */ (opts) + /** @type {RequestInit} */ (opts) ); } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e736003a2815..8bc895f2ae42 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -56,11 +56,9 @@ importers: '@sveltejs/kit': workspace:* cookie: ^0.4.1 marked: ^2.0.1 - node-fetch: ^2.6.1 svelte: ^3.35.0 dependencies: cookie: 0.4.1 - node-fetch: 2.6.1 devDependencies: '@sveltejs/adapter-node': link:../../packages/adapter-node '@sveltejs/kit': link:../../packages/kit @@ -2511,6 +2509,7 @@ packages: /node-fetch/2.6.1: resolution: {integrity: sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==} engines: {node: 4.x || >=6.0.0} + dev: true /node-fetch/3.0.0-beta.9: resolution: {integrity: sha512-RdbZCEynH2tH46+tj0ua9caUHVWrd/RHnRfvly2EVdqGmI3ndS1Vn/xjm5KuGejDt2RNDQsVRLPNd2QPwcewVg==}