Hacker News new | past | comments | ask | show | jobs | submit login
A mobile, desktop and website app with the same code (github.com/benoitvallon)
193 points by benoitvallon on Nov 5, 2015 | hide | past | favorite | 80 comments



I didn't do this project to convince people that the "write once, run everywhere" is the holy grail but I wanted to explore how it is possible to do it with the actual tools.

It happened to be really convincing (at least to me) in the case of a small project like the one I did but I am also convinced that for bigger projects people should be very careful and think twice before going with this paradigm.


Why do you say one should be careful using this approach in a large project?

I'm not sure how much value your paradigm will bring to a project -- 90+% of the non-boilerplate code in most React components is inside the render function, so I'll probably just deal with the very small amount of duplicated code rather than adding the complication of the paradigm you're using.

However in a larger project, duplicated code is much more expensive, so I think your paradigm would be useful there...


I think for bigger projects you really have to think about what your UX is going to be. Sometimes you want UX and features so different for devices that looking to share code at all costs can result in a lot of useless code in the builds but if your project is going to use a similar UX I think this paradigm works.

About the 90% of code inside the render functions, it made me think about the time where people were complaining about huge Angular controllers. I agree that render function can be large sometimes but I think that if 90% of code component is in the render function, you should probably move some code to the stores.


The reason that 90% of the component code is in the render function is because everything else has been moved out to actions & reducers. Sorry I didn't make that clear.

And I'm firmly in the "lots of tiny little components" camp, so I don't have any large render functions. That's also another reason I'm not going to adopt the pattern the OP suggests -- that pattern uses 3 files per component.


> I am also convinced that for bigger projects people should be very careful and think twice before going with this paradigm.

Wise words.


Very cool! Looking forward to diving into the code!

Question- how much extra work would it be to add Android and/or Windows Phone support with react-native?


I don't know how react for android works and I don't know if the "trick" I used for the builds would work with react for android. Maybe it would need to rethink the build system. But the good news is that people are interesting in making it, so we will see the result.


> It happened to be really convincing (at least to me) in the case of a small project like the one I did but I am also convinced that for bigger projects people should be very careful and think twice before going with this paradigm.

How you would have done for a larger project? And also if we remove mobile from the equation, but a cross platform desktop app?


If you mean Windows/Mac App by cross platform desktop app, I don't have any experience in doing that. But windows is pushing for app that uses javascript so it is probably something that is not too complicated to do.

My guess would be just to use the correct "packager“ for it. I used NW.js which today seems to be overpassed by Electron. I think you need to get the right one to build a windows app.


Interesting, and thanks for sharing!

What kind of paradigm do you think you'd use for a larger project? Also do you think you'd stick with Flux vs Redux/Alt/etc?


About the paradigm I already answered before, I think you need to analyse your UX/features in order to avoid useless code in builds.

You are right about flux/redux question, I started this project 3 months ago and let it on the side for a long time, but I would definitely go with Redux if I had to redo it now. Same for a bigger project. I have never used Alt so I can't tell.


Hasn't this already been done? It's called a web app using html, css and javascript


Yes it has been done and to a greater extent than your dismissive comment. It still doesn't detract from the noteworthiness of the OP.


I don't think it was dismissive at all. When a post rises to the front page of HN people are going to post comments both agreeing or disagreeing. In my case, I don't see what all the hoopla was about or how this was upvoted to page 1


The biggest difference in this case is that the mobile version is native instead of using a WebView.

Yes, it uses JS in the background but uses native widgets, which results in a much better user experience.


It has, but look... It's a good example code base and has lots of notes on what technologies are used incase you are interested in doing the same thing...


I understand THIS project's intent which is to learn and discover how possible it is to achieve, However the fact that I'm seeing more and more Javascipt apps being released for desktops really disappoints and scares me. The performance, weight and often security concerns that come with JS frameworks is frightening and while it's fantastic that JS is perhaps lowering the bar as to who can write an application (perhaps) - it's also making it easy to do the wrong thing.


