Upgrading from React 0.11.2 to 0.14.7 in 347 easy steps
manuel.bernhardt.io
manuel.bernhardt.io
>The real painful part of the process is caused by everything around React, including the build tools.
Can't agree with that more. I really like the way react works. It just makes sense and doesn't get in your way very often.
BUT it's incredibly frustrating dealing with npm dependency hell. Especially if you really are concerned about security and don't just trust that "someone else has probably made sure this code is safe, right?"
I just want to use something for longer than 6 months :(
I'm not sure where you're coming from with the "huge clusterfuck of json" comment, but where the source data comes from is quite cleanly separated from how it's rendered using React, with one major caveat I'll come back to in a minute.
React itself is essentially a tool for rendering templates but with a declarative programming style, plus one fundamental performance optimisation that makes that declarative style fast enough to use in practice, plus a small number of hooks to integrate quite flexibly with other parts of your code and to allow for further performance optimisation if you need it.
Of course, there is no magic and there are always trade-offs. Most visibly, like any declarative system, sometimes the costs are significant and you do need to give it a hand to get acceptable performance. This is where the caveat I mentioned comes in, because you'll find a lot of projects using React also wind up using immutable data structures of one kind or another to store their model state. That lets you do fast comparisons based on identity rather than deep equality to see whether relevant parts of your underlying model data have changed, and thus lets you bypass the whole re-rendering process in areas of your UI where nothing interesting has happened. There are a handful of knock-on effects in practice that you have to deal with sometimes as well.
The upside, of course, is that you get much the same advantages as any other declarative programming style: your rendering logic tends to be simpler, more concise, more amenable to analysis, and less subject to surprising interactions and edge cases than more traditional, imperative rendering code tends to be, and all of these become disproportionately greater advantages as the complexity of the rendering and/or the underlying data model grow.
Storing application state within a single immutable tree might be counter-intuitive but doesn't really make much difference to anything important. That data was going to be stored somewhere anyway, access is reasonably efficient in JS, and as you say, sometimes it has useful practical advantages.
One thing I would say is that nothing actually requires you to store all of your data in a single immutable tree like that. I've found some patterns tend to come up often when designing UIs with this sort of architecture, and in those patterns a small number of immutable data structures are used instead of one monolithic one.
For example, sometimes it's advantageous to have one structure that contains strictly the underlying persistent state that you'll ultimately store in some database on the back end. If you also need some supporting data derived from that first structure for presentation purposes, you can still create a second, also immutable structure, that is basically a clone of the first but then with the supplementary data added. Doing this sort of manipulation is usually reasonably efficient with Immutable.js because you basically have copy-on-write semantics for everything, and the logic for deriving the supplementary data tends to be easily tested.
It's made building my web apps front end fun again and bring in big changes is so much quicker than old school dom manipulation.
Took me a long time to become a believer, intuitively I rallied against frameworks, but React is amazing.
In fairness, plenty of people have long warned that recent trends in the JS ecosystem were unhealthy. It's always been possible to run useful modern tools like Browserify and SASS directly, without all the build systems and task runners and other such tools, and plenty of development teams do, and those teams don't run into NPM hell to the same extent.
Tons of NPM modules are small single functions with tests. NPM requires very little boilerplate to publish modules, so you get lots of small and focused (and hopefully composable) modules. Not every module is a megabyte+ one-stop kitchen-sink-containing toolkit that's mostly redundant with your other dependencies.
Though the linked article is specifically complaining about unmaintained tools in the sbt ecosystem. It doesn't appear he's using a build system using NPM modules.
I think you'd find the real problem is with the tendency by the maintainers to abandon a lot of these modules...
Like the author, I have something besides Javascript on the backend. In my case it's Python. Rather than use a Python-specific build system, however, I've had success using a Makefile as the top level build tool, which can directly call out to npm, pip, babel, uglify, sass, etc. There is no Gulp/Grunt/Broccoli/Webpack/Browserify in sight, and that makes me happy. I'm pretty sure Make will be around long after people have forgotten about Grunt.
I was trying to pull some dependencies a while ago and they were failing to build because at some point grunt decided to change the build file name.
I'd be usually fine with that except the only way these tools work is to install them globally so they can't coexhist even with themselves
Some of the tooling is so broken and awkward people got used to commit their /dist/ on github so at least I can skip bower grunt and all that and just get the minified file for many of libraries I need
This is not true, the node community just doesn't advertise it for some reason. You can run npm install a specific version of grunt-cli and run it with ./node_modules/.bin/grunt
I really hope not.
There is plenty to criticise about recent build tools for web projects. Many are absurdly over-engineered. Most have very short working lives. Almost all seem to have a crazy number of dependencies of their own drawn from a fragile ecosystem.
But there is also plenty to criticise in traditional Make. The archaic and cumbersome syntax means makefiles are hard to read, analyse and maintain. The completely static nature of a makefile also means it is ill-suited to rapidly evolving codebases where new files come and go almost by the minute as we refactor. We can do much better than Make.
If your problem is just 'lots of dependencies' that may break from under you, npm has a solution for that: 'npm shrinkwrap'.
Make is so static that there was a Lisp interpreter written in make. Oh wait...
There are several mechanisms in make to have your rules dynamically adapt to your codebase, e.g. $(shell ...), $(wildcard ...), and pattern rules (and that's not all of them).
You just need to put a little effort to actually read the documentation, not just stop at finishing one of the plethora tutorials that stop after showing variables usage.
> We can do much better than Make.
You mean, "we can do much better than my `make' knowledge". Of course we can.
Its syntax still looks like the love child of Perl and Haskell, so it is still unnecessarily difficult to write correct makefiles and to read, understand and modify existing makefiles.
`make' may have awful syntax, though I find it much more pleasant to describe build process than anything other on the market, most of which use general purpose languages, ending up as terrible to read.
Tools like Sass and Watchify can monitor for file changes and automatically regenerate SCSS or Browserify outputs when known source files are modified. They also employ caching techniques to make that regeneration efficient, instead of rebuilding everything each time. This functionality is very helpful, and it is available with a simple shell command that works on any major platform.
However, at the moment such tools typically don't notice when new source files are added and automatically start tracking them as well; this generally remains true even if the new file is imported by an existing known file. Similarly, such tools may break if a file that was being watched gets deleted.
In practice, this means you get automatic and efficient rebuilds as long as you are only changing known files, but you probably have to restart a watch process manually if you add or delete files. Fixing this would be high on my wish list for a modern web build tool, given what we already have.
How would you set Make up to solve this problem?
rm -f $(filter-out $(EXPECTED),$(FOUND)) watchify src/index.js -o dist/index.js -t ...
or sass --watch src/index.scss:dist/index.css
that handles new or removed files within the source tree gracefully, not just modified files that are already known when you run the command.Whether it's monitoring for changes like these examples, or hot reloading and browser sync'ing, or IDEs that rebuild incrementally in the background so they can give immediate feedback, modern tools that actively monitor for relevant changes and respond to them automatically are noticeably more efficient to work with than traditional tools that run once on demand. Make belongs to a time that has passed, and we could be more productive by retaining the concepts that are as relevant as ever but incorporating them into tools with the more dynamic behaviour that we enjoy in other tools today.
The manual for GNU Make contains around 80,000 words. That is roughly the length of an average novel.
Having multiple tools in a build process that each operate on source code, (re)parse it themselves into an AST, support differing features (ES6, async/await, etc), and have their own sourcemap-handling strategy is wasteful and especially frustrating when half of them have subtle bugs in doing these redundant steps. Babel doesn't have plugin support just because of ego.
> There is no Gulp/Grunt/Broccoli/Webpack/Browserify in sight, and that makes me happy.
Webpack and Browserify aren't Make competitors. They're tools for adding a module system to javascript, so you don't have to write your code in one file (or among several files that are hard-coded to be concatenated in a specific order and all share the same variable scope).
Just a couple months ago, I was working on the final screen in an 8 step process that has several seconds of delay (not react). Needless to say, it wasn't fun at all and probably took me several times as much effort. Yeah, getting an understanding of webpack, babel and the setup/configuration for a project can take a full week or more, but once you have it, it's more than made up for.
He shared his makefile: https://github.com/aclark4life/python-project
It was OK until a developer on my team complained because he only used Windows
That seems a very rash assumption with so little information.
Maybe the developer in question needs other software to do their job and some of that software only runs on a certain OS.
Maybe the advantages of having the right person on the team and able to use their preferred dev tools are a big overall win for the project.
Maybe running into portability issues with such a fundamental tool is a warning sign that the build process isn't as robust as it could be.
Maybe the whole thing can be fixed with a ten minute discussion and two-line edit to the makefile, and then you have the option of bringing other developers who prefer the same platform onto the team later as well.
Successful companies and products are built by like-minded people.
If you'd said something like "compatible", I might have agreed with you, but I see little evidence that complete enforced uniformity is necessarily a win in a field like software development. This sounds a lot like the kinds of managers who want to reduce everyone on a development team to interchangeable commodities, ignoring the inevitable reality that everyone's background and ability to contribute will be different. It also sounds a lot like the kinds of development teams that can spend weeks going down a dead-end path because no-one had enough varied experience that they anticipated the problem and thought to question the direction the project was going.
This can't be understated. How about, say, accessibility software? There's a reason that, say, visually impaired developers very often use Windows: because the accessibility tools are really, really good.
But, naturally, it's just not understanding the beauty of Unix. Ick.
And I'd fire you if you used barfy corporate speak like this.
> should've been let go
How positively stalinist. Just so we are clear - a guy complained and you'd fire him for that, not maybe first reason with him? Don't complain when the company is razed to the ground because nobody talks to anybody lest they be taken by the nkvd.
Yes, you should have a chat with the guy but maybe it's as simple as installing MSYS2 on a Windows box or making sure he can run a VM for some tasks.
> I also built a Makefile-centric web development build workflow.
The beauty of unix tools was that the model fit well with memory constrained machines of the time. After that came a mountain of hacks that just happens to still work and are used because nobody bothered to come up with a statically typed equivalent. It's far from beautiful, it just sorta works when it's not aimed at you foot.
> Fire early, fire often and build a team of like minded people around you.
It poisons the whole thing. Respect people and people will respect you and maybe they won't screw you over because you haven't given them a good reason to. Egomaniacally firing people for opinions will create infighting, it will cause people to start scheming and collecting dirt on coworkers to be used as a deflection for when the boss has one of his outbursts again. Supposedly most botched products at Microsoft are result of infighting between teams caused by stack ranking, which is effectively the same thing as what you are proposing.
> Nothing wrong with using corporate language either.
It isn't when it's not doublespeak. Culture is a nicer word for circlejerk. Finally, unix circlejerking is fine as long as you aren't a jerk about it..
Using Windows for development of apps ultimately to be deployed on Linux isn't any more sensible than using Linux when you are ultimately building Windows apps. Visual Studio is there for a reason. So is make.
My own process on windows, is usually to have a linux vm (autostart via hyper-v), that I SSH a few terminals into (conemu ftw), and work in linux... I share via smb/cifs from linux so I can use a gui editor... everything else is in the console, or browser.
Once you get used to it, it works out much better... I've also got most of the nix tools in windows, so some stuff I can just do there. My laptop and work issued laptops are rMBP, I also have a few linux systems/servers at home...
Frankly I don't care too much what OS I'm on... that said, it doesn't take that* much effort to ensure what you are doing can run across the big 3 platforms.
The OS X equivalent is a pretty reasonable experience, and Windows is supposedly a similar experience now. The only significant issue is that mounting a volume from the host gets tricky. But for many development workflows, that won't matter.
Keep in mind this hacky "docker-machine" solution is also just a linux VM, but even more complicated.
Premake also looks interesting.
Waiting 530 days before upgrading and then only spending a day to upgrade what is effectively three major versions actually seems very reasonable to me.
The point of the article is that (to take his example) in Java world, as you get used to the ecosystem, things get easier and easier. It becomes comfortable.
au contraire in the web/javascript world, things keep changing but they're still just as hard.
Also, the author is using a Scala toolchain to build the JS frontend code. The standard toolchains (with the exception of Google Closure and Facebook's Flow) are all built around node.js.
There are even a number of code migrations available for React: https://github.com/reactjs/react-codemod -- but of course even those can't help you if you use non-standard tooling and let a web frontend codebase collect dust as browsers (and your dependencies) march forward.
Projects are never finished. If you cease working on a project, it just becomes unmaintained code.
EDIT: As someone seems to have flagged my account and I'm now apparently limited to two replies per hour or something ridiculous like that (yay for passive aggressive moderating tools?) my reply comes as an edit:
> That's a pretty shallow definition of easier.
It's a library that lets you describe DOM subtrees based on application state. How much simpler could it possibly be?
If you mean the toolchain, the keynote at React.js Conf made it clear that improving that part is a major goal for 2016 but none of that will help you if you want to solve everything with your existing Scala tools.
That's a pretty shallow definition of easier.
Then people will just complain there's yet another build tool, because progress or any change is bad!
They generally provide deprecation warnings at least 1 major version before actually breaking/removing an existing API. They have also started providing codemod scripts to help migrate a large codebase (though I've found find/replace sufficient for a lot of them)
My bigger problem has been relying on 3rd party components that hold me back due to some incompatibility they don't address for months.
Welcome to dependency hell :) It happens with all frameworks. The only solution is to use vanilla JS components.
Also, reducing the number of external dependencies your project has is always a good idea.
cd my_project
boot dev
'boot dev' is a task that's defined in the project's build.boot file. It compiles the cljs files to a main.js file, and serves it from a specified directory.Any edit to a cljs file triggers a recompile (of that namespace only - takes about 0.1 second). If the recompile is unsuccessful then a buzz sound plays. If the recompile is successful, boot will play a nice subtle ding sound, and reload the main namespace. With immutable datastructures everywhere, arranging the app's state to allow reloading is simple.
How simple? There's a fantastic tutorial about how to setup everything I've just described at: [2].
This template will spit out all the code needed for the live-reload-cljs thing [3]. Once you install boot (with 'brew boot-clj' it's on apt-get too), You can run it with
boot -d seancorfield/boot-new new -t tenzing -a +reagent -n boot-cljs-project
cd boot-cljs-project
boot dev
;; then edit the cljs file.
[1] http://boot-clj.com[2] https://github.com/magomimmo/modern-cljs/blob/master/doc/sec...
Actually not strictly true. I spend about one day per week writing application code and the rest of my time trying to work out why some npm module that I need to use won't compile.
Talking from my experience frameworks are one of the hugest anti-patterns in software development. They're hard to learn, they limit your creativity, they go out of business, you've to upgrade them for no good reason and make your code compatible with the latest version, you've to search for help and ask others, they bloat your software and create unnecessary dependencies, and you probably need only 10% of what a framework offers. They just don't make sense.
You can easily implement your own abstractions for your own application and be done with it. Your abstractions won't need upgrades, you'll be in control, and you won't have to waste time searching for help. You should be fighting complexity and not embracing it. I don't use frameworks and I encourage you don't use them too.
React itself doesn't do very much at all, but when you're using React, you're using almost everything React has to offer, and then can choose what you want to add on top of that.
Take a look at the top level API [1] and compnenent API [2]. This is React. It's small, and it's compact - there's not a lot to it.
[1] https://facebook.github.io/react/docs/top-level-api.html
[2] https://facebook.github.io/react/docs/component-api.html
Instead you expect every new team member to wade through your homegrown framework-equivalent which means no transferable skills, less real-world testing, likely inferior documentation and no online community to turn to for help if you ever leave. Yeah, nice one.
And do you really think seeing someone else's code means no transferable skills? Sure, you can't put it in CV, but on the other hand, you'd see more than merely using some random one-function module.
Clearly you have not used React. You can't just use 10% and get any value out of it. It's typically 80% or more.
There are other libraries (not frameworks) that more and more do similar things. And some of them actually offer 'api' and/or source-code level compatibility amongst themselves. Further indicating that these libraries are offering patterns.
For example Inferno JS with inferno-component https://github.com/trueadm/inferno
This is a little optimistic in practice, because while React is often described as being just the V in MVC, it also has significant scaling issues out of the box. Useful strategies for keeping the performance acceptable can have profound implications for the wider architecture of your application.
For example, it seems many in the React community are moving towards using immutable data for the underlying model and pure render components with React. That means you can write efficient shouldComponentUpdate checks. However, it also means you have to design your version of whatever the "M" and "C" become similar to how you'd structure a functional program, which is not at all natural or idiomatic in JS.
https://facebook.github.io/react/docs/top-level-api.html#rea...
If you have projects that do not see any updates for a few years (fairly common, in my experience), then see urgent requests come in (in this example, it was that a Chrome update broke the app, but it might also be a feature request. Normally, those shouldn't require upgrading technology to new versions, but there may be security fixes that didn't get backported, or it may no longer be feasible to get people who know how to use that 'ancient' version), that can get annoying fast.
Lesson learned should be that one should not blindly use the latest, shiniest, technologies, but take longevity of the product into account. Problem for web-based stuff is that there is not really a stable product that one can count on to be around mostly unchanged in a few years time, and that is best in class or at least close to it. Evolution is just too rapid.
Everything else seems to be the result of forcing a square peg in a round hole, i.e. using non-standard tooling. As much as I can understand the desire to have one set of tooling to rule them all, if I were using Ruby/Python/PHP/Java for my backend I wouldn't expect to be able to integrate my backend tooling with the Gulp/Grunt/WebPack I might use to build the frontend. Expecting to be able to do the same the other way around is just as arrogant, especially if you then blame the ecosystem you're trying to avoid for the incompatibilities you're experiencing.
AFAIK React is used in production, and I can not find any alpha/beta labelling on their website either?
More here: http://facebook.github.io/react/blog/2016/02/19/new-versioni...
Beyond this, tfa is fighting with build tools that are a bit of a mismatch, which is a separate problem... That it only took a day isn't such a big deal really, and surprisingly good... it could have been integrated a couple of times over the course of that 1.5 years, instead of being left to rot.
I did spot the problem. But then I'm in the middle of making sbt behave civily with typescript and angular2.
Of course I could just use webpack or some other javascript buildtool. But I like to have integrated incremental compilation for frontend and backend. And since our backend is Scala I'm working in my weekends on a typescript sbt plugin. I guess I should get out more.
BTW, the real title is 374, not 347.
Does that mean they don't follow semantic versioning, or that it isn't production-ready?
I'm integrating PDF.js into a react app, and that has been anything but fun (still need to do more for performance concerns), but this is abnormal for react apps... More often than not, if you need to use refs a lot, and are doing a lot of DOM manipulation directly, odds are "you're doing it wrong" ... I'm not saying there are never times, but there are usually better and less cumbersome patterns.
One of the things I really like about react+redux, it it's closer to 95/5 than 80/20, and when you find yourself fighting the flow, usually the answer is to rethink the problem.