Have you ever wondered if the file you’re been served from the server is up to date ? Why would you ?…
Not so long ago, you might have been programming in php and when something went wrong, the first thing you would say was “Try to clear your browser’s cache”.
Now that our assets filenames are hashed by default by bundlers like webpack, you could think that we shouldn’t run into such problems anymore. Since the filename of js/html (or any other files) will change based on its content, it will force the browser to retrieve the freshest version.
But between you and the server, there could be proxies / caching systems (like varnish / memcached). And more recently, on the client-side, we have ServiceWorkers that let us enable caching strategies.
So, to be 100% sure of which version of the site I’m running, for a few years now, I’ve been using a little routine that adds metadatas into the main generated files, based on:
- infos inside the
package.json
(name, description, version, author, license) - git hash
- date of the generation of the build
Example on an index.html:
<html>...</html><!--!
*
* my-react-app-starter
*
* create-react-app based project with a few pre-configured / installed features such as eslint or prettier
*
* @version v1.0.0 - 2018-06-14T17:28:30+02:00
* @revision #640ba4d - https://github.com/topheman/my-react-app-starter/tree/640ba4df20e3452acd2dd10b0f746a8300af0749
* @author Christophe Rosset <tophe@topheman.com> (http://labs.topheman.com/)
* @copyright 2018(c) Christophe Rosset <tophe@topheman.com> (http://labs.topheman.com/)
* @license MIT
*
-->
That way, you can be sure of date / version (and other infos) of the generated file you’re been served with a simple curl.
Implementation
Whether you use create-react-app or have direct access to the webpack.config, first, copy/paste this common.js file to the root of your project, then:
npm install --save-dev moment git-rev-sync
Using create-react-app
I’ll explain bellow the implementation that you can see in this diff.
1) Copy/paste the following in a bin/expand-metadatas.js
file in your project:
const { getBanner, getInfos } = require("../common");
process.env.REACT_APP_METADATAS_BANNER_HTML = getBanner("formatted");
process.env.REACT_APP_METADATAS_VERSION = getInfos().pkg.version;
2) Add --require ./bin/expand-metadatas.js
to your package.json
, that way, react-scripts
will require bin/expand-metadatas.js
before running and inject REACT_APP_METADATAS_BANNER_HTML
and REACT_APP_METADATAS_VERSION
as env vars:
"scripts": { "start": "react-scripts --require ./bin/expand-metadatas.js start", "build": "react-scripts --require ./bin/expand-metadatas.js build", "test": "react-scripts --require ./bin/expand-metadatas.js test --env=jsdom", "eject": "react-scripts eject" }
3) At the end of public/index.html
, append:
<!--!%REACT_APP_METADATAS_BANNER_HTML% -->
You can also access process.env.REACT_APP_METADATAS_VERSION
in the code of your app (to show the version number for example).
Using the webpack.config
Like in topheman/webpack-babel-starter, you can require common.js
from your webpack.config and:
– access getBanner / getBannerHtml / getInfos
– use the return values with the HtmlWebpackPlugin
Conclusion
Next time your build is deployed on a server and you’re being told that your release doesn’t work, a simple curl will settle it … The front is not the problem ! 😉
Resources: