Right now I have a tradicional (and huge) MVC back-end and an API (I'm not using Node.js). Assets = Gulp to concat+rev+uglify.
What would be the best approach to my pages where a lot of user interaction is needed? Using jQuery and handlebars seems ugly but I think I'll be overcomplicating things if I adopt an entire new stack (React, Babel JSX/ES6, Webpack, modules, hot-reload...) on top of what I already have.
I'm the single developer on this web app, I feel extremely productive on the back-end side but the front-end is driving me NUTS. Since it started making a good amount of money I quit my job a few months ago and it's my main income now.
I'm (literally) having nightmares about a JS bug I won't be able to solve since it's so many moving parts and I'm a back-end dev who doesn't have the time or patience to replace his entire front-end stack every 6 months.
If you want, try applying some of the ideas of the "modern" tools to Backbone: make a backbone view that has two models - one for data (aka React props) and one for view state (aka React state). Bind both model "change" events to your view's `render` method. It won't have the performance boost of React virtual DOM diffing - but you get some of the other design benefits.
I'm the sole developer on a "rails monolith" (254 tables, 540 models/classes, 4 years old), with enterprise-like architecture (ecommerce, event ticket sales, booking engine, access control, etc) and I'm positive the only way I'm able handle it all is because I stick to basic jquery.
My secrets:
- The rails-ujs adapter
- $(document).on('event', '.element', ..) is fantastic. Never debug events ever again
- selectize select's for "find or create" relationships
- cocoon gem for nested form relationships
- parsley for form validation (hooks into html5 validators)
- bootstrap 3
- datatables.net + following the pattern of ajax-datatables-rails (gem - separate classes for each table)
- a single javascript function that accepts a DOM element (body, a modal, section) and initializes all the elements the app knows of (selectize elements, date/time pickers, etc) inside that container
- above function is hooked into by bootstrap's 'bs.modal.shown, bs.modal.hide, tab's, cocoon's 'cocoon:after-insert', etc.
rake stats says: 33k LOC models, 8k LOC controllers, 23k Javascript (though this must be all plugins. I'd guess 3-6k lines of javascript, max)
Needless to say, I don't believe in the frontend javascript hype.
> - $(document).on('event', '.element', ..) is fantastic. Never debug events ever again
> - a single javascript function that accepts a DOM element (body, a modal, section) and initializes all the elements the app knows of (selectize elements, date/time pickers, etc) inside that container
Simple example:
$(document).on 'ajax:success', '.guest-form', ->
notify 'success', 'Guest updated.'
$(@).parents('.modal').modal 'hide'
$(document).ajaxError (event, jqxhr, settings, thrownError) ->
handle_ajax_error(event, jqxhr)
@handle_ajax_error = (error, xhr) ->
if xhr.status is 422
error = JSON.parse(xhr.responseText)['errors']
notify 'error', error
else if xhr.status is 500
notify 'error', 'Error communicating with the server. We have been notified.'
if xhr.status is 401
notify 'warning', 'Session has expired. Redirecting to login...'
window.location = '/login'
if xhr.status is 403
window.location = '/access-denied'
So if you load in content via AJAX (I do this a lot for table views of data and the user wants to see a single record), rather than go to a separate page, I do an ajax call, put the result into a Twitter bootstrap modal, show the modal, and when the bs.modal.shown event fires, that "single javascript function" with the modal as the parameter is called, and it initializes all the javascript needed for that particular DOM container.Example:
$(document).on 'shown.bs.modal', 'a[data-toggle="tab"]', (e) ->
$modal_body = $( $(e.target).attr('href') )
general_init $modal_body
The general_init function will initialize all my selectize elements (among other things) as such: general_init = ($container) ->
add_selectize $container.find('input.membership-plan-select'), $.extend(true, {}, Selects.MembershipPlanOptions)
So when writing forms, lets say to create a new "Event Ticket" I simply plop in a text field with a class of "guest-select" and I instantly have an AJAX powered search field to find/create a guest to assign that ticket to.But if you need something even more stable than React, I'm not sure there is a good option out there. I dislike Angular.js for a number of reasons (which I won't go into here). I've heard good things about Mithril, but it's MVC so as the app grows larger, you're likely to end up with the same problems you have with your current implementation.
Ironically, I'm currently considering a move to the exact stack you're considering (React, Babel JSX/ES6, Webpack...) and I find it better than everything else I've evaluated over the past year.
Thoughts?
I don't think its worth the time to really learn Angular or whatever is the current fad these days - quality of both the software and the documentation of JS frameworks is an afterthought to "getting an MVP ready to ship".
I'm not a ripening chamber for bananas, especially bananas with no papers.
Is like "mini-SPA's" on a few places that deal with too many data sources and would be a pain to make my users change screens.
I really enjoyed doing "one way binding" and some ideas around React though.
I'm not trying to push React (I'm still evaluating it myself), but that sounds like just the job for React components?
- jQuery (for small stuff)
- RequireJS (so that you don't have to load all at once)
- MomentJS (Date / Time management done right)
- AmplifyJS (Pub / Sub and localstorage)
I really like KnockoutJS. Easy to learn and it grows with you so that you don't have to complicate your app if not necessary.
Knockout.js is worth checking out. It can be picked up in a day or so, and can be integrated into existing sites easily.
I actually started down the road of learning Backbone/Marionette to work on an existing codebase, and I'm liking what I see overall. It offers models that can sync up to your backend easily, and adds much needed structure to handlebar templates and jQuery.
If you feel like using React, it looks like it would be quite easy to use Backbone models in the same way Flux implementations are used (basically a data store w/ events). I might try this down the road as I like React but want to avoid CommonJS/ES6 and whatever the Flux lib du jour is.
I am similar, writing the back end was easier ... front end not so much. I hated having JS bugs due to stupid typos and less than 100% code coverage in tests.
Switched to Typescript for the front end and things became much better. Doesn't have to be 'all or nothing' either, I still have some JS glue for interacting with some libraries and more dynamic bits, but generally everything is Typescript and feels much more solid.
FWIW the stack also heavily includes KnockoutJS, DataTables, Backbone's router & a smattering of JQuery plugins for this and that.