Return to the browser, and refresh. You will probably see a blank screen and a console error

Chrome does not understand `import` syntax

Uncaught SyntaxError: Unexpected identifier

The error states that Chrome has encountered language that it does not understand. But hey, wait, I just said that Chrome has fantastic support for ES6 modules!? We have to make a small change to turn this functionality on.

Head back to index.html and update the script tag as follows;

<script type="module" src="index.js"></script>

The type=module attribute tells Chrome that this script is an ES6 module.

Refresh the page, and everything should be working again.

Going a little further

We have a taste for where this is going now, so how about we add a little interactivity to the page?

Let’s build a simple counter with an increment and decrement button. This requires us to work with local state and requires us to attach events to the DOM to respond to user input.

A simple counter app

Define a class called Counter , as follows;

The above code should be very familiar, as I have written it in the exact same way that I would were I using a build toolchain. As Google Chrome has almost full support for ES6 language features such as class , destructuring, and arrow functions, we do not have to write our code in any particularly special way to get things working.

Note: There is a new language feature that is currently Stage-3 in the TC39 release process (so we can expect widespread support and adoption soon) called Class field declarations for JavaScript which will enable us to re-write this in a more succinct way. For now, though, we are stuck with having to bind our function context and define our state in the constructor .

Styling

Nothing ground-breaking here. CSS has been a part of the web browser basically since the beginning of time, so we have excellent browser support across the board.

We will not go into great detail here, but people typically use SCSS because;

SCSS has compile time variables

SCSS allows nesting

SCSS supports functions/mixins

Well I say;

CSS has runtime variables which can be updated dynamically (waaaay better)

Nesting is awful, you probably shouldn’t be nesting (most of the time!)

CSS has many built in functions, but I admit it, you cannot create your own (yet!)

You can add styling directly in the header using a <style> tag, or reference an external stylesheet using <link> tag.

What about legacy browsers like Internet Explorer though?

Internet Explorer? Never heard of it.

Ugh, ok then.

IE is a terrible browser and has terrible support for everything, especially ES6. Microsoft are doing their best to kill IE off altogether, but many people & companies will stick with it to the bitter end. According to w3counter, IE11 currently has about 3.5% of the global market share, so too much to ignore at this point.

Support for IE 11 can be achieved using Traceur. Traceur is an on-the-fly transpiler that enables you to run ES6 code in browsers that do not support it.

To maximise cross browser compatibility, you can add the Traceur CDN scripts to your header, as follows;

Now when you open your page in IE11, the application should still be working as it was in Google Chrome.

React app running in IE11

So honestly, do I need a build toolchain?

You definitely can build a website today without a build toolchain. Evergreen browsers have excellent support for ES6+ and support is getting better all the time. With an in-browser compiler like Traceur, you can vastly increase cross browser support and get things working better in legacy browsers.

Pro: Your code will be waaaaay smaller, and probably a lot more performant. When using an ES6+ to ES5 compiler (like Babel or TypeScript), polyfills are automatically injected into your bundles to ensure cross browser support. Polyfills are often heavy and take time to be executed by the browser. The polyfills are used regardless of whether the browser supports the feature you are using natively, or not. When not using a build toolchain, the only code that runs in your browser is code you write, and your library code (React).

Con: You cannot use JSX. This is massive. JSX greatly simplifies our code and makes it a lot easier to read and understand. Not being able to use JSX natively in the browser is a huge loss.

Kinda-a-con-kinda-a-pro: You cannot bundle and minify your code. You leave it up to the browser to decide when to download your JavaScript files. The browser will make a new HTTP request for each JavaScript module in your application, because they are not bundled together into one big file. This is both a pro and a con. The old version of the HTTP protocol, version 1.1, supported a maximum 7 simultaneous connections with the web server, meaning that once all 7 connections were open, the browser would have to wait for a request to resolve before continuing. When loading many resources at once this caused render blocking and contributed to web pages loading more slowly. However, version 2 of HTTP (which has good support), has no limit on the number of simultaneous connections, meaning this limitation should be removed. The jury is out as to whether the old technique of bundling your assets is faster or not compared to downloading many smaller fragment files.

Summary

Thanks to advancements in browser technology and the standardisation of the JavaScript standard (ECMAScript), it is possible and feasible to build a React application today without a build toolchain. When not using a build toolchain, you can avoid shipping code to the browser that is not necessary to run your application. Cross browser support can be vastly improved by using an on-the-fly compiler Traceur, which will convert ES6 to ES5 at runtime.

Finally

Realistically, most of the time you probably will want to use a build toolchain, because you will want to take advantage of the latest language features that not every evergreen browser will have support for.

The code for this project can be found on GitHub.

Get In Touch

Did you enjoy this story or want to discuss it further with me? Why not send me a message on Twitter!

Or check out my personal blog

Thank You!