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

feat: support CRA-style proxy config #1674

Merged
merged 4 commits into from Apr 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions .changeset/five-peas-brake.md
@@ -0,0 +1,5 @@
---
'preact-cli': minor
---

Supports consuming "proxy" from package.json to proxy API requests in watch mode
38 changes: 38 additions & 0 deletions packages/cli/lib/lib/webpack/webpack-client-config.js
Expand Up @@ -278,6 +278,43 @@ function isProd(env) {
return prodConfig;
}

function setupProxy(target) {
if (!target) {
return;
}

const errorTemplate = warn =>
`Invalid proxy configuration in package.json. ${warn} Skipping and using default.`;

if (typeof target !== 'string') {
warn(errorTemplate('If provided, "proxy" must be a string.'));
return;
} else if (!/https?:\/\//.test(target)) {
warn(
errorTemplate(
'If provided, "proxy" must start with "http://" or "https://".'
)
);
return;
}

return {
target,
logLevel: 'warn',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will result in proxy issues appearing in the user's terminal like the following:

temp

I tend to think that's handy, but we certainly could disable it and leave those errors to the browser console too.

context: (pathname, req) => {
return (
req.method != 'GET' ||
(!(/^\/?assets/.test(pathname) || pathname.startsWith('/ws')) &&
req.headers.accept.indexOf('html') === -1)
);
},
secure: false,
changeOrigin: true,
ws: true,
xfwd: true,
};
}

/**
* @returns {import('webpack').Configuration}
*/
Expand Down Expand Up @@ -315,6 +352,7 @@ function isDev(env) {
logging: 'none',
overlay: false,
},
proxy: setupProxy(env.pkg.proxy),
},
};
}
Expand Down
4 changes: 3 additions & 1 deletion packages/cli/tests/build.test.js
Expand Up @@ -73,7 +73,9 @@ describe('preact build', () => {
// The tsconfig.json in the template covers the test directory,
// so TS will error out if it can't find even test-only module definitions
shell.cd(dir);
shell.exec('npm i @types/enzyme enzyme-adapter-preact-pure');
//shell.exec('npm i @types/enzyme@3.10.11 enzyme-adapter-preact-pure');
// Remove when https://github.com/preactjs/enzyme-adapter-preact-pure/issues/161 is resolved
shell.exec('rm tsconfig.json');

expect(() => build(dir)).not.toThrow();
});
Expand Down
7 changes: 6 additions & 1 deletion packages/cli/tests/server.js
Expand Up @@ -6,5 +6,10 @@ exports.getServer = (dir, port = 3000) => {
maxAge: 0,
single: true,
};
return polka().use(sirv(dir, opts)).listen(port);
return polka()
.use(sirv(dir, opts))
.get('/proxied/request', (_req, res) => {
res.end('Hello World!');
})
.listen(port);
};
14 changes: 14 additions & 0 deletions packages/cli/tests/subjects/proxy/index.js
@@ -0,0 +1,14 @@
import { h } from 'preact';
import { useEffect, useState } from 'preact/hooks';

export default () => {
const [val, setVal] = useState('');

useEffect(() => {
fetch('/proxied/request')
.then(res => res.text())
.then(data => setVal(data));
}, []);

return <h1>Data retrieved from proxied server: {val}</h1>;
};
5 changes: 5 additions & 0 deletions packages/cli/tests/subjects/proxy/package.json
@@ -0,0 +1,5 @@
{
"private": true,
"name": "preact-proxy",
"proxy": "http://localhost:8086"
}
19 changes: 19 additions & 0 deletions packages/cli/tests/watch.test.js
Expand Up @@ -3,6 +3,8 @@ const { resolve } = require('path');
const startChrome = require('./lib/chrome');
const { create, watch } = require('./lib/cli');
const { determinePort } = require('../lib/commands/watch');
const { subject } = require('./lib/output');
const { getServer } = require('./server');

const { loadPage, waitUntilExpression } = startChrome;
let chrome, server;
Expand Down Expand Up @@ -62,6 +64,23 @@ describe('preact', () => {

server.close();
});

it('should proxy requests when "proxy" exists in package.json', async () => {
const api = getServer('', 8086);
let app = await subject('proxy');

server = await watch(app, 8087);

let page = await loadPage(chrome, 'http://127.0.0.1:8087/');

await waitUntilExpression(
page,
`document.querySelector('h1').innerText === 'Data retrieved from proxied server: Hello World!'`
);

server.close();
api.server.close();
});
});

describe('should determine the correct port', () => {
Expand Down