Do you not think a similar thing was said when Cobol came out and young, new developers started abandoning assembly? I don't think being disappointed or scared is necessarily the most reasonable reaction to have in light of the fact that this is just the way technology works. And in the end, it probably is a good thing.


Except Cobol didn't suddenly gain a lot of popularity after C++ was well established. There are plenty of languages even more abstract (and I would argue easy to use) than JavaScript, some of which don't sacrifice nearly as much performance.

The movement to JavaScript is a product of web developers branching out into other areas (great!) without taking the time to learn another language (not so great :/). I don't think performance is an end in and of itself, and I don't turn my nose up at picking a technology because developers and expensive and processing power is cheap, but I still think writing everything in JavaScript is a step backward.

edit: Accidentally wrote developers are cheap and processing power is expensive :P


This is a taste of the future. More and more people are creating things using tools and frameworks but not really understanding the underlying concepts. When I pick up a bookshelf at IKEA and put it together, I don't start calling myself a carpenter because of it.


Taste of the past too.

In my first programming job, there were a few senior programmers who were then in their 50s, meaning they started programming in the 70s (before microcomputers). In those days, the way you became a programmer was to major in electrical engineering. That's why even now, a number of top universities (MIT, Berkeley, Ann Arbor, Rice) have combined departments of "electrical engineering and computer science".

How many C++ and Java programmers these days know how to work their way around NAND gates, digital logic, and RCI circuits? How many know how a transistor works? How many know how to build a mux in hardware, or an adder, or what's in a RAM cell?

I'm sure there are some, but by and large, I think it's an improvement that we don't think about digital logic and binary representations when we write our program. The cycle of moving up the abstraction hierarchy has been going on since high-level languages were invented in the 50s. Today's tools and frameworks are the low-level building blocks of tomorrow.


JS performs well, JS VMs are small enough (or at least comparable to Java's core) and since it runs local code instead of code from the internet, it's pretty secure. I've done desktop applications[0] made with JS, with the .exe being less than 5 MB (including node and all JS code bundled).

Your concerns involve bundling whole web browsers with the desktop applications. We'll probably see a desktop version of react-native in the near future, making things much more lightweight.

[0] Without barely any GUI, it was mostly a canvas.


> JS performs well

As compared to what? Compared to other interpreted languages, sure, but you're looking at least an order of magnitude compared to other VMs.


Most UI layout doesn't involve that much computation. JS is definitely fast enough.


> Most UI layout doesn't involve that much computation. JS is definitely fast enough.

The performances of editors like Atom or Brackets tell us another story.

Web UIs might be fine for an LOB app but then, an LOB app doesn't need to be a desktop app. No, current JS engines (JS is a language, it doesn't have performances) are definitely not fast enough. Compared to the kind of performances that can be achieved with the JVM or QT.


Atom and Brackets use the big old bloated DOM, and not very well. At least in the case of Atom, it's used awfully, and plugins can block the main thread (and they do with big-ish files).

Anyway, the discussion is the use of JS. The language is fine but the UI "library" is not (a whole web rendering engine).


> JS is a language, it doesn't have performances

This is not true. Unless you have a god-compiler that takes your JavaScript and spits out compiled code that doesn't use dynamic typing or a GC, the nature of the language has a significant influence on performance.


> This is not true. Unless you have a god-compiler that takes your JavaScript and spits out compiled code that doesn't use dynamic typing or a GC, the nature of the language has a significant influence on performance.

Well , my point is JS is a spec. You can argue that some language features will make the language slow(er than statically typed languages),and I'd agree.


Doesn't Atom use a web rendering engine? We're not talking about the DOM here, just pure JS.


Sure, if you use a platform that has something like react native. But the desktop app for the calculator used NW.js, so it used a nice, slow DOM.


