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!
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:
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
3. Third, we’re going to create a “dist” folder. This is where our compiled output will go.
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.
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.
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:
Installing dependencies via Yarn/NPM
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.
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
I added the following import and export code to the file.
I wrapped the main logic in this file inside of a function that can be imported.
Now, via the command line, I can run
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.
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.