Reactgo: Deployment in production to reload cached files in user's browsers

Created on 3 Feb 2017  路  12Comments  路  Source: reactGo/reactGo

Overview

Related issues: https://github.com/reactGo/reactGo/issues/361, https://github.com/reactGo/reactGo/issues/282

Details

Long-term cache is a huge issue for us, not have to update file names on every new deployment manually. I'm on this for two days already and can't figure it out due to my limited Webpack knowledge. Same as in #282, I successfully generate assets.json.

Currently, I'm using https://gist.github.com/mhlavacka/ac348ac6fa139491bb5b1b92c4e8cca9 to rewrite file names directly in the files, but then there are different filenames on the server and on the browser what results in 404 error.

Question

How do you guys solve this for your demo site: https://demo-reactgo.herokuapp.com/? Are there any other ways to solve this?

Most helpful comment

@mhlavacka That's definitely a valid concern!

I raised it in https://github.com/reactGo/reactGo/issues/735 as well. We can use an webpack manifest plugin to grab the file names, https://github.com/danethurber/webpack-manifest-plugin

I'm in the midst of the webpack 2 refactor, but I can hopefully smash that out and then do a PR to do long term caching as an example if that helps!

All 12 comments

@mhlavacka That's definitely a valid concern!

I raised it in https://github.com/reactGo/reactGo/issues/735 as well. We can use an webpack manifest plugin to grab the file names, https://github.com/danethurber/webpack-manifest-plugin

I'm in the midst of the webpack 2 refactor, but I can hopefully smash that out and then do a PR to do long term caching as an example if that helps!

Thanks for a quick response and good work! I'm all up for it 馃挴 .

I managed to successfully implement hashing using rewrite function mentioned in the former post, but it's super hacky solution. Hopefully will be to switch to your more practical solution eventually.

This will be what I'm working on next, now that webpack 2 is in! 馃帀

@choonkending, good news! Might I suggest looking into dll plugins if you haven't already? It's (subjectively) a bit more involved than multiple entries + common chunks, but it's probably more reliable for long term caching, and it has the super nice side-effect of speeding up build times (a lot potentially)

@GGAlanSmithee thanks for the PR and the suggestion. I was reading up on it yesterday. However my one concern is whether or not it's supported with webpack 2( it's not on the webpack.js.org) page documentation.

Other than that I'm definitely gonna be referring to your document when making this work.

@choonkending It's definitely supported in webpack 2 because I've used it. IMO it's quite opiniated though, and require some housekeeping to use. I will try and send a PR using code-splitting and common chunks which is a less opiniated and less intrusive alternative.

No elegant solution so far?

@IharKrasnik There are a couple of PRs open I have meant to review. Possibly apply a solution thanks to the brilliant @GGAlanSmithee

Analysis - How I am reasoning this out

We wish for long term caching for our static assets, a must-have in production environments. Currently we do not cache bust our Javascript assets in our demo site, as shown with this line. Our code pushed to Heroku is still up to date because Heroku sets

Cache-Control:public, max-age=0

Running in production though is another story, as we wish to cache as much as possible to save resources. Certain companies will even cache static assets for up to one year, i.e.

Cache-Control:public, max-age= 31468444

Solution

To fully utilise cache-busting with webpack, we would:

  1. Add a [chunkhash] to each file name in our webpack configuration
  2. Generate a chunk manifest json file
  3. Inline the values generated from the manifest JSON file when rendering our HTML response. The code to change would be here

1: Use webpack manifest plugin without code splitting

A straight forward (and possibly naive) solution would be to generate the chunk manifest using a plugin such as Webpack Manifest Plugin.

馃憤 Straight forward - easy to implement
馃憥 Anytime any bit of code changes, we will generate an entire new chunk hash. Most vendor code (react) might not change as often as our app code, thus we are not fully leveraging caching because users still have to download the entire app.js file.

2: Use webpack manifest Plugin + CommonChunksPlugin

Split our code using CommonsChunkPlugin

馃憤 Webpack automatically identifies which code to put in the shared bundle
馃憤 You can force specific libraries into a 'commons' chunk - which can be cached for longer
馃憤 Only 1 webpack configuration
馃憥 CommonsChunk recompiled every time you run webpack - 馃悽

3: Use webpack DLL Plugin

馃摉 DLL is short for Dynamically Linked Library which is a feature for native Windows applications that solves the same problem.

馃憤 Fast build times (full and incremental) - compile library bundles separately from the application bundle
馃憥 Two separate configuration files
馃憥 Shared libraries (included by many DLLs) are included many times @GGAlanSmithee
馃憥 My understanding is that we would have to manually figure out which are the DLLs you want using a stats analyzer, following the approach here

馃

I am still torn between 2 and 3.

I am leaning towards 2 as a solution. Mainly because I do not see users knowing which "file" to decide to be a library DLL, i.e. it involves understanding how to determine which libraries are "entrypoints" to a project. As a project grows with more developers, do we see ourselves regularly visiting this?

It really depends on how stable our major vendor dependencies will be. I value fast build times. Any thoughts? @psimyn @ZeroCho @slavab89

References

  1. Long term caching of static assets with webpack
  2. Webpack Manifest Plugin
  3. Webpack DLL Plugin
  4. Optimizing your webpack builds

Given I've already implemented Option 2 before in another project. I will try Option 3 based on this https://github.com/reactGo/reactGo/pull/823 PR.

I've ended up with an initial PR with option 1, which I think is pretty solid. Once it's merged, it will be easy to work on either option 2 or 3.

https://github.com/reactGo/reactGo/pull/867

Was this page helpful?
0 / 5 - 0 ratings

Related issues

elitekode picture elitekode  路  8Comments

davidychow87 picture davidychow87  路  4Comments

slavab89 picture slavab89  路  6Comments

choonkending picture choonkending  路  8Comments

newasmod picture newasmod  路  4Comments