Making a programming language harder to use, or making a build chain more difficult to get working, doesn't make software better.

Raising the barrier to entry doesn't "raise the bar" when it comes to software quality. It just adds artificial difficulty.

The hard part about writing software shouldn't be Hello World. It should be building a user experience people enjoy. The less steps to get to that point, the better.


I'm not sure if it works that way in real life. Dreamweaver made it really simple to create websites but look at the quality of what was produced. Any good developer would not use this tool even though it did make things simpler


That's a quality/ubiquity tradeoff. Dreamweaver converted non-consumers into shitty programmers. It didn't actually reduce the quality of anyone's existing HTML, it just increased the quantity of HTML out there, and of course the marginal machine-generated HTML is going to be worse than that written by experts with 5 years of experience. Average software quality declines, but this is a Simpson's-paradox effect, not a decline in the output of any one person's software.

Ditto PHP, Node.js, Rails, and any other technology aimed at opening up programming to a larger audience.

This trend has a while to go: while there are vastly more programmers out there than when I started programming, there are still vastly more non-programmers than programmers, and I believe that ultimately mastery of machines will become as important as literacy.


How can a script running in a VM be less secure than the ability to run unchecked gets() & friends?!


I'm doing exactly the same with http://duckie.tv/

Runs as: - Mobile (Phonegap) - Native (nw.js) - Website - Chrome extension

with exactly the same codebase.


That doesn't sound the same. PhoneGap uses a web view to render your layouts, React Native uses native platform components to render layouts.


This is a pretty clever implementation. We're demoing out a POC React Native app this week at Vogue. I initially thought that we could share a lot, but due to the specific implementation of containers and styles, there is less than I expected. All helpers, stores, and dataflows should be preserved though. Breaking this apart at the render methods and having build processes that chose the right renderer is something I have been theorizing on as the proper approach. Thanks for sharing this!


Way cool! Looks like a common `Keyboard.js` will render either `KeyboardRender.js` on web/desktop or `KeyboardRender.ios.js` on mobile.

KeyboardRender.ios.js: https://github.com/benoitvallon/react-native-nw-react-calcul... KeyboardRender.js: https://github.com/benoitvallon/react-native-nw-react-calcul...

I'm wondering, though, if we can take this a step further and write Keyboard as the exact same code by composing it with more general components like `<View>` instead of `<div>`. This will require inline styles instead of class names, though.

I theorize that this will be made a little easier for you with the use of react-native-web: https://github.com/necolas/react-native-web

Cool project, though, thanks for sharing. Code is very clean, I'll definitely be using it as a reference.


> This will require inline styles instead of class names, though

That's probably not a bad thing; at the moment there's duplication of inline styles for the mobile view and styles in a CSS file for the web/desktop.


I'm a little hungover, so a bit stupid today.

So, the mobile app is an actual native app, with no phonegap / webview.

The desktop app is a webkit browser packed as its own application.

And the server app is a single-page app run in the browser and served from a server.

Correct?


Probably yes.


Exactly


Facebook has a pretty solid blog post about how they use a similar architecture to share code between android & ios apps:

https://code.facebook.com/posts/1189117404435352/react-nativ...


I like this as a thought experiment - can I write JS code (specifically using React) that can be shared across a variety of devices. At the same time, I would not do this for any sort of non-trivial production application. The main reason being that you're going to end up writing platform specific logic at one point or another (basic example: Handling files on the web vs on mobile - ios / android vs via node webkit). I think that the codebase is already doing something like this with its .ios.js files.

Eventually you'll end up with some shared code and other platform specific code and you'll wonder why you don't just split up the codebase into individual applications (that can easily be worked on by independent teams). You can still have a shared dependency that handles logic, but you can iterate on each application independently.


Very few large multi-platform applications use separate code bases. Why should it be different for a javascript/React app?


