-
-
Notifications
You must be signed in to change notification settings - Fork 104
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
Advertise Browser Support #14
Comments
We could do it if someone is willing to help me setup automated browser testing (because otherwise it's just too easy to accidentally break browser support). I just have never setup browser testing before. |
I believe we had something setup internally for this, probably with Sauce Labs, I will ask our QA lead if he has any suggestions and post back. Really I am just glad to hear that you are interested in this being a "supported feature" of the module. I am going to write a push-state router implementation wrapping this module, and didn't want to base my stuff on something that might not be supported in the long run. |
No problem. There are modules that are definitively Node.js-specific, and others (like this) that are basically neutral (that don't intend to not work in browsers, but it's not the author's primary concern). If I can set it up so I get automated browser tests, then I'll know when a change breaks and can just make it not break, thus providing support :) |
I'm curious, what it can be used for in browser environment? Some kind of a single-page app? |
@rlidwka Yeah, we are doing an isomorphic app. Basically I am making a var index = require('./handlers/index'),
foo = require('./handlers/foo');
module.exports = function(router) {
router.get('/', index);
router.get('/foo/:bar', foo);
}; Where We are using React for rendering and a wrapper around XHR/Request or data loading. It enables almost all of our modules to work on both the server and the client. |
For backstory: Our last application was an Angular app with a Go backend. One of the most common bugs we had was weird behavior because we forgot to define all the proper routes in both Go and javascript. This was both a consequence of our architecture (multiple angular apps on a single domain) and having the routes duplicated. So this time around we really want to avoid the duplicated route issue. |
Ok, so going more deeply into the browser testing I found that // Was:
router.__proto__ = this
// Now:
for (var i in this) {
router[i] = this[i];
} Also, it looks like you could get IE9 support with two polyfills, Anyway, I can look at putting together a PR for that if the change seem fine to you all. As for the automation, Sauce Labs has free accounts for OS projects, so if you, @dougwilson, want to set one up I could also do a PR for that integration. |
I would rather find a
Sounds good to me. |
To expand on this, what I mean is we can just replace that with a call to |
Yeah, great point. I was unsure of that because of the exact thing you pointed out. I will look at doing that first thing tomorrow morning. Also, if you are interested, here is the progress I made today. I still have quite a bit of work to do for the popstate handler and coming up with a good So thanks for making my dreams come true! I really always wanted to be able to do isomorphic apps, this is the first time I am actually able to make it happen. |
Does anyone happen to know of a good polyfill for |
Polyfill can be the following for our purposes: Object.setPrototypeOf = { __proto__: [] } instanceof Array
? function setPrototypeOf(obj, prototype) { obj.__proto__ = prototype }
: function mixinProperties(obj, prototype) { for (var prop in prototype) { obj[prop] = prototype[prop] } } |
Apparently |
MDN certainly has some conflicting information on this subject. Last thing to consider here is avoiding the pollution of the global namespace. I threw together a little npm module to avoid that polution, if it looks good to you I will put together a PR using this module. |
Link to module :)? |
HAHA, yeah that would help! https://github.com/wesleytodd/setprototypeof |
Hey! I'm planning on using this module for the new recommended routing library for DerbyJS (http://derbyjs.com/). Everything else in the framework (including the current router based on older Express code) supports IE 9+. @wesleytodd's recommendation for falling back to property mixins looks like the best solution given the current API. Could we get it merged in? Looks like
could simply be:
Agree? |
I don't agree; the As far as this whole thing, I can merge in, but not until I can actually test it (i.e. I need tests that fail if the changes are missing). Without testing, nothing is guaranteed and everything will just randomly break in the future. If someone can provide god instructions on how I can setup a browser CI for this project, that's all I'm waiting for. |
It isn't really a polyfill in the current implementation, since it is a function that called Could of course write a true polyfill pretty easily, but it would be more code and slower. |
That's irrelevent; it's a simple |
Whatever the solutions we end on are, the real problem is that it is not supported, officially supported, until we have automated tests. Do you have a good setup in derby? If so can you setup something similar here? |
We set something up with testling, but that has broken and haven't heard anything about James fixing it. Will probably switch to Sauce Labs, which is the only other good option of which I'm aware. For now, we've been manually running the tests in VMs. Microsoft makes it free and relatively easy to download different versions of Windows for testing at least: https://www.modern.ie/en-us/virtualization-tools#downloads Re: setImmediate, you could make it generic:
Or https://github.com/YuzuJS/setImmediate if you want to actually polyfill it. Alternatively, how about removing this altogether, since it is only needed in Node <= 0.8, which is pretty old at this point. The Express version of this is calling setImmediately directly at the moment: https://github.com/strongloop/express/blob/master/lib/router/index.js#L188 If people want to polyfill it, they can always include the module above and polyfill it themselves. |
Um, telling me to drop support for Node.js 0.8 is the same as me saying I won't support IE < 9. You're not really starting off great asking me to support old browsers and then saying I shouldn't support old Node.js versions... |
Sure, then people can include |
Just commenting to say the generic code looks more like: var defer = typeof setImmediate === 'function'
? setImmediate
: function(fn) {
var args = Array.prototype.slice.call(arguments, 1)
process.nextTick(function() {
fn.apply(null, args)
})
} But since it's only used in a single place, I don't see why it couldn't be a function that just accepts two arguments? It's not a proper polyfill, but we don't need one for the only use of it. |
Regardless of what is here: my offer is still out. I just need to figure out (or someone can help me, which would get it done way faster) testing modules on web browsers in a CI and then I'll pick away and casting the widest browser support I can. I just need help setting up web testing on a CI. |
@wesleytodd re req/res abstraction, we're mocking these in sails for the purpose of socket.io requests. That code is definitely not browser compatible but might be useful if you need a list of properties on req/res you need to mock |
https://github.com/wesleytodd/nighthawk/blob/master/lib/request.js That is what im doing right now. But link up yours so I can see what I am mssing! |
Actually, maybe we can see about abstracting it out so we have something to share. I can take a look at that this weekend if you think its possiable. |
Separate from the issue of old browser support, my understanding is that Personally, we just avoid use of |
Yes, you are correct, and shimming the global method does solve any concerns about IE 8 compatibility. Just wanted to note the performance consideration since you mentioned the idea of banning Personally, I've found this method good to avoid altogether, primarily because it is easier to ask people to avoid things wholesale than to ask for contributors to have good judgement about using certain things only when they are not performance critical. |
I agree. I avoid |
@wesleytodd definitely-- although I think @dougwilson should be involved in this too, esp. re http2 Here's the function we use to build the virtual request object in Sails core: https://github.com/balderdashy/sails/blob/master/lib/router/req.js Here's an example of building the virtual request then squirting it through some middleware (Basically incoming socket.io messages do this): And finally the usage that kicks the whole thing off (btw this is nothing special, and I have no particular attachment to this usage; I'm just linking to it for context-- basically this method ends up triggerring the code that builds the virtual request which I linked to above.): https://github.com/balderdashy/sails/blob/master/test/unit/virtual-request-interpreter.test.js#L12 and the implementation of |
@wesleytodd Hopefully we can simplify all that ^^ craziness! As is, it works with a lot of middleware out of the box (everything I've tried including the middleware being used there in core). I'm sure there is probably a significant subset of middleware that won't work with it though. Ideally we get to where we can replace these mocks with some kind of abstractions; i.e. "request emitter" and "response receiver". |
@mikermcneil thanks! It will take me a bit to go through that, but the only thing I noticed right off is that you are using express 3 compatible api (I know that is what sails uses). Personally I would rather not do that, and go for express 4/5 support. @dougwilson Correct me if I am wrong, but the express req/res extend directly from the node classes. Seems like we might not need all of that, especially since I need this in the browser where most of it doesn't make sense to have. Is there a new pillarjs repo for the req/res stuff moving forward? If not maybe we could make one? Lastly, I was working today on getting my test running with sauce labs like mentioned above. I made some progress, but the modules I was using did not seem to fully work. I have an issue open on one repo and will hopefully be able to get some help, but regardless, progress is being made :) |
@wesleytodd @dougwilson How about the router is totally independent of req/res and simply has a |
@felixfbecker So from my understanding that is was is basically happening now. https://github.com/wesleytodd/nighthawk/blob/master/lib/router.js#L204 Am I wrong? Or rather how is your idea different from those? |
I figured out the browser testing stuff. I tried to run the tests here on sauce labs and then realized they are totally not browser compatible. I see two options:
The bulk of the the tests are pretty tied into the existing server based setup, which technically isn't necessary because there is nothing specific about matching routes that needs an http server running. Most of the tests could just as easily use mock requests/responses. For example: it('should support array of paths', function (done) {
var cb = after(3, done)
var router = new Router()
var server = createServer(router)
router.all(['/foo', '/bar'], saw)
request(server)
.get('/')
.expect(404, cb)
request(server)
.get('/foo')
.expect(200, 'saw GET /foo', cb)
request(server)
.get('/bar')
.expect(200, 'saw GET /bar', cb)
}) The above could just as easily be written as (obviously missing some stuff, but just to illustrate the point): it('should support array of paths', function (done) {
var cb = after(3, done)
var router = new Router()
router.all(['/foo', '/bar'], saw)
var req = mockReq('/')
var res = mockRes()
router.handle(req, res)
assert(res.statusCode === 404)
var req = mockReq('/foo')
var res = mockRes()
router.handle(req, res)
assert(res.statusCode === 200)
var req = mockReq('/bar')
var res = mockRes()
router.handle(req, res)
assert(res.statusCode === 200)
}) Which do you all think is a better way to move forward? |
Hi, Personally I think it's a great idea, as far I've seen there are a couple of issues to make this happen:
Maybe I'm missing something, but this is what i've seen. I have no problem at all in working on this, in fact I can book one or two full time months to iron this out. @dougwilson feel free to contact me if you are interested |
Hey @eth0lo, Actually most of this work has been done. The title of the issue is "Advertise" support, not make it work. It already fully works and I am using it in multiple production applications. But to hit on your points:
|
The reason why I suggested the aforementioned strategy is because: Related to 1 For one everything that relates to this test, means that trying to bundle Also because Related to 3 With those changes in place this module could become agnostic of the environment, while the implementors stick to the req and res contracts. PS. I'm also using this in production already, just wanted to highlight what could be done to be I'm sorry if did not make myself clear before |
Hi @eth0lo, I'm not sure what you are saying is adding buffer to the build. The "auto head" feature you linked to is implemented with literally the following three lines: https://github.com/pillarjs/router/blob/master/lib/route.js#L103-L105 and I'm not clear how that would cause buffer to get bundled. |
Let me me double check that |
Hi @dougwilson, I'm really sorry, I got confused, you are right it's not auto headers it's the auto options when there's no handler associated with a route, in here For example removing buffer will decrease the bundle size around 38% for a gzip bundle |
This is the only line I can find that uses Line 698 in d3a598d
But again, I don't think this is an issue. The bundle is not large to begin with, and all of my apps use buffer for other purposes anyway so it would get included either way for me. I am sure it is pretty common to already use those built-ins if you are bundling modules from npm. |
@wesleytodd yes that's the only line. Actually when I posted the decreased size, what I did was changing that line for In the other hand you are saying that most people use buffer in the builds, actually from my experience is totally the oposite most of the people I know use browserify/webpack/rollup to bundle SPA style apps, which barely use buffer. BTW, I think this is getting super into details, how about we create a thread for browser support?, and there we discuss file sizes, browser specific stuff, and the migration of the tests, maybe after that we can create a list of stuff get done to properly support browsers as first citizen as node is. Disclaimer, I continued this thread, because I see more value in contributing to this project than forking it |
Digging in a bit more into the functionality here, it is clear that this will never be used in the browser, opened #44 to discuss. |
Cleaning up old issues. |
I am interested to know if you all think it is worth mentioning that this module is compatible with browsers. I threw together an example of using this module in front-end code, and it works perfectly fine.
It is a big deal to say that the module is "Browser Compatible" because of the support issues, but the current implementation works in Chrome & FF (which is all I tested). And after reading most of the code I don't see anything that will clearly break it in other browsers (at least with the required polyfills).
The text was updated successfully, but these errors were encountered: