This article is the second entry of a devlog on my participation to js13k competition with MogSogeking
As we start developing our game, there are some tasks we want to avoid doing manually like:
- reloading our game each time we do some change;
- creating our submission file;
- checking if we reach the 13k limit;
- deploying our game to a public url (it is nice to gather feedback during development);
Before choosing a tool to help us achieve the tasks listed above it is important to know how our code must be structured. Here is the rule of js13k competition about the folder structure.
Your .zip package should contain index.html file in the top level folder structure
Our entry point must be an index.html file that loads our JavaScript files. Parcel is a web application bundler that works with a html file as entry point. It requires almost no configuration. It seems to fit our needs so let's give it a try.
Firstly, we install this new development dependency in our project.
Development server
npm install --dev parcel-bundler
As explained in the getting started section of the documentation, the default command of the cli launchs a development server. It will rebuild our game each time we change a file and refresh the JavaScript code opened in the browser (without reloading the whole page!). We add a dev
script to avoid typing this command each time we need it.
"scripts": {
"dev": "parcel src/index.html"
},
Let's create a few files to test it. Here is our folder structure:
.
├── package-lock.json
├── package.json
└── src
├── index.html
└── index.js
Our index.html
file import our JavaScript code with a script
tag.
<html>
<body>
<script src="./index.js"></script>
</body>
</html>
To begin we add the well known Hello world!.
console.log('Hello world!')
We start our dev server with the following command:
npm run dev
We should see a log Hello world!
in our browser console. I change the message in our console.log parameter with my first name and save the file.
console.log('Hello Yvonnick!')
Our browser has reloaded our code automatically and display the updated log 🎉
Submission file
Our development server is set up. We need to generate our submission file which is a zip file containing our index.html, JavaScript files and other assets.
build
The js13k rules says we can optimize our JavaScript code.
You can use tools that minify JavaScript source code.
Parcel cli has a build command for this purpose. We add a few options to make it fill our needs.
"scripts": {
"dev": "parcel src/index.html",
"build": "parcel build src/index.html --no-source-maps --experimental-scope-hoisting --public-url ./",
},
Let's get some explanations about these options.
--public-url option
Parcel prefixes the filename of the bundled javascript file with public-url
in the index.html
script tag. This option defaults to /
. It is fine for a website stored on a static server.
when unzipped should work in the browser.
If we try to open the built index.html
we will see a blank page. Because the path of our JavaScript file is /src.9905d997.js
. It will look for our JavaScript file at system root. Setting public-url
to ./
will fix this issue since it will look for our JavaScript file in the current folder. Now, it works just fine when we open the built index.html
.
--no-source-maps option
Source maps are files which reference a readable version of production that are most of the time minified. It helps us tracking bugs in our production bundle. Since our final zip size matters we don't want to include unnecessary files in it so we disable this feature.
--experimental-scope-hoisting option
This option enables tree shaking during the build process. Tree shaking is a feature that prevents unused code of our dependencies being part of our production bundle. You can find out more in this article of Devon Govett.
zip
At last, we add a zip
script which creates a zip file with the content from dist
folder that is the output of our build
command.
"scripts": {
"dev": "parcel src/index.html",
"build": "parcel build src/index.html --no-source-maps --experimental-scope-hoisting --public-url ./",
"zip": "zip -r submission.zip dist"
},
Now, we can create our submission file using scripts 👌
Adding a CI/CD
There are two last points to deal with:
- checking if we reach the 13k limit
- deploying our game to a public url (it is nice to gather feedback during development)
We don't want to figure out at the end of the competition that our submission file doesn't not fit the requirements. We don't want either to type our commands manually each time we commit some change. Since we need to host our source code on Github we will use GitHub Actions to automate it.
Please provide two sources of your game - first one should be minified and zipped to fit in the 13 kB limit (sent via the form) and the second one should be in a readable form with descriptive variable names and comments (hosted on GitHub).
I wont explain how GitHub Actions works but you can find a lot of nice articles on dev.to on this topic.
Checking our submission file size
First of all, we need to add a script that checks our submission file size. We will use bundlesize to achieve it. It needs a bit of configuration (the file path to test, the max size it must not reach). We add it directly in our package.json
file.
"bundlesize": [
{
"path": "submission.zip",
"maxSize": "13 kB"
}
],
Then, we add a size
script that calls bundlesize
. It will throw an error if the zip file weight more than 13 kB.
"scripts": {
// ...
"size": "bundlesize"
}
We create a first action in the file .github/workflows/ci.yml
that will call our freshly created size
script with the following content:
name: CI
on:
pull_request:
jobs:
size:
runs-on: ubuntu-latest
env:
CI: true
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: 12
- run: npm ci
- run: npm run build
- run: npm run zip
- run: npm run size
We trigger this action only on pull request.
on:
pull_request:
We create the zip file.
- run: npm ci
- run: npm run build
- run: npm run zip
Finally, we run our size
script which will prevent us to merge if it fails.
- run: npm run size
Now, our CI checks for us our submission file size at each commit on pull request.
Deploying our game
Cherry on the cake, we want to deploy our game on a public url so we can share it with friends to gather feedback during development. We create our second action in the file .github/workflows/deploy.yml
with the following content:
name: Deploy
on:
push:
branches:
- master
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: npm ci
- run: npm run build
- uses: JamesIves/github-pages-deploy-action@3.5.9
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages # The branch the action should deploy to.
FOLDER: dist # The folder the action should deploy.
We trigger this action only on master branch.
on:
push:
branches:
- master
We use the action github-pages-deploy-action from James Ives which deploy our code on GitHub Pages. Our app will be available at the url https://[your-handle].github.io/[repository-name]
in my case https://frinyvonnick.github.io/js13k-2020.
We are all set 🙌 We can now develop our game at peace!
Follow me on dev.to or twitter if you want to be informed when a new blogpost of this serie is published!
Top comments (2)
That's a great workflow :)
One thing that could benefit you is to have the feedback on your development environment. This way, you don't have to wait for your CI to run to know that your bundle is too large !
You could achieve that with a git hook for instance.
Sure, this is a great idea, thank you 👌