>My "thing I dont know as of 2018", just for good measure: How to build complex front-end applications without making a complete mess of things!
If you find anyone that truly knows the answer, please let us know :)
I'm sure plenty of people claim to, and many more will just claim that the mere concept is flawed so there's no point, and there are even more non-answers. But the actual problem is very difficult. I remember when AngularJS (the old Angular) first came out and it felt like we finally started having an idea of how to handle frontend after years of dissatisfaction with jQuery, Knockout, etc.. Then React, Polymer, Web Components, ES6, Webpack, Modules, TypeScript, Redux (and its Flux-based ancestors) and so, so much more hit and... it's mesmerizing.
I think React is the best option so far, it's still not 100% where it should be but it offers my favorite API and the essence of it is simple enough to fit in a tiny, minimal library if you want. It can be tricky here and there, but the way it encapsulates state is, for the most part, super predictable. I love the way you fold asynchronous streams into state and props using tools like create-subscription so that components don't have to fiddle around with confusing, long async chains.
For me, Polymer and Web Components were both huge misses - the promise of Web Components is still neat to this day, but I really don't think I would want to compose my application out of many Web Components, it just doesn't seem like the right tool for that job, it seems like a better tool for embedding or shared widgets. There's really a lot that can be said here w.r.t. Polymer and Web Components in general but I don't think any of it hasn't been said better so I'll leave it alone.
Angular 2+ do not do it for me. It is amazingly nice having so much out of the box unlike React, but at the same time I find myself constantly annoyed. The NgModule system feels like a relic of AngularJS. When it was standard to simply concatenate JavaScript files together and call it a bundle, this system made perfect sense. In the world of ES modules and Webpack, it's just a layer of needless complexity. The AOT compiler causes all sorts of shenanigans where valid, obvious JavaScript won't work. I don't really care for dependency injection, at least not the way its implemented in Angular. It does give you some neat tricks, but I am happier with my obvious, ugly code, thanks. Even disregarding modules and DI, I still don't like Angular. My favorite concept from React is that the tree of components is out of line of the DOM. In Angular the component is actually in the DOM. This usually only matters in a few cases, but when it does it's really annoying. Example would be CSS, or say, if you want a component to be a table row. The way event listeners work is not orthogonal between child elements and the so-called 'host' element due to this, as well, whereas in React you can just use HTML-style on event attributes since you are rendering all of the elements that end up in the DOM always. Angular's documentation frequently doesn't have example code showing you how to use things, which may actually be because the developers aren't sure - I've often tried to figure out how to use basic features only to find GitHub issues pointing out the severe limitations in them. Like, Angular Router - What if you want to compartmentalize some routes in a child module? You could of course just define a Routes[] variable somewhere and import it, but there is actually a RouterModule.forChild, so surely you can use that? No. You can only use that if you are using loadChildren, which uses lazy loading. Lazy loading is actually a PITA especially depending on how you have modules setup, and the AOT compiler once again does some truly confusing stuff. Like, you can fake loading something synchronously with loadChildren, but check out what you gotta do to make it work with the AOT compiler: https://github.com/angular/angular/issues/10958#issuecomment... - Nearly every interaction with Angular beyond trivialities end in multiple open GitHub issues that lead nowhere, and it's frustrated me like crazy. Angular also seems to like RxJS, a library I really want to love but can't seem to quite get there. It's very powerful, but I hate that to get the exact behavior I want I often end up with quite a long list of operators where the order can be important in subtle ways. It's easy to leak subscriptions in RxJS especially if you're new to it. Some things are hard to implement, like say if you wanted to implement some kind of feedback loop where the result goes back through. And worst of all, you tend to get RxJS subscriptions and subjects at the component level at Angular, meaning you've got to deal with these async values in rendering code, in logic code, etc. Which can cause RxJS to spread like a virus when all you wanted to do was pull some state in and combine it with some other state. And if you want change detection to work, there's even more rules you need to be careful about following...
I've yet to try Ember. I've looked at Vue.js but ultimately haven't been as drawn in.
...But even despite my preference for React, large apps are still super hard to structure, and many problems feel unsolved. Like saving and synchronizing state to a server. There's individual solutions to that problem, but none feel like they're 'perfect' across all of the domains you want them to be. GraphQL seems like it could be nice but so far I have been mystified by it in practice, and longing for better type-safety on both sides. React obviously is far from perfect, too, and because of its imperfections, you are going to want a lot of linting to prevent people from shooting themselves in the foot, especially if you are working on a team. I've never fully figured out unit and integration testing in React, last I checked the standard was to use Jest and JSdom and JSdom required native Node.JS modules and bla bla... needless to say, I was unsatisfied. Because unit test suites on JS apps tend to compile to one giant bundle, you have a harder time parallelizing work and doing coverage-based tests.
Organizing components? Smart components vs dumb components? Container components? High order components? Where to put the Redux reducers and actions and state? How to split your bundle? Whether or not to split your bundle? Webpack vs Rollup vs Parcel? I'm barely scratching the surface. Production frontend apps are insanely difficult and it's fragmented to all hell. I don't buy in super hard to the JS fatigue thing, but I do think we're very scatterbrained right now on how to build good frontend apps, and it seems like it's gonna take a while to fully collect our thoughts and figure out how things 'ought' to be done. Right now, it's really super all over the place.
So yeah... I think it's OK if you don't know how to write complex front-end apps without making a mess. I doubt you are alone even among the pioneers.