Creating a JavaScript Development Environment: Production Build

coryWelcome to Part 12 of this review of the Pluralsight course “Creating a JavaScript Development Environment” by Cory House.

Cory is a Microsoft MVP in C#, founder of OutlierDeveloper.com, avid tech reader, and speaker.

He believes in clean code, pragmatic development, and responsive native UIs.

He has also created reactjsconsulting.com, and has the authored Pluralsight courses including Building Applications with React and Flux and Building Applications with React and Redux in ES6.

Also in this series:
Part 1 – You Need a Starter Kit
Part 2 – Editors and Configuration
Part 3 – Package Management
Part 4 – Development Web Server
Part 5 – Automation
Part 6 – Transpiling
Part 7 – Bundling
Part 8 – Linting
Part 9 – Testing and Continuous Integration
Part 10 – HTTP Calls
Part 11 – Project Structure
Part 12 – Production Build
Part 13 – Production Deploy

Production Build

Minification and Sourcemaps

Cory says minification removes all the things humans care about and leaves only the things that machines need.

Demo: Production Webpack Configuration with Minification

Earlier in the course we creating webpack.config.dev.js, and here we copy it to create webpack.config.prod.js.

We then make the adjustments we need for our production environment, adding references to UglifyJsPlugin and DedupePlugin.

Next we create a build.js file, importing webpack, webpackConfig and chalk.
The basic code runs webpack and returns 0 for fail and 1 for pass.

Cory says in the real world we will want a bit more code here. We set our node environment to production, and add code to log errors, warnings and stats to the console.

Demo: Configure Local /Dist Server

In this lesson we create distServer.js and begin by copying the contents of srcServer.js into it.

For our production server we can simplify as we do not need to use webpack. We serve up only the static built files, and for this we just need one line of Express code.
Cory also shows how to use gzip compression here.

Demo: Toggle Mock API

We return to baseUrl.js and rework the simple logic to look at the query string parameter to determine whether we use our mock API or the real one.

Demo: Production Build npm Scripts

In this lesson Cory uses 4 npm scripts to compose the production build:

– clean-dist
– prebuild
– build
– postbuild

When we run this we see the error:

Error: ENOENT: no such file or directory, stat '/Users/coryhouse/Desktop/projects/js-dev-env-demo/dist/index.html' at Error (native)

This is because webpack is configured to write our JavaScript files and handle our CSS but we haven’t setup anything yet for outputting our index.html file.

Dynamic HTML Generation

Should we run slightly different HTML in production from development? Cory begins by explaining why we might want to manipulate HTML for this.

Up until now we’ve had a script tag in our HTML referencing bundle.js. Cory says this is okay for a simple setup but there are other more powerful approaches to consider:

1. manipulate via Node (e.g. with regular expressions)
2. html-webpack-plugin

Demo: Dynamic HTML Generation

In this lesson we use Jan Nicklas’s html-webpack-plugin to handle dynamic HTML. We update webpack.config.prod.js, importing this and using it in our plugins section to create our index.html.

The webpack plugin will dynamically add in any necessary script tags for us so we can remove our hardcoded reference to bundle.js.

We see that the generated bundle.js is minified and gzipped and only 4.6KB in size.

We enhance this further by configuring html-webpack-plugin to minify our HTML, removing comments, collapsing whitespace, removing redundant attributes and empty attribute, using a short Doctype etc.

Cory also points out that the delete user links won’t work when we are pointing to our real API.

Bundle Splitting

Cory explains that bundle splitting speeds up the initial page load and avoids re-downloading all libraries.

Demo: Bundle Splitting

This lesson demonstrates bundle splitting using Webpack. Cory begins by discussing some different design approaches we could take:

– split by page?
– split 3rd party libraries from application code?

We go for the latter strategy here, creating separate entries vendor and main and adding a new vendor.js file.

To perform code splitting we reference webpack.optimize.CommonsChunkPlugin
You can think of “chunk” as another word for bundle.

We must also update the output section as we can’t just have a single filename anymore. Cory shows us how to use a placeholder instead.

We see vendor.js and main.js are generated by the build at both are under 3KB in size. Nice!

For further details on code splitting in Webpack see https://github.com/webpack/docs/wiki/code-splitting

Cache Busting

Cory explains that cache busting can save on HTTP requests and allows us to force a request for the latest version when needed.

Our high level plan is to:
1. Hash bundle filename
2. Generate HTML dynamically

Demo: Cache Busting

Kirill Ermolov came up with a clever solution to make cache busting easier. His webpack-md5-hash tool  generates a deterministic hash for each bundle and appends it to the filename, ensuring the filename of the bundle changes at the same time as the code!

Cory shows us how to import and use this tool in only 3 lines of code. Cache busting is easier than ever before.

We might want to setup cache busting for our CSS as well.

Demo: Extract and Minify CSS

Again this is easy with just 3 lines of code required in our webpack config file.

We import the extract-text-webpack-plugin and call it in our plugins section. Finally we update our CSS loader to use this plugin.

Error Logging

Cory begins by highlighting some services that can help us:

TrackJS
Sentry
New Relic
Raygun

He also runs through some important considerations when assessing an error logging service. He recommends going with a paid service over trying the DIY approach.

Demo: Error Logging

Cory shows how to get setup with a Track.js free trial. This service looks pretty good.
It captures a range of useful data including the Url, the timestamp, time on page, visitor time, browser, operating system, source IP and viewport.

Demo: HTML Templates via EmbeddedJS

We only want our production build to log to Track.JS. We can achieve this by adding conditional logic to our HTML. Again webpack can help us with this!

Webpack supports a number of templating engine including Jade, EJS, Underscore and Handlebars. The default is EJS and we use that here.

http://www.EmbeddedJS.com

We can now start thinking about shipping our app!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s