Open henryoliver opened 6 years ago
@henryoliver yes I'd like to implement http2 by default, but there were issues implementing response modifications and other vital features that Browsersync uses.
it could be the case that this is no longer a problem, so I will address this asap đź‘Ť
Thank you @shakyShane ! I'm a fan of BrowserSync and had been using it in many projects. Great job guys!
@shakyShane just checking, any update on the http2 implementation?
Thanks!
I have a few questions about this:
in this comment on nodejs/http2 it is explained that built-ins always take precedence over installed modules—and the official http2 built-in is now called. http2
. So I find, for example, running node 9.x, regardless of whether I have molnarg's node-http http2
module installed, if I require('http2')
I get the native (built-in) one—with the attendant warning about http2 being an "experimental module". So already resolving the right module is one issue;
another potential issue with the httpModule
option as documented is the fact that it's meant to accept a string module name. This is not usable by tools that integrate browser-sync and are installed globally and not locally, because the module won't be found, as it's installed with the global one but the local node_modules
directory will be searched. (This sort of use-case is the reason AFAIK that webpack for example, allows the search directories for 'loaders' to be configured);
but finally, since I was hacking around anyway trying to solve this for my own tool which integrates browser-sync, is installed globally, and where I run node 9.x, I ended up with the following solution to make sure the module was found and that it was molnarg's and not the native one...it seems to work; do you see any problem with this? Am I missing or misunderstanding something about how browser-sync assembles and configures things?
EDIT: code below updated to use browserify's implementation of resolve
.
const requireResolve = require('resolve');
// get molnarg's http2 module
const http2Module = require(requireResolve.sync('http2', { basedir: process.cwd() }));
bsync.init({
/*...other options...*/
httpModule: http2Module,
https: true,
}, cb);
@shakyShane any news on Node's built-in HTTP2 support? The LTS release v10 is out so it's not in experimental mode anymore.
I'd like to point out as I implied in my comment above: the native http2
module is actually being loaded if you are on a recent version of Node and specify { httpModule: 'http2' }
in the options.
As of—at latest—Node 9.x, require.resolve()
which is what browser-sync is using internally will resolve to the native http2
module.
The workaround is to use the resolve
package which mimic's the original module resolution behavior. @shakyShane can you confirm, whether BS is actually compatible with native http2
now or not? If not, maybe the docs should add this workaround...
// Node v 9.x+
const resolve = require('resolve');
resolve.sync('http2') // will resolve the molnarg http2 module if you have it installed
require.resolve('http2') // will always resolve the native http2 module
I am trying to get browsersync to load in http2.0. Browser sync runs with no issues, but I when I try to access the app:
$ curl -I https://foo-demo.com
curl: (35) error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
I don't have this issue with https and http 1, only http 2 and https. Anyone know what is wrong?
develop /home/one/gitlab/sp6-client # node -v
v10.16.1
develop /home/one/gitlab/sp6-client # browser-sync --version
2.26.7
const express = require('express');
const app = express();
const resolve = require('resolve');
const http2 = require.resolve('http2');
const historyApiFallback = require('connect-history-api-fallback');
const httpProxy = require('http-proxy');
const path = require('path');
const bs = require('browser-sync').create();
const proxyBackEnd = httpProxy.createProxyServer({
target: 'http://127.0.0.1:5901/'
});
const proxyMiddleware = function(req, res, next) {
if (
req.url.match(/\WV1\W/)
|| req.url.match(/\Wv1\W/)
) {
try {
proxyBackEnd.web(req, res);
} catch(e) {
console.log(e);
}
} else {
next();
}
};
app.use(historyApiFallback());
bs.init({
server: true,
httpModule: http2,
baseDir: ['/'],
notify: false,
"files": [
'index.*',
'src/*',
'src/css/*.css',
'src/**/*',
'src/**/**/*',
'src/**/**/**/*'
],
middleware: [proxyMiddleware, historyApiFallback(), app],
https: {
key: "work-ssl/ssl/private-key.pem",
cert: "work-ssl/ssl/certificate.pem",
ca: "work-ssl/ssl/ca.pem"
},
port: 443,
ui: {
port: 3075,
},
});
I'm not sure if you can use http2/https with a proxying setup 🤷‍♂
@lunelson Thank you for the reply. I also ran it without the proxy at but still hitting the issue. I am wondering if it has to do with the browsersync version? Maybe some kind of regression in the 2.26.7? Do you know of a version that works for sure with http2?
I'm using 2.26.7
actually, but in a different kind of setup, not involving a second server, just letting browsersync serve (which uses connect
internally)
We have the same issue as @dman777 w/ 2.26.7
. When trying to run browsersync with HTTPS and HTTP/2 in a proxy set-up we get an ERR_SSL_PROTOCOL_ERROR
in Chrome and a PR_END_OF_FILE_ERROR
in Firefox.
@lunelson - did you get anywhere with this? I'm having the same issue with v2.27.5 on node 10. Documentation suggests everything works with:
// First run: npm install browser-sync http2
const bs = require('browser-sync').create();
bs.init({
server: './app',
httpModule: 'http2',
https: true
});
but it just doesn't work. Tried 'requiring in' http2 as per @dman777 suggestion above but no joy. Not running as a proxy, browserSync is hosting.
Super frustrating.
I struggled with this too.
I think the problem might be that browser-sync doesn't really support https with http2.
In getHttpModule
we see that if the httpModule
option is not specified then we'll return either the http
or https
module:
https://github.com/BrowserSync/browser-sync/blob/764a437c9b23484b94b060aac2827d53eeeeb838/packages/browser-sync/lib/server/utils.js#L104-L125
Both of these modules have a createServer
method, which is called by getServer
:
https://github.com/BrowserSync/browser-sync/blob/764a437c9b23484b94b060aac2827d53eeeeb838/packages/browser-sync/lib/server/utils.js#L82-L103
But there isn't a separate module module for 'http2s'; the native http2
module has separate createServer
and createSecureServer
methods:
https://github.com/nodejs/node/blob/7ca38f05a023666274569343f128c5aed81599f3/lib/internal/http2/core.js#L3304-L3314
but browser-sync never uses the createSecureServer
method.
I hacked-around this via:
const http2 = require('http2');
http2.createServer = http2.createSecureServer;
which got http2 working in browser-sync (along with the aforementioned config options:
https: true,
httpModule: 'http2',
)
@jfstephe it's been a long time since I used this but back then the solutions I outlined above did work: the non-native http2 module was compatible with BS, the trick was getting that one instead of the native one, since they had the same name
Interesting... is there a way to get the non native http2 module?
@lunelson thanks for responding. I had missed the 'molnarg http2' bit in your comment above (doh!). I've got that installed now but still no joy. I can't see that it's loading that module. Seems to just be using the default.
PS I'm actually running on node 10, in case that affects anything?!
@jfstephe my solution from back then probably depends on the specific versions of the resolve
and http2
packages at the time. NOTE that @dman777 is using require.resolve
in his code above; but this will get the native module not the 3rd party one. You need resolve.sync
from the resolve
package. OTOH @Andrew-Bx 's insight about createSecureServer
vs createServer
looks like a better fix if it works
Issue details
Please update browser-sync so it no longer seeks for a third-party node module when you set
httpModule: 'http2'
, but instead uses the node native one.Please specify which version of Browsersync, node and npm you're running
Affected platforms
Browsersync use-case
If CLI, please paste the entire command below
node ./.tasks/browsersync.js
for all other use-cases, (gulp, grunt etc), please show us exactly how you're using Browsersync