bemusic / bemuse

⬤▗▚▚▚ Web-based online rhythm action game. Based on HTML5 technologies, React, Redux and Pixi.js.
https://bemuse.ninja/
GNU Affero General Public License v3.0
1.15k stars 147 forks source link

Remove webpack-progress hack #524

Closed dtinth closed 5 years ago

dtinth commented 5 years ago

Motivation

In the previous versions of Bemuse, I wanted to display a loading indicator that showed the loading progress of Bemuse’s JavaScript bundle, similar to loading screens in games built using Macromedia Flash.

To be able to do this, I used a pretty elaborate hack.

When webpack generates a bundle, it includes in the main chunk, the runtime code that contains the logic to download other chunks. webpack loads a chunk by creating <script> tags pointing to the JS file, and insert it into <head>:

head.appendChild(script);

To monitor the download progress, I have to intercept the script loading process. I am able to do this by writing a webpack plugin that patches the runtime code to allow application code to override how chunks are loaded:

// A webpack plugin that hacks the webpack JSONP template
// to allow introspection of script download progress.
//
module.exports = function ProgressPlugin() {
  return function ProgressPluginInstance() {
    this.plugin('compilation', function(compilation) {
      compilation.mainTemplate.plugin('require-ensure', function(result) {
        result = result.replace('head.appendChild(script);', function() {
          return (
            'window.WebpackLoadingContext ? ' +
            'window.WebpackLoadingContext.load(script, head) : ' +
            'head.appendChild(script);'
          )
        })
        return result
      })
    })
  }
}

Now, before the main chunk downloads the subsequent chunks, it overrides webpack chunk download logic. Instead of download the chunk normally by placing a <script> tag into <head>, the overridden logic downloads the JavaScript chunk using XMLHTTPRequest.

This allows the loading progress to be monitored. Once the file has been downloaded, the downloaded data gets converted into a blob: URL and added as a <script> tag to the <head>.

This little hacked works well since webpack 1 and still works today with no modifications.

However, now that we are using webpack 4, there are few complications:

Now I've seen that displaying the loading progress bar for the app bundle is not a widely-used practice anymore, keeping this hack around adds to the maintenance costs of this project, so I decided to remove this hack.

The loading screen has also been modernized a bit.

codecov-io commented 5 years ago

Codecov Report

Merging #524 into master will not change coverage. The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #524   +/-   ##
=======================================
  Coverage   81.38%   81.38%           
=======================================
  Files         153      153           
  Lines        4619     4619           
  Branches       68       68           
=======================================
  Hits         3759     3759           
  Misses        842      842           
  Partials       18       18

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 2d8641f...da5e7e4. Read the comment docs.