Vendor Bundle to Improve Gulp Build Speed

Since the previous post I’ve looked more into Gulp. I started migrating the tool website from the Express/React setup to use the static-react-starter project starter. The transition has worked fine so far, but I’ve realized some issues with the starter project.

  • Gulp watch is slow to rebuild when the number of JavaScript files and dependencies increase.
  • The resulting build structure is messy and results in urls that are long. Ideally I want a short path following the domain name.
  • Each page is relatively large in file size, since the JavaScript files are not uglified.

The build time quickly became annoying. To fix this, I tried replacing gulp.watch with watchify for the JS files. Watchify helps incrementally rebuilding your bundles while developing, and works together with browserify. This really helped speed up the script rebundling time. Before it could take anywhere from 5-10 seconds from saving a file to the update appeared in the browser. After the switch, it takes less than a second. However, the initial build time only improved marginally, if at all. After adding uglify to the script task, the initial build time was around 14 seconds.


Creating an External Vendor Bundle

What solved this problem for me, was creating a vendor script bundle in addition to each subpage’s app script bundle. This can be done by taking Browserify’s external and require options in use. The result was that each app script bundle would only take around 1 second to build, whereas the vendor script bundle takes around 5 seconds to build. Much faster!


Why you Should do This

  • You seldom update the dependencies of a project. Watching dependencies and building them more than once are unnecessary.
  • In my case, each subpage utilizes mostly the same dependencies. Having a common bundle for vendor scripts might reduce load time because of caching.
  • Improves the development workflow. Changes are propagated faster from the editor to your browser.
  • With gulp.parallel the app subpage script bundling task and the vendor bundle task are conducted in parallel.


Vendor Bundle with Gulp Recipe

Import Project Dependencies

Start by loading the dependencies into your Gulp file:

...
import packageJson from './package.json';

const dependencies = Object.keys(packageJson.dependencies || {});
...

The dependencies variable will contain a list of your project dependencies that you’ve added through npm install <dep> --save.

Modify your Script Bundler Gulp Task

You will need to tell Browserify about external requires. When Browserify encounters a require (or import) marked as external it will ignore it when building a bundle. Basically, it will trust you to add these dependencies through another script tag somewhere in your HTML.

...

let b = browserify(opts);
b.external(dependencies);
b.transform(babelify);

...

Create a Vendor Bundling Gulp Task

After modifying the app bundling task to ignore the dependencies, you’ll need to create a vendor script file. Create a new Gulp task:

export function vendorScripts() {
  return browserify()
  .require(dependencies)
  .bundle()
  .on('error', (err) => console.log(err))
  .pipe(source('vendor.js'))
  .pipe(buffer())
  .pipe(uglify({compress: {unused: false}}))
  .pipe(gulp.dest(dirs.dest + '/app'))
}

You will also have to include this new task in your build task:

...

const build = gulp.series(clean, gulp.parallel(styles, vendorScripts, scripts, images, sounds, views))
export { build }

...

Add new Script Tag

Somewhere in your HTML, above where the app bundle script is, include the vendor bundle script. For instance:

...

<script src="/app/vendor.js"></script>
<script src="/app/tool1/entry.bundle.js"></script>

...

If you go to Chrome’s Network tab in the inspect window, you can see both vendor.js and entry.bundle.js will be requested on page load.

To see the entire Gulp file, go here.

How to do Gulp with ES2015 (ES6)

This weekend I decided to re-visit web development by looking at Gulp and React. A friend and me did this project where we wanted to create small and shiny utility web apps with React. Most of the tools out there are not the easiest to use and visually not that appealing to put it mildly. So, we created an isomorphic/universal Express/React setup and created half a dozen of tools or so, ranging from a weather, white noise and country code lookup tool.

We hosted the solution on DigitalOcean. The site has run for a couple of years now, but occasionally crashes. Now, it’s been down now for a couple of months. Motivated by this, I’ve started to investigate the possibility of simplifying the tooling, separating the backend and frontend and migrating that site over to GitHub pages.

