Number Quest - Using Django + webpack + p5

Nov 11 2018

Picture here

I've recently completed a fairly large and time consuming project; Number Quest.
You can find a link to it in the navigation bar above.


During the project I faced a lot of different challenges, so I won't go into details regarding all of them, but I will cover a few of the more important lessons I learned.


If you look at the project, you'll notice that it's not particularly complicated, however the methods that I used to construct it were certainly different to the methods I have employed in the past. I built this project using Django to set up the back-end, JavaScript ES6 modules to build the front-end, these modules were managed via webpack and on top of that I included the p5.js library to speed up the canvas animation creation. All of these separate entities had to be properly bound together to allow them to work and communicate effectively.


In my previous post I went through how I connected webpack and Django thanks to a tutorial by Chong Kim, https://www.youtube.com/watch?v=A2vEazcfJ7U which was a great reference and starting point. I still had to customize a few things, like creating multiple HTML pages that are managed by multiple webpack bundles. Again, I must thank Chong Kim for his hints and help. I included multiple entries in the webpack.config.js file as per the documentation, but for some reason I wasn't seeing multiple outputs in my dist folder.....the reason for this is a bit of a sad one: I was using hot-loading with webpack and just running 'run start', which never gave webpack the chance to re-build my changes. I eventually noticed this and once I ran 'run build' first, everything worked as required and I could even continue using hot-loading afterwards.


I'll continue with webpack challenges even though I faced these towards the end of the project. I created a production config file that incorporated the use of plugins (MiniCssExtractPlugin and CleanWebpack plugin) the reason I stayed away from Uglifyjs plugin is that production mode does this automatically and after all the other messing around I went through I didn't want to manually configure it too. I also learned about chunks and used the optimization option. I remember this initially caused me difficulty. The reason for wanting to use chunks is because my p5.js library had to be included as a module to get my animations to work. It was a HUGE file..3MB..and after sifting the net and GitHub I finally figured out that there were issues with the p5.sound files that prevented using the minified version of p5 (which is about 400kB, not great, but still a marked improvement). All of these problems were intertwined and I had to go through the spaghetti to figure it out. But eventually I did. I had used some pretty hack techniques to get the project to work initially and it took a while to clean everything up. I was calling p5 through my HTML files directly, which was unnecessary and I wasn't using node_modules to do that either. The only place you need to import p5 is the index file so you can call something like "new p5(sketch)" --sketch is your JavaScript file where you setup/draw your canvas.


To get p5 to play with webpack, just use npm to include it in your node_modules and webpack will recognise it. Make sure to include "@types/p5" through npm as well. I couldn't get it to work without it.


I included Audio in this project. It led to another important lesson: knowing where the server fetches files from e.g. from the static folder or the webpack hot-loader port 8080? This was painful too. Eventually, I figured things out. Initially, my sounds didn't play because the server was trying to fetch them from a different port using webpack. I decided to include the sound scripts in the HTML directly and then reference them in my JS files. This method worked because I could manually specify the file's location, which was nice because I could easily change that location later when I uploaded the project to the server. I used Django's 'static' input in HTML to specify each sound file's location (e.g. var audio = "{% static 'audio.mp3' %}") and made sure that I included "STATICFILES_DIRS = ['dist', 'sounds']" in settings.py. This is very handy as Django will automatically take the contents of your dist folder (and any other folder you specify) and include them in the 'static' folder it creates when you run the command "collectstatic" - that folder is then used by the server to fetch your static files.
Before I figured out that this was a fairly basic problem, I researched MIMS, file types and browser incompatibility because I thought the issue was with whether my file was an mp3 or wav type...like I said...painful.


Other quick lessons learned along the way:
How HTML divs work to split up the page vertically.
The "body" element is connected to it's parent, the "html" element and you need to make sure that both of these elements have their width set to 100% if you want to make responsive pages.
The p5.position function messed me up. I didn't need it at all.


NOTES FOR WEBPACK:
If you want to test the site in development:
1) In urls.py uncomment url(r'^homedev/', app.views.homedev, name="homedev") and url(r'^resultdev/', app.views.resultdev, name="resultdev").
2) In package.json remove --config webpack.production.config.js.
3) In settings.py change STATIC_URL to 'http://127.0.0.1:8080/'.
4) Run npm run build in terminal. This will create the main.js and main2.js files that are used in homedev and resultdev html files and served via 8080 port.
5) Run npm run start for hotloader. Make any required changes this way.
6) Once finished swap back to production mode (include --config webpack.production.config.js again) Run npm run build again, which will clean up the dist folder due to CleanWebpackPlugin. Make sure that the scripts in the main html files have been updated with these new main.[hash].js files and that's it. Deploy to server.


Well, this was a steep learning curve, but I managed.