I'm assuming that you mean Linux/Windows/MacOS when you say multiplatform. I agree that for Desktop apps its sometimes okay to use the same codebase (thinking of Blender, Gimp, other open source apps that work across Desktop OSes). Other times there are apps that work significantly better because they utilize an OS's strengths (Pixelmator for MacOS).

The key difference here is that user expectations are completely different between a mobile app, a desktop app (either native or node webkit), and a web app - at the moment I would say that its rare to see any app share the same codebase (not including shared libraries/dependencies) for all of those. As this post shows, its not impossible, but there are still some tradeoffs.

If I was starting a brand new application that needed to work across all platforms, I would still consider having independent code bases sharing a library as a dependency rather than having a single codebase for everything - especially if I wanted to be sure to have the best possible experience for each platform.


The whole "write a shared library, and layer your platform-specific UI on top of it" sounds great in theory and is brought up all the time, but vanishingly few apps actually do this from what I can tell.


In the example app, the mobile variant has completely view code than the two web based variants. The fact that they look and feel similar is a deliberate coincidence more than a consequence of the design.


Any thoughts on adding React Native for Android support? I know it's newer than the iOS counterpart but would be curious how hard/trivial it would be to include it


As a native mobile developer... How is react-native (or something similar) not the future?


From everything I can tell as well as talking to many people in the industry, React Native (or something very much like it) is definitely the future.


I still live in fear of the day some time down the road when all the people far smarter than me start writing articles titled "Why Function/Reactive/Reactifluxidux architecture was a horrible decision". That's the nature of tech I suppose.


It is always a horrible decision and often driven by an incompetent management not to go native. If I'd ask my aces to use react, I am pretty sure at least one would puke over the desk, another one would jump out of the fifth floor and the rest would simply decline and start question my competencies. (I know you'd puke Felix!)

On the other hand we're earning a lot due to all the unnecessary and wasted resources we have to sell to meet performance expectations of our customers ( and those guys happily buy it ) you could reach with 1/1000 probably 1/100000 of the MIPs by utilizing native C.

Utilizing react is not even programming or engineering. That's assembling. rant off


you're going to get downvoted and you'll think it's because you badmouthed a popular technology. It's not because of that, it's because you criticized something on a technical forum without giving any concrete reasons why said technology is bad.


Well, we can't know the future, but I'd like to draw a parallel. A few years ago, Java offered the promise "write once, run anywhere". It worked pretty well until a major OS decided "nah, not gonna happen here".

What's different this time?

It is popular (Java was and still is), it is backed by a big company (Java too), it only needs Javascript, which all devices have (Java only needs a JVM, which all devices used to have).

Well, I sure hope for all the folks involved it really is the future. At least, it may well be for the next few years.


> It worked pretty well until a major OS decided "nah, not gonna happen here".

No, it really didn't. For a time after "Java Web Start" was introduced in 2001, java had (has) a pretty decent story for distributing application (big run time dependency, problematic java updater non withstanding).

But I think the biggest problem java had/has is the mix of java being a hopelessly verbose, and arguably rather primitive language that's a bad fit for both AWT and (to a lesser degree) Swing. It's almost comical to contrast "hello world" with swing/java and with swing/jython (or jruby) - it's not that the UI toolkit is unusable, but it's not a good fit for the biggest use-case: simple business applications.

I should add that I think kotlin looks like a pretty perfect match for "the good parts of java without any added complexity".

> What's different this time?

Modern JS is arguably a better fit for simple GUI programming than modern java is.


From what you've seen, what's recommended, flux or redux or relay/graphql? I have trouble keeping up with those


Does it still only support OS X for building apps?


Just like on the desktop, true native apps will always have their place on mobile. But for a very large majority of apps React Native will be more than good enough and much faster to work with.

Personally I've switched my focus from native iOS to React & React Native.


I don't think I could deal with losing Swift's type system and working in JavaScript, plus the whole Optional vs null issue.


