fix(client): add cache-busting hashes to chunks (#37746)

* fix(client): add cache-busting hashes to chunks

* fix: create cache-busting names for the workers

Prior to this PR the first webpack compilation gave the workers static
names.  This can cause caching problems, so this PR adds hashes to
their names to invalidate the cache.

In order for Gatsby to find them, the names are added to the
config directory.
This commit is contained in:
Oliver Eyton-Williams 2019-11-14 21:13:44 +01:00 committed by mrugesh
parent c4dc0b297f
commit 687c4fdb98
5 changed files with 34 additions and 6 deletions

3
client/.gitignore vendored
View File

@ -4,6 +4,9 @@ node_modules
yarn-error.log
config/env.json
config/frame-runner.json
config/sass-compile.json
config/test-evaluator.json
# Build directory
/public

View File

@ -18,6 +18,10 @@ import protect from 'loop-protect';
import * as vinyl from '../utils/polyvinyl.js';
import createWorker from '../utils/worker-executor';
// the config files are created during the build, but not before linting
// eslint-disable-next-line import/no-unresolved
import { filename as sassCompile } from '../../../../config/sass-compile';
const protectTimeout = 100;
Babel.registerPlugin('loopProtection', protect(protectTimeout));
@ -89,7 +93,7 @@ export const babelTransformer = cond([
[stubTrue, identity]
]);
const sassWorker = createWorker('sass-compile');
const sassWorker = createWorker(sassCompile);
async function transformSASS(element) {
const styleTags = element.querySelectorAll('style[type="text/sass"]');
await Promise.all(

View File

@ -8,9 +8,15 @@ import {
createMainFramer
} from './frame';
// the config files are created during the build, but not before linting
// eslint-disable-next-line import/no-unresolved
import { filename as runner } from '../../../../config/frame-runner';
// eslint-disable-next-line import/no-unresolved
import { filename as testEvaluator } from '../../../../config/test-evaluator';
const frameRunner = [
{
src: '/js/frame-runner.js'
src: `/js/${runner}.js`
}
];
@ -91,7 +97,7 @@ export function getTestRunner(buildData, proxyLogger, document) {
function getJSTestRunner({ build, sources }, proxyLogger) {
const code = sources && 'index' in sources ? sources['index'] : '';
const testWorker = createWorker('test-evaluator', { terminateWorker: true });
const testWorker = createWorker(testEvaluator, { terminateWorker: true });
return (testString, testTimeout) => {
return testWorker

View File

@ -1,8 +1,11 @@
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { writeFileSync } = require('fs');
module.exports = (env = {}) => {
const __DEV__ = env.production !== true;
const staticPath = path.join(__dirname, './static/js');
const configPath = path.join(__dirname, './config');
return {
mode: __DEV__ ? 'development' : 'production',
entry: {
@ -13,8 +16,18 @@ module.exports = (env = {}) => {
devtool: __DEV__ ? 'inline-source-map' : 'source-map',
output: {
publicPath: '/js/',
chunkFilename: '[name].js',
path: path.join(__dirname, './static/js')
filename: chunkData => {
// construct and output the filename here, so the client can use the
// json to find the file.
const filename = `${chunkData.chunk.name}.${chunkData.chunk.contentHash.javascript}`;
writeFileSync(
path.join(configPath, `${chunkData.chunk.name}.json`),
`{"filename": "${filename}"}`
);
return filename + '.js';
},
chunkFilename: '[name].[contenthash].js',
path: staticPath
},
stats: {
// Display bailout reasons

View File

@ -49,6 +49,8 @@ const {
createPoly
} = require('../../client/src/templates/Challenges/utils/polyvinyl');
const testEvaluator = require('../../client/config/test-evaluator').filename;
const oldRunnerFail = Mocha.Runner.prototype.fail;
Mocha.Runner.prototype.fail = function(test, err) {
if (err instanceof AssertionError) {
@ -327,7 +329,7 @@ async function createTestRunnerForJSChallenge({ files }, solution) {
const { build, sources } = await buildJSChallenge({ files });
const code = sources && 'index' in sources ? sources['index'] : '';
const testWorker = createWorker('test-evaluator', { terminateWorker: true });
const testWorker = createWorker(testEvaluator, { terminateWorker: true });
return async ({ text, testString }) => {
try {
const { pass, err } = await testWorker.execute(