Gulp logo

The first step is the tooling. We want some tasks that take the source code and transform it into a static web page. We also want each subpage to support React components. To do this transformation I decided to use Gulp. One of many task runners out there. In Gulp 3.9.1 you define tasks using ECMAScript 5 (JavaScript ES5). However in Gulp 4 you’ll be able to do so with ES2015 (JavaScript ES6). Below you can find a small recipe on how to utilize ES2015 with Gulp.

New Project Using Gulp with ES2015

  • Create a new project by npm init
  • Install gulp v4:
    npm install gulpjs/gulp.git#4.0
    
  • Install Babel:
    npm install --save-dev babel-register babel-preset-es2015
    
  • Create a .babelrc file, and add:
    {
    "presets": [ "es2015" ]
    }
    
  • Place your gulp tasks in a file named gulpfile.babel.js, to avoid some potential issues.

You’ll now be able to define tasks using ES2015! For instance, you can use const, let and import. In addition you can define tasks using named functions. A lot of details can be found in Gulp’s v4 branch README file.

Pitfalls

Trying to convert gulp tasks from various ES5 samples can be challenging. They’ve changed the task execution system in Gulp v4. Previously you had to specify the order of execution by adding dependencies to the task’s method signature. For example in task, gulp.task('build', ['clean', 'concat']), the task clean and concat have to finish before the build task can start. In Gulp v4, you instead specify the order of execution by using gulp.parallel and gulp.series. This article explains how to specify dependencies for a Gulp v4 task well.

Sample

This weekend’s effort can be found on my GitHub page. The result is a very primitive static web page generator that supports React components, where Gulp tasks have been written with JavaScript ES2015. The repository can be found here

Software Development Timesaver #2

Command-line interface shortcuts can be real timesavers. I use the Atom text editor frequently for projects, or changing text files. It’s fast and versatile. If you’re using Git from your command-line interface, this tip can save you some time opening Atom to the correct project directory.

Basically, if you usually navigate around your file system using command-line, having a way to open Atom to your working directory would be great. This will save you time, since you avoid having to deal with navigating in the pesky GUI file dialog.

Simply, cd into the folder you want opened in Atom, and write:

atom .

That’s all. Atom will start and have every file and subdirectory available in the left-hand-side Project view. Furthermore, you can also open a file in Atom with the same method, by replacing the dot with a path to a file. For instance atom ./example.txt.

Steam Controller with Unity

My current Unity game is a 4 player couch game. It’s a turn based ball game, where each player tries to knock another player’s ball into a hole. Whose turn it is to control the ball is of course decided by a virtual match of rock paper scissor. The input device each player will use is therefore a game controller. Unfortunately, I only have Steam controllers, which turned out to be a bit harder to use with the Unity Editor, because the Steam controller works best within the Steam application. It is, however, possible to make them work as gamepads inside the Unity Editor.

The trick is to add Unity as a non-Steam game to your Steam library.

Use Steam Controller in Unity Editor Recipe

1. Add Unity to your Steam library

  • Open Steam
  • Find Games in the Menu bar.
  • Click Add a Non-Steam Game to My Library...

Add non-steam game to Steam

  • A browser will appear. Here you can either scroll to find Unity in the list of programs, or browse to find Unity. On Windows, Unity is often located at C:\Program Files\Unity\Editor\Unity.exe

Add Unity to library

2. Configure the Steam Controller

  • After you’ve added Unity to your Steam library, open Big Picture.
  • Make sure your Steam controller is on, and connected to Steam.
  • Find Unity in the library, and open it.
  • Then, open Controller Configuration

Start Unity from Steam library

  • Change the controller configuration to Gamepad. The configuration can be found in Templates.

Start Unity from Steam library

3. Open Unity from Steam

  • Then you’re done. You are now able to use your Steam Controller as a regular joystick input device inside the Unity Editor. Just remember to open Unity from your Steam library.

Steam Unity demonstration