Showing posts with label browser. Show all posts
Showing posts with label browser. Show all posts

Monday, June 29, 2015

Building a browser application using React

tl;dr - use Node.js-Browser-App on github to quickly get started making a React based web application built with Node.js

Lately I've been doing a lot of work constructing javascript-based applications that are meant to run in a browser. In some cases an application was meant to be used in a web browser and in other cases as a Chrome App (formerly called a Packaged App). Currently the React toolkit developed by Facebook and Instagram has achieved a certain dominance in web app development and it functions well in both environments.

One of the amazing strengths of React is the size of the ecosystem that has grown up around it. There are a large number of addons, mixins, and other projects that augment its capabilities. The sheer amount of functionality (code) available is staggering. But before I get too far into React I should really talk about Node.js. Node.js is simply a runtime environment for javascript code. Like React Node.js also has acquired a large ecosystem of code that can be executed in the runtime, perhaps most famously the "Node Package Manager" always referred to as npm.

npm helps solve one of the problems javascript projects have suffered from in the past: how to organize the code so that it can be understood by humans (file naming, directory structure, and small encapsulated chunks of functionality) and packaged for efficient delivery to a javascript runtime. One solution is to use npm packages with source code organized following CommonJS conventions. Both Node.js and npm understand CommonJS and can work with it directly but browsers can not. However as in all things Node.js + npm there's a package for that: browserify. Browserify is a toolkit that reads CommonJS files and converts them into javascript that a web browser can execute. Additionally Browserify supports "transforms" that can be applied to CommonJS source files before they are parsed and transform (modify) them in some way if necessary. Also Browserify can generate "source maps" so that later in the browser's debugger the original source files can be debugged rather than the bowserified files. As we've seen Browserify has been packaged so that it's available in the Node.js environment through npm.

Now back to React. React files are regular javascript except they support the use of JSX syntax. JSX is a little like HTML embedded in your javascript. Unfortunately neither javascript runtimes or browserify understand JSX, but there's a package for that. Through npm we have access to reactify, a browserify transform that will convert the JSX syntax into plain old javascript. Once the JSX is converted browserify can bundle up the code for a web browser.

Of course there are many other steps in preparing a web app for delivery to a server. Node.js + npm can do this too using a variety of task / build utilities, I chose to use gulp. Briefly here are some things you can do with gulp: bowserify (including reactify), conditionally affect stream piping (using gulp-if), copy and modify a JSON file (using gulp-json-editor, generate jsdoc documentation, minify output, copy files, and much more.

With Node.js + npm + gulp + browserify + reactify we can create javascript web applications where the code is organized in a manageable fashion by using CommonJS conventions and we get a high performance UI with React. If you think that those are a lot of pieces to put together from scratch you're right, so don't. You can get off to a faster start using the Node.js-Browser-App repository on github. This repository has all the components described above (plus a Flux dispatcher) so you can just copy the repo and start building a web app or Chrome App.

Incidentally, once you've got your project going you'll find a lot of cloud services can work with it. For example Microsoft's(!) Azure can be setup with webhooks from github so that every time your source code changes it will: fetch the updates from the repository, build using Node.js, and deploy the output.

Saturday, November 17, 2012

Mobile web app fail

As an experiment I wanted to see if a web app could be created that would send images from a wi-fi enabled mobile device to a computer. The reason was that the computer could easily serve the web app directly to a user's mobile device and the user could then upload their images to the computer and both operations could be done without needing to download a native app from an application vendor or use a data plan.

The proof-of-concept requirements were fairly broad and simple: serve the necessary files that make up the web app from the computer, allow the user to choose image files, and upload the images to the computer. Serving the files was simple, I created a basic stand-alone server process that could respond to requests for files and also handle the image files that were uploaded to it via XHRs from the device's browser. The user requested the start page by scanning a QR code that launched the browser and navigated to the app's URL. Problems really started with the web browsers available on mobile devices.

The largest problem was the iOS web browser. Prior to recently released iOS 6 the iOS browser didn't allow the user to choose files for upload. The basic HTML "input" element with type "file" was not supported in the browser. It seems hard to believe this was an unintentional oversight on Apple's part. The practical effect was that this forced developers to create native iOS apps rather than allowing them to create a single web app for any mobile device. There will remain a large number of devices running iOS 5 and earlier versions of iOS for years to come. As developers we will be living with a crippled iOS browser for a long time. IE 6 anyone?

The next problem involved displaying thumbnails of multiple images. On my Nexus S phone both the native and Chrome browsers crashed after opening multiple images. Looking at the logs I found that the browsers were running out of memory. I was able to improve the situation considerably, but not entirely fix it, by setting the img element's width and height attributes to the size of the image that actually displayed rather than relying on CSS.

Once that problem was minimized I was able to select images, insert the thumbnails into the DOM and then upload the the files to the computer. Some positives from this experiment: all of the Android browsers had partial support for the File API (notable exception below), data URIs could be used to access the image information in the files, and finally @font-face support so I could use Font Awesome for the images on buttons and menus. Negatives: while the File API's File object is supported Android doesn't have multi-file select functionality for browsers. Each image file had to be chosen one at a time from the Gallery application which became tedious by the second file selection.

I'd like to mention that of the three browsers I used during development only Mozilla's Firefox browser for Android was able to reliably display and upload files. Unfortunately for the proof-of-concept web app it had to run on at least the iOS and Android native browsers. Other browsers like Firefox or Dolphin just don't have a large enough market share to make them an acceptable solution.

Having said that, my experience with the shortcomings of many mobile web browsers has reinforced my belief that Mozilla's mobile browser and Firefox mobile operating system are as important now as Firefox was ten years ago in helping to push innovation forward, especially on mobile devices, and to keep the web open.

Lastly a tool that was indispensable and made development easier and faster was desktop Firefox's Responsive Design View mode. In this mode (available under the "Web Developer" menu) the browser's viewport is resized to emulate various common monitor and mobile device screen dimensions or you can set custom dimensions as needed. Using this I was able to set the browser to the same size as my phone and do most of the development work on my desktop, only using the phone to periodically test functionality. If you need to design a web page that is "responsive" to different size screens or screens that change size, like switching from portrait to landscape then this tool is a must have.