I can't say I don't miss types, but if you use ESLint and FlowType it's not as bad as you might think. Hopefully I'll be able to start using Typescript on React projects soon.


It totally sounds like the future, but I can't help but hate the fact that it is tied to javascript. React-native with WASM would be a dream come true :)


Many language compile to JS nowadays! (PureScript, ClojureScript and GHCJS are a few I personally would really like to use)

I think currently there are more languages compiling to JS then to JVM. :)


I personally use scala.js and clojurescript quite a bit, but in every case of an existing non-JS language compiling to JS, there is a semantic mismatch coming from the runtime mismatch. This results from various things like the lack of static types, threads, 64 bit integers, etc. Furthermore, the performance still leaves a lot to be desired.

WASM holds a lot more promise for all of these problems.


Yeah but just because you can...


I don't know much about React. When poking through the code I found this:

https://github.com/benoitvallon/react-native-nw-react-calcul...

Lots of ad-hoc global variables like _lastPressedWasEqual. Is this idiomatic?


Apparently, that's how people build "flux stores" in samples. Their purpose is to hold "all the state of the application", so that design is enough. I'm not versed in Flux, but I can imagine that in real world situations one would actually build a store that has some sort of persistent cache, like by using a database or the filesystem.


They aren't global, they're local to the source file, which represents a singleton class, so it's not really dangerous. You could think of them as static variables in a singleton class.


I'm not sure what justifies using a Singleton here - what if I want more than one Calculator in my app?

I also noticed that we have a Store (which I interpret to mean model-layer) handling key events, e.g. "processBackKeyPressed()". Is that common too? From my outsider's perspective, this looks like a layering violation.


I didn't write this so I am not in a good place to argue in favor or against any pattern, but the obvious answer here would be the needs of the application justify a Singleton. The app doesn't support more than one Calculator, adding additional object management for a feature that isn't necessary is strictly wasted effort.

I don't think it's a "key event" in the sense you're imagining. The store is a black box around a calculator device with emulated physical buttons, so "back key pressed" is one of the store's fundamental actions. I might be wrong about this.


> You could think of them as static variables in a singleton class.

So... global variables?


Q: Say you find a bug in a component, do you need to edit both .js and .ios.js files to fix it? Yes? Not the same code base. No? Quasi the same code base.

IMO same code base is just that, no ambiguities. In this example it would be the same js, html and css that run inside a different container (browser, nw, node or webview)


In the past, I would have jumped at these demo apps screaming "but they won't feel native! They won't integrate well!"... however, these days all major OS developers are busy knee-capping themselves and making their desktops feel and act like webpages, so hey, it might actually work.


The mobile app uses native components.


The GP is talking about look and feel, not native vs multiplatform components.

The point about everybody converging to the flat paradigm that evolved from the mobile web is a valid one. What is good for small touch devices may not be for large mouse-driven ones; the removal of affordances and button labels in particular is a problem in the new style favored by web designers.

However, I would also complaint against developers trying to make web applications feel like desktop ones, with window management and all, which is a similarly recurring and worrying trend.


I'm doing the same within the confines of a Rails app. Works well so far. It'll be a while to release. I may open source the scaffolding portions of it.

Off topic but does anyone know people hiring freelance React Native? I'd really like to focus there myself. It's the future.


If you bill yourself as a mobile dev expert and work for non-technical teams, you could probably take any mobile dev job.

For instance, if a hospital is looking for someone to build an appointment management app for their patients, they don't care if you use Obj-C or JavaScript - they just want an app that works.


Very interesting. Really nice stack: allowing extensive re-use, across a huge range of devices (Android seems to be worked on), fully open source!

For personal taste I'd put a little PureScript or Haskell (with GHCJS) in the mix :)


History has shown me that "write once, run everywhere" is a holy grail for internal developers and consultants.

But this web everywhere shit...

That might do it.


This is somewhat silly. By this logic, any website could be billed as "A mobile, desktop and website App with the same code".




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: