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.
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
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:
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)
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)
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.
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
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.
Cory begins by highlighting some services that can help us:
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.
We can now start thinking about shipping our app!