From 5901ac5a0888c6ab5773996c5e7ae73c76838a76 Mon Sep 17 00:00:00 2001 From: Alex MacArthur Date: Mon, 12 Sep 2022 21:42:34 -0500 Subject: [PATCH] Switch to different HTTP library for more reliable fetching. --- package-lock.json | 137 +++++++++++++++------------------------------- package.json | 16 +++--- src/index.test.ts | 21 ++++--- src/index.ts | 64 ++++++++++++---------- tsconfig.json | 10 ++-- vite.config.js | 13 +---- 6 files changed, 108 insertions(+), 153 deletions(-) diff --git a/package-lock.json b/package-lock.json index e790f32..36f76e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.1", "license": "MIT", "dependencies": { - "isomorphic-fetch": "^3.0.0", + "axios": "^0.27.2", "jsdom": "^20.0.0" }, "devDependencies": { @@ -158,6 +158,15 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, + "node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", @@ -752,6 +761,25 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "node_modules/follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -870,15 +898,6 @@ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" }, - "node_modules/isomorphic-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", - "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", - "dependencies": { - "node-fetch": "^2.6.1", - "whatwg-fetch": "^3.4.1" - } - }, "node_modules/jsdom": { "version": "20.0.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.0.tgz", @@ -1024,25 +1043,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/nwsapi": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", @@ -1299,11 +1299,6 @@ "node": ">=6" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, "node_modules/type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -1462,11 +1457,6 @@ "node": ">=12" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, "node_modules/whatwg-encoding": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", @@ -1478,11 +1468,6 @@ "node": ">=12" } }, - "node_modules/whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" - }, "node_modules/whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", @@ -1491,15 +1476,6 @@ "node": ">=12" } }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -1649,6 +1625,15 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", @@ -1990,6 +1975,11 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" + }, "form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -2077,15 +2067,6 @@ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" }, - "isomorphic-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", - "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", - "requires": { - "node-fetch": "^2.6.1", - "whatwg-fetch": "^3.4.1" - } - }, "jsdom": { "version": "20.0.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.0.tgz", @@ -2192,14 +2173,6 @@ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, "nwsapi": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", @@ -2380,11 +2353,6 @@ "url-parse": "^1.5.3" } }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -2467,11 +2435,6 @@ "xml-name-validator": "^4.0.0" } }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, "whatwg-encoding": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", @@ -2480,25 +2443,11 @@ "iconv-lite": "0.6.3" } }, - "whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" - }, "whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==" }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", diff --git a/package.json b/package.json index 31f9606..d12eccd 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,21 @@ { "name": "vite-plugin-proxy-page", - "version": "0.0.1", + "version": "0.0.2", "license": "MIT", "author": "Alex MacArthur (https://macarthur.me)", - "homepage": "https://github.com/alexmacarthur/vite-plugin-proxy-page", + "homepage": "https://macarthur.me/posts/project-local-spa-onto-production-page", "scripts": { "dev": "vite", "test": "vitest run", "test:watch": "vitest", - "build": "vite build && tsc", + "build": "rm -rf dist && npm run build:esm && npm run build:cjs", + "build:esm": "tsc --module es2015 --outDir dist/esm", + "build:cjs": "tsc --module commonjs --outDir dist/cjs", "format": "prettier --write \"./**/*.{md,js,ts}\"" }, - "main": "dist/index.umd.js", - "module": "dist/index.es.js", - "types": "dist/index.d.ts", + "main": "dist/cjs/index.js", + "module": "dist/esm/index.js", + "types": "dist/types/index.d.ts", "keywords": [ "vite-plugin", "proxy", @@ -28,7 +30,7 @@ "vitest": "^0.23.2" }, "dependencies": { - "isomorphic-fetch": "^3.0.0", + "axios": "^0.27.2", "jsdom": "^20.0.0" } } diff --git a/src/index.test.ts b/src/index.test.ts index 1f5ae40..df1c2ca 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,5 +1,6 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { proxyPage, htmlCache } from "./index"; +import axios from "axios"; const url = "https://vite-proxy-demo.netlify.app/some-page"; @@ -10,27 +11,31 @@ beforeEach(() => { describe("caching", () => { it("performs fresh transformation when cache is empty", async () => { - const fetchSpy = vi.spyOn(globalThis, "fetch"); + const requestSpy = vi.spyOn(axios, "get"); - await proxyPage({ + const plugin = proxyPage({ localEntryPoint: "local-dev.tsx", remoteUrl: url, - }).transformIndexHtml(); + }); - expect(fetchSpy).toHaveBeenCalledTimes(1); + await plugin.transformIndexHtml(""); + + expect(requestSpy).toHaveBeenCalledTimes(1); expect(htmlCache.get(url)).not.toBe(undefined); }); it("uses cache when it's filled", async () => { - const fetchSpy = vi.spyOn(globalThis, "fetch"); + const requestSpy = vi.spyOn(axios, "get"); htmlCache.set(url, ""); - await proxyPage({ + const plugin = proxyPage({ localEntryPoint: "local-dev.tsx", remoteUrl: url, - }).transformIndexHtml(); + }); + + await plugin.transformIndexHtml(""); - expect(fetchSpy).toHaveBeenCalledTimes(0); + expect(requestSpy).toHaveBeenCalledTimes(0); }); }); diff --git a/src/index.ts b/src/index.ts index 879eec5..2b2c03f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ -import "isomorphic-fetch"; +import { Plugin } from "vite"; import transform from "./transform"; +import axios from "axios"; export interface RootNode { prependTo?: string; @@ -13,6 +14,10 @@ export interface ProxyPageOptions { rootNode?: RootNode; } +export interface ProxyPlugin extends Plugin { + transformIndexHtml: (html: string) => Promise; +} + export const htmlCache = new Map(); export const proxyPage = ({ @@ -20,30 +25,33 @@ export const proxyPage = ({ remoteEntryPoint, remoteUrl, rootNode, -}: ProxyPageOptions) => ({ - name: "vite-plugin-proxy-page", - - apply: "serve", - - async transformIndexHtml() { - if (htmlCache.get(remoteUrl)) { - return htmlCache.get(remoteUrl); - } - - const html = await fetch(remoteUrl).then((r) => r.text()); - - const { origin } = new URL(remoteUrl); - - const transformedHtml = transform({ - html, - localEntryPoint, - remoteEntryPoint, - remoteHost: origin, - rootNode, - }); - - htmlCache.set(remoteUrl, transformedHtml); - - return transformedHtml; - }, -}); +}: ProxyPageOptions): ProxyPlugin => { + return { + name: "vite-plugin-proxy-page", + + apply: "serve", + + async transformIndexHtml(_html = ""): Promise { + if (htmlCache.get(remoteUrl)) { + return htmlCache.get(remoteUrl); + } + + const { origin } = new URL(remoteUrl); + const { data: html } = await axios.get(remoteUrl, { + responseType: "text", + }); + + const transformedHtml = transform({ + html, + localEntryPoint, + remoteEntryPoint, + remoteHost: origin, + rootNode, + }); + + htmlCache.set(remoteUrl, transformedHtml); + + return transformedHtml; + }, + }; +}; diff --git a/tsconfig.json b/tsconfig.json index 95d8cd5..75e5b63 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,23 +1,23 @@ { "compilerOptions": { "outDir": "dist", + "declaration": true, + "declarationDir": "./dist/types", "target": "ESNext", "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ESNext", "DOM"], + "module": "commonjs", + "lib": ["ESNext"], "moduleResolution": "Node", "strict": true, "sourceMap": true, "resolveJsonModule": true, "isolatedModules": true, "esModuleInterop": true, - "declaration": true, - "emitDeclarationOnly": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "skipLibCheck": true }, - "include": ["src"], + "include": ["src"], "exclude": ["src/fixtures/*"] } diff --git a/vite.config.js b/vite.config.js index 505e46f..3074120 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,25 +1,16 @@ import { defineConfig } from "vite"; -import path from "path"; import { proxyPage } from "./src/index"; export default defineConfig({ plugins: [ proxyPage({ localEntryPoint: "./sandbox/index.ts", - remoteUrl: "https://vite-proxy-demo.netlify.app/some-page", + remoteUrl: + "https://www.ramseysolutions.com/real-estate/moving-and-storage", rootNode: { id: "someId", prependTo: "main", }, }), ], - build: { - target: "esnext", - lib: { - entry: path.resolve(__dirname, "src/index.ts"), - name: "VitePluginProxyPage", - fileName: (format) => `index.${format}.js`, - formats: ["es", "umd"], - }, - }, });