How to set up a modern web app and stay sane
Long story short, I had to create a modern web app.
Actually, it was an HTML page prototype for our new feature. Basic layout and a fairly complex JavaScript to check our design and interaction ideas.
I’ve been doing a lot of web development during the last 2 years, but it was mostly about extending the existing long-running project. The opportunity to learn how to set up a completely new solution sounded too tempting too miss it.
Side note: I was going to write a rant-like blogpost initially. However, the final text turned out to be more like a guide than a bunch of complaints. So you actually may think about it as a from-zero-to-infinity guide to setting up a bare-bones JavaScript web app and its accompanying infrastructure on Windows.
Baby steps
I start with a simple index.html.
Since it’s going to be mostly about interactive interfaces, and I don’t want to spend that much time thinking about boilerplate markup and event handling, I’m going to build it with React.js.
Even though the codebase is not going to be that huge, I probably also want a proper module system. OK, we’ve been using Require.js for quite a long time now, so it looks like a reasonable choice. Just put a <script>
with the reference to the main JS file into index.html.
Obviously, I don’t want to download the libraries manually, so I’m going to pick Bower for dependency management.
Ask the colleague whether I’m doing everything right, just in case. Maybe there is a better way, you know.. Well, actually, it turns out that the cool guys use webpack these days. All right, let’s check it out.
Webpack is an advanced module bundling system which takes your code modules and assets and bundles them together with 3rd party libraries, transforming them on the way (for example, from one language to another) and packing for the optimal performance. Sounds good.
But don’t rush to nail the getting start guide—the cool guys don’t do that nowadays. Why write any bootstrapping code at all when you can reuse the boilerplate crafted by the worldwide community? That’s the main idea behind scaffolding tools like Yeoman. You just choose the kind of web app you’d like to build from the fairly large gallery of templates, and the tool generates a typical code you’d have to write yourself.
Want enterprise Angular skeleton build according to the "best practice recommendations"? Sure thing! "Hipster stack for Java developers"? Why not? ASP.NET MVC? Suit yourself. You can find almost anything out there. And if it doesn’t exist, feel free to submit your own generator.
npm install everything
All right, let’s dive into bootstrapping the app itself!
First of all, I’d highly recommend to use Chocolatey as a general package management on Windows. It installs almost everything – from media apps to editors to Windows Features. It’s also a powerful tool for OS setup automation in case you need to install a lot of stuff with almost no hassle.
Go to http://chocolatey.org and install it, then restart the command prompt (duh..)
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin
Now you can use commands like clist
and cinst
to browse and install packages.
Most of the web tools run under node.js, so it should be your next step.
cinst nodejs
cinst npm
The mentioned yeoman comes next
npm install -g yo
Now wait until it fetches and installs dozens of packages :grin:
You’ve probably started worrying about wasting your life at this point. So it’s time to go shopping, err.. finding the Yeoman generator which suits your needs (remember that a generator is a template Yeoman uses to scaffold the project structure).
I’ve picked react-webpack:
npm install -g generator-react-webpack
Now you’re finally ready to generate some code, yay! In a project dir, run:
yo react-webpack
I particularly enjoy that yo
syntax. It sounds extremely gangsta and it probably also has --beatch
flag.
OK, go grab some coffee because NPM is going to fetch even more packages this time. In the end, I had about 100mb of them for a simple web app. Not bad!
Just follow the documentation from now on. What could possibly go wrong?
grunt build
Oh, you also need to install grunt. In case you didn’t know, that’s the "JavaScript task runner". Basically, it’s a service which you can run to automate basic webdev tasks like compiling your scripts, running tests or reloading the live app on the fly whenever you change the code (yes, that’s possible and it even works. Sometimes).
So..
npm install -g grunt-cli
grunt build
If nothing breaks at this point you should get a basic app compiled in your \dist\
directory. You won’t probably be able to load it via index.html
though because this template was designed to be used with a server-based apps, and it generates broken links to assets for file:
protocol.
You should try to launch the local web-server instead.
grunt serve
The webserver renders your actual app into an iframe on a page with hot-reload and basic compilation trace output.
If you’ve come that far and you’re not overly depressed with setting up the infrastructure, then congratulations on getting to the application code!
Probably now you’re ready to write your first class for your new app. Since we use React, we can utilize its JSX loader for webpack to build ES6-like classes.
class Model {
constructor(name) {
this._name = name;
},
get greeting() {
return "Hello, " + this._name;
}
}
Unfortunately, this code doesn’t compile (I still laugh about compiling JavaScript, but that’s another story) because JSX doesn’t support getters (at least at the moment of writing).
OK, let’s use the transpiler then!
6to5 was a go-to choice, but NPM will tell you it’s deprecated upon installation, so let’s try its successor called Babel. It has a loader for webpack (loader is a module transforming a source code for bundling).
npm install babel-loader --save-dev
Now open webpack.config.js file, locate the loaders
config for JS files, and add babel
transformer to the pipeline.
loaders: [{
test: /\.js$/,
loader: 'react-hot!jsx-loader?harmony!babel'
}]
This syntax tells webpack to apply Babel-transform, then jsx-loader transform with harmony
flag, then react-hot
for the hot application reload.
grunt serve
Yay, finally up and running! Time to get back to coding models.
At some point you’d probably want to use underscore or lodash to manipulate your data structures. Good luck with that because it all breaks down quite fast.
If you reference underscore, you’d probably get runtime TypeError quite soon due from the depths of underscore’s initialization routine:
// Establish the root object, window in the browser, or exports on the server.
var root = this;
var previousUnderscore = root._;
Babel prefaces every "webpack"-ed module with 'use strict';
instruction by default, which prevents underscore from storing a global host variable. I honestly haven’t found anything better than disabling this transformation at all, so my loaders
config for webpack now looks like this.
loaders: [{
test: /\.js$/,
loader: 'react-hot!jsx-loader?harmony!babel?blacklist=useStrict'
}]
The final grunt serve
and it all seems to work now. Phew.. Now, the several hours later I can get to the actual coding and prototyping!
Conclusion
At first I was quite disappointed with the amount of things you have to do to make such a small app work. The explosion of technologies and platforms makes it a little bit hard to jump-start and dive right into the development, compared to the typical desktop, mobile, web or server applications you build these days with .NET, for example.
The funny thing is that the mature front-end developers don’t actually feel any pain here. However, reflecting on that experience and writing the blogpost made me think that it’s not actually that bad, you just have to keep your mind open to grasp the entire network of small technologies and their relations to each other.
Hopefully, the front-end web development evolves even further in the coming years, the irrelevant solutions will die, and we will get several good, stable and fairly easy tools to build the reliable things in a fast and enjoyable manner.