Migrating a poorly written web app to use Webpack and Babel

I play a lot of Pokemon GO! To help me on the road I built a Type Effectiveness checking site called Poketype! (Poketype on GitHub) It’s a simple site and, having come from a company that primarily used jQuery, I decided to write it all in Vanilla JS. This was a bad idea! Note to self: use React next time!

Oh well. Having a pile of trash as a base is a good way to demonstrate how to add WebPack and Babel to a JavaScript project as we’ll undoubtedly go through many trials and tribulations on our journey. Let’s begin!

What are we trying to achieve?

This project was a quick hack-job that I’m not proud of. I’m going to break up the main spaghetti code poketype.js file into smaller, more readable files that will use the import/export keywords, and Babel will be tossed into the mix to ensure this runs on as many devices as possible.

Installing Webpack and Babel

Webpack and Babel will be our weapons of choice here. Webpack is our build tool, and Babel is our transpiler. I’ve done the hard yards and have come up with the following foundation to start working from:

1. First, we’re going to install Webpack, Webpack plugins and loaders, and Babel. I use yarn, you can use npm if you prefer.

Our project looks like this:

Screen Shot 2018-03-23 at 10.04.32 am

2. Second, we’re going to create a “src” folder at the top level and move the majority of our project into it. I even created a html folder for index.html

Screen Shot 2018-03-23 at 10.24.40 am

3. Third, we’re going to create a “dist” folder. This is where our compiled output will go.

Screen Shot 2018-03-23 at 10.25.28 am

Alright! We’ve broken our project, nice!! Time to get it working again. We’ve set up the file structure, now it’s time to tell Webpack what to do.

Configuring Webpack

The following gists will be serving as the base from which my Webpack projects will work from in the future. Side note – The fact that Webpack allows unlimited configuration is a huge negative! An opinionated build tool would be preferable.

Alright, we’re going to create three files at the root level. Code omitted from the article for size reasons. Click the links to see the files. To fully understand what is going on, please read and work through the Webpack Guides.

webpack.common.js
webpack.dev.js
webpack.prod.js

Screen Shot 2018-03-23 at 10.58.16 am

We’re also going to update our package.json file with some build commands. Note the “scripts” key, and the “build” and “build-prod” keys. This will enable us to run “yarn run build” or “yarn run build-prod”

Ok. This is configuration finished! However, I’m not game to run these commands as the project isn’t ready for them yet. Let’s continue.

Understanding the way forward

It’s time to understand the MINIMUM amount of changes necessary to ensure our project builds. Let’s start with understanding how our project currently works, and then how it needs to work to be successfully built by Webpack.

Currently our “entry point” is index.html (link to the exact version). We have dependencies on multiple CSS files loaded in the <head> tag, and dependencies on multiple .js files loaded at the bottom of the <body> tag. We also have the app initialisation logic in it’s own tag as well. We also have the rest of the HTML which we can’t forget about.

Two js dependencies are on libraries that are available as npm packages: lodash and choices.js. For the sake of consistency, We will swap to using the npm package instead of the manually downloaded version.

Our project needs to have a new entry point, which is defined as “./src/index.js” in webpack.common.js.
In this new file we must:

  • import from the js files,
  • require the CSS files,
  • and execute the main app logic

In addition to the new entry point, we need to persist the remaining HTML in a new file “./src/index.template.ejs” which is also defined in webpack.common.js.

Making the minimum required changes

Our project structure is currently this:

Screen Shot 2018-03-23 at 11.33.11 am

Installing dependencies via Yarn/NPM

index.template.ejs

.ejs stands for “embedded javascript“. We’ll keep this simple by copying everything from index.html into index.template.ejs.

We know that Webpack is going to build a dependency graph starting from index.js and generate a bundle which will be inserted as a tag at the bottom of the <body> element.
Using this knowledge, let’s comment out all <link rel=”stylesheet” href=”…”> and <script> tags.

index.js

This is where our app initialisation logic will be stored, so let’s move that from index.html to here.

In the previous step we identified the following code that needs to be imported:

  • class “PokeType” from poketype.js
  • the logic from register-sw.js as a new function
  • The file choices.min.css
  • The file style.css

This will give us the following code

poketype.js

I added the following import and export code to the file.

register-sw.js

I wrapped the main logic in this file inside of a function that can be imported.

Building

Now, via the command line, I can run

yarn build

and just like that, we’re ready to go! Well, almost. One last change to our server.js file and then we’re good to go. Our endpoint of /poketype/ needs to internally point to /poketype/dist/ to serve files correctly.

Finishing up

The project is now at a stage where I can begin deployment testing first before beginning to move on to refactoring and splitting up my spaghetti codebase.

A keen eye will have noticed that a ServiceWorker was being used. How I get that back up-and-running again will be the subject of another post in the future.

Advertisements

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 )

Google+ photo

You are commenting using your Google+ 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

This site uses Akismet to reduce spam. Learn how your comment data is processed.