mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-12-11 16:21:04 -05:00
Merge pull request #8036 from scratchfoundation/webpack5
Upgrade to webpack 5
This commit is contained in:
commit
f75e145139
12 changed files with 7820 additions and 7693 deletions
23
.babelrc
23
.babelrc
|
@ -1,9 +1,22 @@
|
||||||
|
// .babelrc is an alias for .babelrc.json and uses JSON5 syntax
|
||||||
{
|
{
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"transform-async-to-generator",
|
"@babel/plugin-transform-async-to-generator",
|
||||||
"transform-object-rest-spread",
|
"@babel/plugin-transform-object-rest-spread",
|
||||||
"transform-require-context",
|
"@babel/plugin-syntax-dynamic-import",
|
||||||
"syntax-dynamic-import"
|
"transform-require-context"
|
||||||
],
|
],
|
||||||
"presets": ["es2015", "react"],
|
"presets": [
|
||||||
|
[
|
||||||
|
"@babel/preset-env",
|
||||||
|
{
|
||||||
|
"bugfixes": true,
|
||||||
|
|
||||||
|
// This papers over the fact that our current code is inconsistent
|
||||||
|
// For example, we sometimes use `import` with a file that exports with `module.exports`
|
||||||
|
"modules": "commonjs"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@babel/preset-react"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
extends: ['scratch', 'scratch/node'],
|
extends: ['scratch', 'scratch/node', 'scratch/es6'],
|
||||||
plugins: ['json']
|
plugins: ['json']
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
|
|
||||||
const https = require('https');
|
const https = require('https');
|
||||||
|
|
||||||
let environment = process.env.SCRATCH_ENV || 'unknown environment';
|
const environment = process.env.SCRATCH_ENV || 'unknown environment';
|
||||||
|
|
||||||
let branch = process.env.CIRCLE_BRANCH || 'unknown branch';
|
const branch = process.env.CIRCLE_BRANCH || 'unknown branch';
|
||||||
|
|
||||||
let urlEng = process.env.SLACK_WEBHOOK_ENGINEERING;
|
const urlEng = process.env.SLACK_WEBHOOK_ENGINEERING;
|
||||||
let urlMod = process.env.SLACK_WEBHOOK_MODS;
|
const urlMod = process.env.SLACK_WEBHOOK_MODS;
|
||||||
let urlNotifications = process.env.SLACK_WEBHOOK_CIRCLECI_NOTIFICATIONS;
|
const urlNotifications = process.env.SLACK_WEBHOOK_CIRCLECI_NOTIFICATIONS;
|
||||||
|
|
||||||
let announcement = {text: `scratch-www has deployed branch ${branch} to ${environment}.`};
|
const announcement = {text: `scratch-www has deployed branch ${branch} to ${environment}.`};
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -20,11 +20,11 @@ const options = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const postMessage = (url, message, channelName) => {
|
const postMessage = (url, message, channelName) => {
|
||||||
let data = JSON.stringify(message);
|
const data = JSON.stringify(message);
|
||||||
const req = https.request(url, options, res => {
|
const req = https.request(url, options, res => {
|
||||||
console.log(`statusCode: ${res.statusCode}`); // eslint-disable-line no-console
|
console.log(`statusCode: ${res.statusCode}`); // eslint-disable-line no-console
|
||||||
if (res.statusCode === 200) {
|
if (res.statusCode === 200) {
|
||||||
process.stdout.write(`announced to ${channelName}\n` + JSON.stringify(message) + '\n');
|
process.stdout.write(`announced to ${channelName}\n${JSON.stringify(message)}\n`);
|
||||||
} else {
|
} else {
|
||||||
process.stdout.write(`FAILED to announce to slack`);
|
process.stdout.write(`FAILED to announce to slack`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
var async = require('async');
|
const async = require('async');
|
||||||
var defaults = require('lodash.defaults');
|
const defaults = require('lodash.defaults');
|
||||||
var fastlyConfig = require('./lib/fastly-config-methods');
|
const fastlyConfig = require('./lib/fastly-config-methods');
|
||||||
const languages = require('scratch-l10n').default;
|
const languages = require('scratch-l10n').default;
|
||||||
|
|
||||||
var routeJson = require('../src/routes.json');
|
const routeJson = require('../src/routes.json');
|
||||||
|
|
||||||
const FASTLY_SERVICE_ID = process.env.FASTLY_SERVICE_ID || '';
|
const FASTLY_SERVICE_ID = process.env.FASTLY_SERVICE_ID || '';
|
||||||
const S3_BUCKET_NAME = process.env.S3_BUCKET_NAME || '';
|
const S3_BUCKET_NAME = process.env.S3_BUCKET_NAME || '';
|
||||||
|
|
||||||
var fastly = require('./lib/fastly-extended')(process.env.FASTLY_API_KEY, FASTLY_SERVICE_ID);
|
const fastly = require('./lib/fastly-extended')(process.env.FASTLY_API_KEY, FASTLY_SERVICE_ID);
|
||||||
|
|
||||||
var extraAppRoutes = [
|
const extraAppRoutes = [
|
||||||
// Homepage with querystring.
|
// Homepage with querystring.
|
||||||
// TODO: Should this be added for every route?
|
// TODO: Should this be added for every route?
|
||||||
'/\\?',
|
'/\\?',
|
||||||
|
@ -18,18 +18,18 @@ var extraAppRoutes = [
|
||||||
'/[^/]*.html$'
|
'/[^/]*.html$'
|
||||||
];
|
];
|
||||||
|
|
||||||
var routes = routeJson.map(function (route) {
|
const routes = routeJson.map(
|
||||||
return defaults({}, {pattern: fastlyConfig.expressPatternToRegex(route.pattern)}, route);
|
route => defaults({}, {pattern: fastlyConfig.expressPatternToRegex(route.pattern)}, route)
|
||||||
});
|
);
|
||||||
|
|
||||||
async.auto({
|
async.auto({
|
||||||
version: function (cb) {
|
version: function (cb) {
|
||||||
fastly.getLatestActiveVersion(function (err, response) {
|
fastly.getLatestActiveVersion((err, response) => {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
// Validate latest version before continuing
|
// Validate latest version before continuing
|
||||||
if (response.active || response.locked) {
|
if (response.active || response.locked) {
|
||||||
fastly.cloneVersion(response.number, function (e, resp) {
|
fastly.cloneVersion(response.number, (e, resp) => {
|
||||||
if (e) return cb('Failed to clone latest version: ' + e);
|
if (e) return cb(`Failed to clone latest version: ${e}`);
|
||||||
cb(null, resp.number);
|
cb(null, resp.number);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -40,40 +40,40 @@ async.auto({
|
||||||
recvCustomVCL: ['version', function (results, cb) {
|
recvCustomVCL: ['version', function (results, cb) {
|
||||||
// For all the routes in routes.json, construct a varnish-style regex that matches
|
// For all the routes in routes.json, construct a varnish-style regex that matches
|
||||||
// on any of those route conditions.
|
// on any of those route conditions.
|
||||||
var notPassStatement = fastlyConfig.getAppRouteCondition('../build/*', routes, extraAppRoutes, __dirname);
|
const notPassStatement = fastlyConfig.getAppRouteCondition('../build/*', routes, extraAppRoutes, __dirname);
|
||||||
|
|
||||||
// For a non-pass condition, point backend at s3
|
// For a non-pass condition, point backend at s3
|
||||||
var recvCondition = '' +
|
const recvCondition = `${'' +
|
||||||
'if (' + notPassStatement + ') {\n' +
|
'if ('}${notPassStatement}) {\n` +
|
||||||
' set req.backend = F_s3;\n' +
|
` set req.backend = F_s3;\n` +
|
||||||
' set req.http.host = "' + S3_BUCKET_NAME + '";\n' +
|
` set req.http.host = "${S3_BUCKET_NAME}";\n` +
|
||||||
'} else {\n' +
|
`} else {\n` +
|
||||||
' if (!req.http.Fastly-FF) {\n' +
|
` if (!req.http.Fastly-FF) {\n` +
|
||||||
' if (req.http.X-Forwarded-For) {\n' +
|
` if (req.http.X-Forwarded-For) {\n` +
|
||||||
' set req.http.Fastly-Temp-XFF = req.http.X-Forwarded-For ", " client.ip;\n' +
|
` set req.http.Fastly-Temp-XFF = req.http.X-Forwarded-For ", " client.ip;\n` +
|
||||||
' } else {\n' +
|
` } else {\n` +
|
||||||
' set req.http.Fastly-Temp-XFF = client.ip;\n' +
|
` set req.http.Fastly-Temp-XFF = client.ip;\n` +
|
||||||
' }\n' +
|
` }\n` +
|
||||||
' } else {\n' +
|
` } else {\n` +
|
||||||
' set req.http.Fastly-Temp-XFF = req.http.X-Forwarded-For;\n' +
|
` set req.http.Fastly-Temp-XFF = req.http.X-Forwarded-For;\n` +
|
||||||
' }\n' +
|
` }\n` +
|
||||||
' set req.grace = 60s;\n' +
|
` set req.grace = 60s;\n` +
|
||||||
' if (req.http.Cookie:scratchlanguage) {\n' +
|
` if (req.http.Cookie:scratchlanguage) {\n` +
|
||||||
' set req.http.Accept-Language = req.http.Cookie:scratchlanguage;\n' +
|
` set req.http.Accept-Language = req.http.Cookie:scratchlanguage;\n` +
|
||||||
' } else {\n' +
|
` } else {\n` +
|
||||||
' set req.http.Accept-Language = accept.language_lookup("' +
|
` set req.http.Accept-Language = accept.language_lookup("${
|
||||||
Object.keys(languages).join(':') + '", ' +
|
Object.keys(languages).join(':')}", ` +
|
||||||
'"en", ' +
|
`"en", ` +
|
||||||
'std.tolower(req.http.Accept-Language)' +
|
`std.tolower(req.http.Accept-Language)` +
|
||||||
');\n' +
|
`);\n` +
|
||||||
' }\n' +
|
` }\n` +
|
||||||
' if (req.url ~ "^(/projects/|/fragment/account-nav.json|/session/)" && ' +
|
` if (req.url ~ "^(/projects/|/fragment/account-nav.json|/session/)" && ` +
|
||||||
'!req.http.Cookie:scratchsessionsid) {\n' +
|
`!req.http.Cookie:scratchsessionsid) {\n` +
|
||||||
' set req.http.Cookie = "scratchlanguage=" req.http.Cookie:scratchlanguage;\n' +
|
` set req.http.Cookie = "scratchlanguage=" req.http.Cookie:scratchlanguage;\n` +
|
||||||
' } else {\n' +
|
` } else {\n` +
|
||||||
' return(pass);\n' +
|
` return(pass);\n` +
|
||||||
' }\n' +
|
` }\n` +
|
||||||
'}\n';
|
`}\n`;
|
||||||
|
|
||||||
|
|
||||||
fastly.setCustomVCL(
|
fastly.setCustomVCL(
|
||||||
|
@ -84,48 +84,48 @@ async.auto({
|
||||||
);
|
);
|
||||||
}],
|
}],
|
||||||
fetchCustomVCL: ['version', function (results, cb) {
|
fetchCustomVCL: ['version', function (results, cb) {
|
||||||
var passStatement = fastlyConfig.negateConditionStatement(
|
const passStatement = fastlyConfig.negateConditionStatement(
|
||||||
fastlyConfig.getAppRouteCondition('../build/*', routes, extraAppRoutes, __dirname)
|
fastlyConfig.getAppRouteCondition('../build/*', routes, extraAppRoutes, __dirname)
|
||||||
);
|
);
|
||||||
var ttlCondition = fastlyConfig.setResponseTTL(passStatement);
|
const ttlCondition = fastlyConfig.setResponseTTL(passStatement);
|
||||||
fastly.setCustomVCL(results.version, 'fetch-condition', ttlCondition, cb);
|
fastly.setCustomVCL(results.version, 'fetch-condition', ttlCondition, cb);
|
||||||
}],
|
}],
|
||||||
appRouteRequestConditions: ['version', function (results, cb) {
|
appRouteRequestConditions: ['version', function (results, cb) {
|
||||||
var conditions = {};
|
const conditions = {};
|
||||||
async.forEachOf(routes, function (route, id, cb2) {
|
async.forEachOf(routes, (route, id, cb2) => {
|
||||||
var condition = {
|
const condition = {
|
||||||
name: fastlyConfig.getConditionNameForRoute(route, 'request'),
|
name: fastlyConfig.getConditionNameForRoute(route, 'request'),
|
||||||
statement: 'req.url.path ~ "' + route.pattern + '"',
|
statement: `req.url.path ~ "${route.pattern}"`,
|
||||||
type: 'REQUEST',
|
type: 'REQUEST',
|
||||||
// Priority needs to be > 1 to not interact with http->https redirect
|
// Priority needs to be > 1 to not interact with http->https redirect
|
||||||
priority: 10 + id
|
priority: 10 + id
|
||||||
};
|
};
|
||||||
fastly.setCondition(results.version, condition, function (err, response) {
|
fastly.setCondition(results.version, condition, (err, response) => {
|
||||||
if (err) return cb2(err);
|
if (err) return cb2(err);
|
||||||
conditions[id] = response;
|
conditions[id] = response;
|
||||||
cb2(null, response);
|
cb2(null, response);
|
||||||
});
|
});
|
||||||
}, function (err) {
|
}, err => {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
cb(null, conditions);
|
cb(null, conditions);
|
||||||
});
|
});
|
||||||
}],
|
}],
|
||||||
appRouteHeaders: ['version', 'appRouteRequestConditions', function (results, cb) {
|
appRouteHeaders: ['version', 'appRouteRequestConditions', function (results, cb) {
|
||||||
var headers = {};
|
const headers = {};
|
||||||
async.forEachOf(routes, function (route, id, cb2) {
|
async.forEachOf(routes, (route, id, cb2) => {
|
||||||
if (route.redirect) {
|
if (route.redirect) {
|
||||||
async.auto({
|
async.auto({
|
||||||
responseCondition: function (cb3) {
|
responseCondition: function (cb3) {
|
||||||
var condition = {
|
const condition = {
|
||||||
name: fastlyConfig.getConditionNameForRoute(route, 'response'),
|
name: fastlyConfig.getConditionNameForRoute(route, 'response'),
|
||||||
statement: 'req.url.path ~ "' + route.pattern + '"',
|
statement: `req.url.path ~ "${route.pattern}"`,
|
||||||
type: 'RESPONSE',
|
type: 'RESPONSE',
|
||||||
priority: id
|
priority: id
|
||||||
};
|
};
|
||||||
fastly.setCondition(results.version, condition, cb3);
|
fastly.setCondition(results.version, condition, cb3);
|
||||||
},
|
},
|
||||||
responseObject: function (cb3) {
|
responseObject: function (cb3) {
|
||||||
var responseObject = {
|
const responseObject = {
|
||||||
name: fastlyConfig.getResponseNameForRoute(route),
|
name: fastlyConfig.getResponseNameForRoute(route),
|
||||||
status: 301,
|
status: 301,
|
||||||
response: 'Moved Permanently',
|
response: 'Moved Permanently',
|
||||||
|
@ -134,40 +134,40 @@ async.auto({
|
||||||
fastly.setResponseObject(results.version, responseObject, cb3);
|
fastly.setResponseObject(results.version, responseObject, cb3);
|
||||||
},
|
},
|
||||||
redirectHeader: ['responseCondition', function (redirectResults, cb3) {
|
redirectHeader: ['responseCondition', function (redirectResults, cb3) {
|
||||||
var header = {
|
const header = {
|
||||||
name: fastlyConfig.getHeaderNameForRoute(route),
|
name: fastlyConfig.getHeaderNameForRoute(route),
|
||||||
action: 'set',
|
action: 'set',
|
||||||
ignore_if_set: 0,
|
ignore_if_set: 0,
|
||||||
type: 'RESPONSE',
|
type: 'RESPONSE',
|
||||||
dst: 'http.Location',
|
dst: 'http.Location',
|
||||||
src: '"' + route.redirect + '"',
|
src: `"${route.redirect}"`,
|
||||||
response_condition: redirectResults.responseCondition.name
|
response_condition: redirectResults.responseCondition.name
|
||||||
};
|
};
|
||||||
fastly.setFastlyHeader(results.version, header, cb3);
|
fastly.setFastlyHeader(results.version, header, cb3);
|
||||||
}]
|
}]
|
||||||
}, function (err, redirectResults) {
|
}, (err, redirectResults) => {
|
||||||
if (err) return cb2(err);
|
if (err) return cb2(err);
|
||||||
headers[id] = redirectResults.redirectHeader;
|
headers[id] = redirectResults.redirectHeader;
|
||||||
cb2(null, redirectResults);
|
cb2(null, redirectResults);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
var header = {
|
const header = {
|
||||||
name: fastlyConfig.getHeaderNameForRoute(route, 'request'),
|
name: fastlyConfig.getHeaderNameForRoute(route, 'request'),
|
||||||
action: 'set',
|
action: 'set',
|
||||||
ignore_if_set: 0,
|
ignore_if_set: 0,
|
||||||
type: 'REQUEST',
|
type: 'REQUEST',
|
||||||
dst: 'url',
|
dst: 'url',
|
||||||
src: '"/' + route.name + '.html"',
|
src: `"/${route.name}.html"`,
|
||||||
request_condition: results.appRouteRequestConditions[id].name,
|
request_condition: results.appRouteRequestConditions[id].name,
|
||||||
priority: 10
|
priority: 10
|
||||||
};
|
};
|
||||||
fastly.setFastlyHeader(results.version, header, function (err, response) {
|
fastly.setFastlyHeader(results.version, header, (err, response) => {
|
||||||
if (err) return cb2(err);
|
if (err) return cb2(err);
|
||||||
headers[id] = response;
|
headers[id] = response;
|
||||||
cb2(null, response);
|
cb2(null, response);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, function (err) {
|
}, err => {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
cb(null, headers);
|
cb(null, headers);
|
||||||
});
|
});
|
||||||
|
@ -175,7 +175,7 @@ async.auto({
|
||||||
tipbarRedirectHeaders: ['version', function (results, cb) {
|
tipbarRedirectHeaders: ['version', function (results, cb) {
|
||||||
async.auto({
|
async.auto({
|
||||||
requestCondition: function (cb2) {
|
requestCondition: function (cb2) {
|
||||||
var condition = {
|
const condition = {
|
||||||
name: 'routes/?tip_bar= (request)',
|
name: 'routes/?tip_bar= (request)',
|
||||||
statement: 'req.url ~ "\\?tip_bar="',
|
statement: 'req.url ~ "\\?tip_bar="',
|
||||||
type: 'REQUEST',
|
type: 'REQUEST',
|
||||||
|
@ -184,7 +184,7 @@ async.auto({
|
||||||
fastly.setCondition(results.version, condition, cb2);
|
fastly.setCondition(results.version, condition, cb2);
|
||||||
},
|
},
|
||||||
responseCondition: function (cb2) {
|
responseCondition: function (cb2) {
|
||||||
var condition = {
|
const condition = {
|
||||||
name: 'routes/?tip_bar= (response)',
|
name: 'routes/?tip_bar= (response)',
|
||||||
statement: 'req.url ~ "\\?tip_bar="',
|
statement: 'req.url ~ "\\?tip_bar="',
|
||||||
type: 'RESPONSE',
|
type: 'RESPONSE',
|
||||||
|
@ -193,7 +193,7 @@ async.auto({
|
||||||
fastly.setCondition(results.version, condition, cb2);
|
fastly.setCondition(results.version, condition, cb2);
|
||||||
},
|
},
|
||||||
responseObject: ['requestCondition', function (redirectResults, cb2) {
|
responseObject: ['requestCondition', function (redirectResults, cb2) {
|
||||||
var responseObject = {
|
const responseObject = {
|
||||||
name: 'redirects/?tip_bar=',
|
name: 'redirects/?tip_bar=',
|
||||||
status: 301,
|
status: 301,
|
||||||
response: 'Moved Permanently',
|
response: 'Moved Permanently',
|
||||||
|
@ -202,7 +202,7 @@ async.auto({
|
||||||
fastly.setResponseObject(results.version, responseObject, cb2);
|
fastly.setResponseObject(results.version, responseObject, cb2);
|
||||||
}],
|
}],
|
||||||
redirectHeader: ['responseCondition', function (redirectResults, cb2) {
|
redirectHeader: ['responseCondition', function (redirectResults, cb2) {
|
||||||
var header = {
|
const header = {
|
||||||
name: 'redirects/?tip_bar=',
|
name: 'redirects/?tip_bar=',
|
||||||
action: 'set',
|
action: 'set',
|
||||||
ignore_if_set: 0,
|
ignore_if_set: 0,
|
||||||
|
@ -213,7 +213,7 @@ async.auto({
|
||||||
};
|
};
|
||||||
fastly.setFastlyHeader(results.version, header, cb2);
|
fastly.setFastlyHeader(results.version, header, cb2);
|
||||||
}]
|
}]
|
||||||
}, function (err, redirectResults) {
|
}, (err, redirectResults) => {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
cb(null, redirectResults);
|
cb(null, redirectResults);
|
||||||
});
|
});
|
||||||
|
@ -221,7 +221,7 @@ async.auto({
|
||||||
embedRedirectHeaders: ['version', function (results, cb) {
|
embedRedirectHeaders: ['version', function (results, cb) {
|
||||||
async.auto({
|
async.auto({
|
||||||
requestCondition: function (cb2) {
|
requestCondition: function (cb2) {
|
||||||
var condition = {
|
const condition = {
|
||||||
name: 'routes/projects/embed (request)',
|
name: 'routes/projects/embed (request)',
|
||||||
statement: 'req.url.path ~ "^/projects/embed/(\\d+)"',
|
statement: 'req.url.path ~ "^/projects/embed/(\\d+)"',
|
||||||
type: 'REQUEST',
|
type: 'REQUEST',
|
||||||
|
@ -230,7 +230,7 @@ async.auto({
|
||||||
fastly.setCondition(results.version, condition, cb2);
|
fastly.setCondition(results.version, condition, cb2);
|
||||||
},
|
},
|
||||||
responseCondition: function (cb2) {
|
responseCondition: function (cb2) {
|
||||||
var condition = {
|
const condition = {
|
||||||
name: 'routes/projects/embed (response)',
|
name: 'routes/projects/embed (response)',
|
||||||
statement: 'req.url.path ~ "^/projects/embed/(\\d+)"',
|
statement: 'req.url.path ~ "^/projects/embed/(\\d+)"',
|
||||||
type: 'RESPONSE',
|
type: 'RESPONSE',
|
||||||
|
@ -239,7 +239,7 @@ async.auto({
|
||||||
fastly.setCondition(results.version, condition, cb2);
|
fastly.setCondition(results.version, condition, cb2);
|
||||||
},
|
},
|
||||||
responseObject: ['requestCondition', function (redirectResults, cb2) {
|
responseObject: ['requestCondition', function (redirectResults, cb2) {
|
||||||
var responseObject = {
|
const responseObject = {
|
||||||
name: 'redirects/projects/embed',
|
name: 'redirects/projects/embed',
|
||||||
status: 301,
|
status: 301,
|
||||||
response: 'Moved Permanently',
|
response: 'Moved Permanently',
|
||||||
|
@ -248,7 +248,7 @@ async.auto({
|
||||||
fastly.setResponseObject(results.version, responseObject, cb2);
|
fastly.setResponseObject(results.version, responseObject, cb2);
|
||||||
}],
|
}],
|
||||||
redirectHeader: ['responseCondition', function (redirectResults, cb2) {
|
redirectHeader: ['responseCondition', function (redirectResults, cb2) {
|
||||||
var header = {
|
const header = {
|
||||||
name: 'redirects/projects/embed',
|
name: 'redirects/projects/embed',
|
||||||
action: 'set',
|
action: 'set',
|
||||||
ignore_if_set: 0,
|
ignore_if_set: 0,
|
||||||
|
@ -259,19 +259,19 @@ async.auto({
|
||||||
};
|
};
|
||||||
fastly.setFastlyHeader(results.version, header, cb2);
|
fastly.setFastlyHeader(results.version, header, cb2);
|
||||||
}]
|
}]
|
||||||
}, function (err, redirectResults) {
|
}, (err, redirectResults) => {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
cb(null, redirectResults);
|
cb(null, redirectResults);
|
||||||
});
|
});
|
||||||
}]
|
}]
|
||||||
}, function (err, results) {
|
}, (err, results) => {
|
||||||
if (err) throw new Error(err);
|
if (err) throw new Error(err);
|
||||||
if (process.env.FASTLY_ACTIVATE_CHANGES) {
|
if (process.env.FASTLY_ACTIVATE_CHANGES) {
|
||||||
fastly.activateVersion(results.version, function (e, resp) {
|
fastly.activateVersion(results.version, (e, resp) => {
|
||||||
if (e) throw new Error(e);
|
if (e) throw new Error(e);
|
||||||
process.stdout.write('Successfully configured and activated version ' + resp.number + '\n');
|
process.stdout.write(`Successfully configured and activated version ${resp.number}\n`);
|
||||||
// purge static-assets using surrogate key
|
// purge static-assets using surrogate key
|
||||||
fastly.purgeKey(FASTLY_SERVICE_ID, 'static-assets', function (error) {
|
fastly.purgeKey(FASTLY_SERVICE_ID, 'static-assets', error => {
|
||||||
if (error) throw new Error(error);
|
if (error) throw new Error(error);
|
||||||
process.stdout.write('Purged static assets.\n');
|
process.stdout.write('Purged static assets.\n');
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
var glob = require('glob');
|
const glob = require('glob');
|
||||||
var path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
var FastlyConfigMethods = {
|
const FastlyConfigMethods = {
|
||||||
/*
|
/*
|
||||||
* Given the relative path to the static directory, return an array of
|
* Given the relative path to the static directory, return an array of
|
||||||
* patterns matching the files and directories there.
|
* patterns matching the files and directories there.
|
||||||
*/
|
*/
|
||||||
getStaticPaths: function (rootDir, pathToStatic) {
|
getStaticPaths: function (rootDir, pathToStatic) {
|
||||||
var staticPaths = glob.sync(path.resolve(rootDir, pathToStatic));
|
const staticPaths = glob.sync(path.resolve(rootDir, pathToStatic));
|
||||||
return staticPaths.filter(function (pathName) {
|
return staticPaths.filter(pathName =>
|
||||||
// Exclude view html, resolve everything else in the build
|
// Exclude view html, resolve everything else in the build
|
||||||
return path.extname(pathName) !== '.html';
|
path.extname(pathName) !== '.html'
|
||||||
}).map(function (pathName) {
|
).map(pathName => {
|
||||||
// Reduce absolute path to relative paths like '/js'
|
// Reduce absolute path to relative paths like '/js'
|
||||||
var base = path.dirname(path.resolve(rootDir, pathToStatic));
|
const base = path.dirname(path.resolve(rootDir, pathToStatic));
|
||||||
return pathName.replace(base, '') + (path.extname(pathName) ? '' : '/');
|
return pathName.replace(base, '') + (path.extname(pathName) ? '' : '/');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -23,8 +23,8 @@ var FastlyConfigMethods = {
|
||||||
* the express route and a static view file associated with the route
|
* the express route and a static view file associated with the route
|
||||||
*/
|
*/
|
||||||
getViewPaths: function (routes) {
|
getViewPaths: function (routes) {
|
||||||
return routes.reduce(function (paths, route) {
|
return routes.reduce((paths, route) => {
|
||||||
var p = route.routeAlias || route.pattern;
|
const p = route.routeAlias || route.pattern;
|
||||||
if (paths.indexOf(p) === -1) {
|
if (paths.indexOf(p) === -1) {
|
||||||
paths.push(p);
|
paths.push(p);
|
||||||
}
|
}
|
||||||
|
@ -48,16 +48,16 @@ var FastlyConfigMethods = {
|
||||||
* string suitable for a Fastly condition
|
* string suitable for a Fastly condition
|
||||||
*/
|
*/
|
||||||
pathsToCondition: function (paths) {
|
pathsToCondition: function (paths) {
|
||||||
return 'req.url~"^(' + paths.reduce(function (conditionString, pattern) {
|
return `req.url~"^(${
|
||||||
return conditionString + (conditionString ? '|' : '') + pattern;
|
paths.reduce((conditionString, pattern) => conditionString + (conditionString ? '|' : '') + pattern, '')
|
||||||
}, '') + ')"';
|
})"`;
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper method to NOT a condition statement
|
* Helper method to NOT a condition statement
|
||||||
*/
|
*/
|
||||||
negateConditionStatement: function (statement) {
|
negateConditionStatement: function (statement) {
|
||||||
return '!(' + statement + ')';
|
return `!(${statement})`;
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -65,23 +65,23 @@ var FastlyConfigMethods = {
|
||||||
* fastly condition to match req.url
|
* fastly condition to match req.url
|
||||||
*/
|
*/
|
||||||
getAppRouteCondition: function (pathToStatic, routes, additionalPaths, rootDir) {
|
getAppRouteCondition: function (pathToStatic, routes, additionalPaths, rootDir) {
|
||||||
var staticPaths = FastlyConfigMethods.getStaticPaths(rootDir, pathToStatic);
|
const staticPaths = FastlyConfigMethods.getStaticPaths(rootDir, pathToStatic);
|
||||||
var viewPaths = FastlyConfigMethods.getViewPaths(routes);
|
const viewPaths = FastlyConfigMethods.getViewPaths(routes);
|
||||||
var allPaths = [].concat(staticPaths, viewPaths, additionalPaths);
|
const allPaths = [].concat(staticPaths, viewPaths, additionalPaths);
|
||||||
return FastlyConfigMethods.pathsToCondition(allPaths);
|
return FastlyConfigMethods.pathsToCondition(allPaths);
|
||||||
},
|
},
|
||||||
|
|
||||||
getConditionNameForRoute: function (route, type) {
|
getConditionNameForRoute: function (route, type) {
|
||||||
return 'routes/' + route.pattern + ' (' + type + ')';
|
return `routes/${route.pattern} (${type})`;
|
||||||
},
|
},
|
||||||
|
|
||||||
getHeaderNameForRoute: function (route) {
|
getHeaderNameForRoute: function (route) {
|
||||||
if (route.name) return 'rewrites/' + route.name;
|
if (route.name) return `rewrites/${route.name}`;
|
||||||
if (route.redirect) return 'redirects/' + route.pattern;
|
if (route.redirect) return `redirects/${route.pattern}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
getResponseNameForRoute: function (route) {
|
getResponseNameForRoute: function (route) {
|
||||||
return 'redirects/' + route.pattern;
|
return `redirects/${route.pattern}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -91,19 +91,19 @@ var FastlyConfigMethods = {
|
||||||
* @param {string} condition condition under which the response should be set
|
* @param {string} condition condition under which the response should be set
|
||||||
*/
|
*/
|
||||||
setResponseTTL: function (condition) {
|
setResponseTTL: function (condition) {
|
||||||
return '' +
|
return `${'' +
|
||||||
'if (' + condition + ') {\n' +
|
'if ('}${condition}) {\n` +
|
||||||
' if (req.url ~ "^(/projects/|/fragment/account-nav.json|/session/)" && ' +
|
` if (req.url ~ "^(/projects/|/fragment/account-nav.json|/session/)" && ` +
|
||||||
'!req.http.Cookie:scratchsessionsid) {\n' +
|
`!req.http.Cookie:scratchsessionsid) {\n` +
|
||||||
' set beresp.http.Vary = "Accept-Encoding, Accept-Language";\n' +
|
` set beresp.http.Vary = "Accept-Encoding, Accept-Language";\n` +
|
||||||
' unset beresp.http.set-cookie;\n' +
|
` unset beresp.http.set-cookie;\n` +
|
||||||
' return(deliver);\n' +
|
` return(deliver);\n` +
|
||||||
' } else {\n' +
|
` } else {\n` +
|
||||||
' set beresp.ttl = 0s;\n' +
|
` set beresp.ttl = 0s;\n` +
|
||||||
' set beresp.grace = 0s;\n' +
|
` set beresp.grace = 0s;\n` +
|
||||||
' return(pass);\n' +
|
` return(pass);\n` +
|
||||||
' }\n' +
|
` }\n` +
|
||||||
'}\n';
|
`}\n`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
var Fastly = require('fastly');
|
const Fastly = require('fastly');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fastly library extended to allow configuration for a particular service
|
* Fastly library extended to allow configuration for a particular service
|
||||||
|
@ -8,7 +8,7 @@ var Fastly = require('fastly');
|
||||||
* @param {string} Service id
|
* @param {string} Service id
|
||||||
*/
|
*/
|
||||||
module.exports = function (apiKey, serviceId) {
|
module.exports = function (apiKey, serviceId) {
|
||||||
var fastly = Fastly(apiKey);
|
const fastly = Fastly(apiKey);
|
||||||
fastly.serviceId = serviceId;
|
fastly.serviceId = serviceId;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -20,7 +20,7 @@ module.exports = function (apiKey, serviceId) {
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
fastly.getFastlyAPIPrefix = function (servId, version) {
|
fastly.getFastlyAPIPrefix = function (servId, version) {
|
||||||
return '/service/' + encodeURIComponent(servId) + '/version/' + version;
|
return `/service/${encodeURIComponent(servId)}/version/${version}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -32,12 +32,12 @@ module.exports = function (apiKey, serviceId) {
|
||||||
if (!this.serviceId) {
|
if (!this.serviceId) {
|
||||||
return cb('Failed to get latest version. No serviceId configured');
|
return cb('Failed to get latest version. No serviceId configured');
|
||||||
}
|
}
|
||||||
var url = '/service/' + encodeURIComponent(this.serviceId) + '/version';
|
const url = `/service/${encodeURIComponent(this.serviceId)}/version`;
|
||||||
this.request('GET', url, function (err, versions) {
|
this.request('GET', url, (err, versions) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb('Failed to fetch versions: ' + err);
|
return cb(`Failed to fetch versions: ${err}`);
|
||||||
}
|
}
|
||||||
var latestVersion = versions.reduce((latestActiveSoFar, cur) => {
|
const latestVersion = versions.reduce((latestActiveSoFar, cur) => {
|
||||||
// if one of [latestActiveSoFar, cur] is active and the other isn't,
|
// if one of [latestActiveSoFar, cur] is active and the other isn't,
|
||||||
// return whichever is active. If both are not active, return
|
// return whichever is active. If both are not active, return
|
||||||
// latestActiveSoFar.
|
// latestActiveSoFar.
|
||||||
|
@ -62,24 +62,24 @@ module.exports = function (apiKey, serviceId) {
|
||||||
if (!this.serviceId) {
|
if (!this.serviceId) {
|
||||||
return cb('Failed to set condition. No serviceId configured');
|
return cb('Failed to set condition. No serviceId configured');
|
||||||
}
|
}
|
||||||
var name = condition.name;
|
const name = condition.name;
|
||||||
var putUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/condition/' + encodeURIComponent(name);
|
const putUrl = `${this.getFastlyAPIPrefix(this.serviceId, version)}/condition/${encodeURIComponent(name)}`;
|
||||||
var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/condition';
|
const postUrl = `${this.getFastlyAPIPrefix(this.serviceId, version)}/condition`;
|
||||||
return this.request('PUT', putUrl, condition, function (err, response) {
|
return this.request('PUT', putUrl, condition, (err, response) => {
|
||||||
if (err && err.statusCode === 404) {
|
if (err && err.statusCode === 404) {
|
||||||
this.request('POST', postUrl, condition, function (e, resp) {
|
this.request('POST', postUrl, condition, (e, resp) => {
|
||||||
if (e) {
|
if (e) {
|
||||||
return cb('Failed while inserting condition "' + condition.statement + '": ' + e);
|
return cb(`Failed while inserting condition "${condition.statement}": ${e}`);
|
||||||
}
|
}
|
||||||
return cb(null, resp);
|
return cb(null, resp);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb('Failed to update condition "' + condition.statement + '": ' + err);
|
return cb(`Failed to update condition "${condition.statement}": ${err}`);
|
||||||
}
|
}
|
||||||
return cb(null, response);
|
return cb(null, response);
|
||||||
}.bind(this));
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -94,24 +94,24 @@ module.exports = function (apiKey, serviceId) {
|
||||||
if (!this.serviceId) {
|
if (!this.serviceId) {
|
||||||
cb('Failed to set header. No serviceId configured');
|
cb('Failed to set header. No serviceId configured');
|
||||||
}
|
}
|
||||||
var name = header.name;
|
const name = header.name;
|
||||||
var putUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/header/' + encodeURIComponent(name);
|
const putUrl = `${this.getFastlyAPIPrefix(this.serviceId, version)}/header/${encodeURIComponent(name)}`;
|
||||||
var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/header';
|
const postUrl = `${this.getFastlyAPIPrefix(this.serviceId, version)}/header`;
|
||||||
return this.request('PUT', putUrl, header, function (err, response) {
|
return this.request('PUT', putUrl, header, (err, response) => {
|
||||||
if (err && err.statusCode === 404) {
|
if (err && err.statusCode === 404) {
|
||||||
this.request('POST', postUrl, header, function (e, resp) {
|
this.request('POST', postUrl, header, (e, resp) => {
|
||||||
if (e) {
|
if (e) {
|
||||||
return cb('Failed to insert header: ' + e);
|
return cb(`Failed to insert header: ${e}`);
|
||||||
}
|
}
|
||||||
return cb(null, resp);
|
return cb(null, resp);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb('Failed to update header: ' + err);
|
return cb(`Failed to update header: ${err}`);
|
||||||
}
|
}
|
||||||
return cb(null, response);
|
return cb(null, response);
|
||||||
}.bind(this));
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -126,24 +126,25 @@ module.exports = function (apiKey, serviceId) {
|
||||||
if (!this.serviceId) {
|
if (!this.serviceId) {
|
||||||
cb('Failed to set response object. No serviceId configured');
|
cb('Failed to set response object. No serviceId configured');
|
||||||
}
|
}
|
||||||
var name = responseObj.name;
|
const name = responseObj.name;
|
||||||
var putUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/response_object/' + encodeURIComponent(name);
|
const putUrl =
|
||||||
var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/response_object';
|
`${this.getFastlyAPIPrefix(this.serviceId, version)}/response_object/${encodeURIComponent(name)}`;
|
||||||
return this.request('PUT', putUrl, responseObj, function (err, response) {
|
const postUrl = `${this.getFastlyAPIPrefix(this.serviceId, version)}/response_object`;
|
||||||
|
return this.request('PUT', putUrl, responseObj, (err, response) => {
|
||||||
if (err && err.statusCode === 404) {
|
if (err && err.statusCode === 404) {
|
||||||
this.request('POST', postUrl, responseObj, function (e, resp) {
|
this.request('POST', postUrl, responseObj, (e, resp) => {
|
||||||
if (e) {
|
if (e) {
|
||||||
return cb('Failed to insert response object: ' + e);
|
return cb(`Failed to insert response object: ${e}`);
|
||||||
}
|
}
|
||||||
return cb(null, resp);
|
return cb(null, resp);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb('Failed to update response object: ' + err);
|
return cb(`Failed to update response object: ${err}`);
|
||||||
}
|
}
|
||||||
return cb(null, response);
|
return cb(null, response);
|
||||||
}.bind(this));
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -154,7 +155,7 @@ module.exports = function (apiKey, serviceId) {
|
||||||
*/
|
*/
|
||||||
fastly.cloneVersion = function (version, cb) {
|
fastly.cloneVersion = function (version, cb) {
|
||||||
if (!this.serviceId) return cb('Failed to clone version. No serviceId configured.');
|
if (!this.serviceId) return cb('Failed to clone version. No serviceId configured.');
|
||||||
var url = this.getFastlyAPIPrefix(this.serviceId, version) + '/clone';
|
const url = `${this.getFastlyAPIPrefix(this.serviceId, version)}/clone`;
|
||||||
this.request('PUT', url, cb);
|
this.request('PUT', url, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,7 +167,7 @@ module.exports = function (apiKey, serviceId) {
|
||||||
*/
|
*/
|
||||||
fastly.activateVersion = function (version, cb) {
|
fastly.activateVersion = function (version, cb) {
|
||||||
if (!this.serviceId) return cb('Failed to activate version. No serviceId configured.');
|
if (!this.serviceId) return cb('Failed to activate version. No serviceId configured.');
|
||||||
var url = this.getFastlyAPIPrefix(this.serviceId, version) + '/activate';
|
const url = `${this.getFastlyAPIPrefix(this.serviceId, version)}/activate`;
|
||||||
this.request('PUT', url, cb);
|
this.request('PUT', url, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -184,25 +185,25 @@ module.exports = function (apiKey, serviceId) {
|
||||||
return cb('Failed to set response object. No serviceId configured');
|
return cb('Failed to set response object. No serviceId configured');
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = this.getFastlyAPIPrefix(this.serviceId, version) + '/vcl/' + name;
|
const url = `${this.getFastlyAPIPrefix(this.serviceId, version)}/vcl/${name}`;
|
||||||
var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/vcl';
|
const postUrl = `${this.getFastlyAPIPrefix(this.serviceId, version)}/vcl`;
|
||||||
var content = {content: vcl};
|
const content = {content: vcl};
|
||||||
return this.request('PUT', url, content, function (err, response) {
|
return this.request('PUT', url, content, (err, response) => {
|
||||||
if (err && err.statusCode === 404) {
|
if (err && err.statusCode === 404) {
|
||||||
content.name = name;
|
content.name = name;
|
||||||
this.request('POST', postUrl, content, function (e, resp) {
|
this.request('POST', postUrl, content, (e, resp) => {
|
||||||
if (e) {
|
if (e) {
|
||||||
return cb('Failed while adding custom vcl "' + name + '": ' + e);
|
return cb(`Failed while adding custom vcl "${name}": ${e}`);
|
||||||
}
|
}
|
||||||
return cb(null, resp);
|
return cb(null, resp);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb('Failed to update custom vcl "' + name + '": ' + err);
|
return cb(`Failed to update custom vcl "${name}": ${err}`);
|
||||||
}
|
}
|
||||||
return cb(null, response);
|
return cb(null, response);
|
||||||
}.bind(this));
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return fastly;
|
return fastly;
|
||||||
|
|
|
@ -9,7 +9,7 @@ const Handler = function (route) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = '/' + route.name + '.html';
|
const url = `/${route.name}.html`;
|
||||||
return function (req, res, next) {
|
return function (req, res, next) {
|
||||||
req.url = url;
|
req.url = url;
|
||||||
next();
|
next();
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
var express = require('express');
|
const express = require('express');
|
||||||
var proxy = require('express-http-proxy');
|
const proxy = require('express-http-proxy');
|
||||||
var webpackDevMiddleware = require('webpack-dev-middleware');
|
const webpackDevMiddleware = require('webpack-dev-middleware');
|
||||||
var webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
|
|
||||||
var compiler = webpack(require('../webpack.config.js'));
|
const compiler = webpack(require('../webpack.config.js'));
|
||||||
var handler = require('./handler');
|
const handler = require('./handler');
|
||||||
var log = require('./log');
|
const log = require('./log');
|
||||||
var routes = require('../src/routes.json').concat(require('../src/routes-dev.json'))
|
const routes = require('../src/routes.json').concat(require('../src/routes-dev.json'))
|
||||||
.filter(route => !process.env.VIEW || process.env.VIEW === route.view);
|
.filter(route => !process.env.VIEW || process.env.VIEW === route.view);
|
||||||
|
|
||||||
// Create server
|
// Create server
|
||||||
var app = express();
|
const app = express();
|
||||||
app.disable('x-powered-by');
|
app.disable('x-powered-by');
|
||||||
|
|
||||||
// Server setup
|
// Server setup
|
||||||
|
@ -21,11 +21,11 @@ routes.forEach(route => {
|
||||||
app.get(route.pattern, handler(route));
|
app.get(route.pattern, handler(route));
|
||||||
});
|
});
|
||||||
|
|
||||||
var middlewareOptions = {};
|
const middlewareOptions = {};
|
||||||
|
|
||||||
app.use(webpackDevMiddleware(compiler, middlewareOptions));
|
app.use(webpackDevMiddleware(compiler, middlewareOptions));
|
||||||
|
|
||||||
var proxyHost = process.env.FALLBACK || '';
|
const proxyHost = process.env.FALLBACK || '';
|
||||||
if (proxyHost !== '') {
|
if (proxyHost !== '') {
|
||||||
// Fall back to scratchr2 in development
|
// Fall back to scratchr2 in development
|
||||||
// This proxy middleware must come last
|
// This proxy middleware must come last
|
||||||
|
@ -33,10 +33,10 @@ if (proxyHost !== '') {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start listening
|
// Start listening
|
||||||
var port = process.env.PORT || 8333;
|
const port = process.env.PORT || 8333;
|
||||||
app.listen(port, function () {
|
app.listen(port, () => {
|
||||||
process.stdout.write('Server listening on port ' + port + '\n');
|
process.stdout.write(`Server listening on port ${port}\n`);
|
||||||
if (proxyHost) {
|
if (proxyHost) {
|
||||||
process.stdout.write('Proxy host: ' + proxyHost + '\n');
|
process.stdout.write(`Proxy host: ${proxyHost}\n`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
var bunyan = require('bunyan');
|
const bunyan = require('bunyan');
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
var logger = bunyan.createLogger({
|
const logger = bunyan.createLogger({
|
||||||
name: 'www',
|
name: 'www',
|
||||||
serializers: {req: bunyan.stdSerializers.req}
|
serializers: {req: bunyan.stdSerializers.req}
|
||||||
});
|
});
|
||||||
|
|
14946
package-lock.json
generated
14946
package-lock.json
generated
File diff suppressed because it is too large
Load diff
37
package.json
37
package.json
|
@ -59,6 +59,13 @@
|
||||||
"scratch-storage": "2.3.1"
|
"scratch-storage": "2.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/cli": "7.23.4",
|
||||||
|
"@babel/core": "7.23.7",
|
||||||
|
"@babel/plugin-syntax-dynamic-import": "7.8.3",
|
||||||
|
"@babel/plugin-transform-async-to-generator": "7.23.3",
|
||||||
|
"@babel/plugin-transform-object-rest-spread": "7.23.4",
|
||||||
|
"@babel/preset-env": "7.23.8",
|
||||||
|
"@babel/preset-react": "7.23.3",
|
||||||
"@formatjs/intl-datetimeformat": "6.4.3",
|
"@formatjs/intl-datetimeformat": "6.4.3",
|
||||||
"@formatjs/intl-locale": "3.0.11",
|
"@formatjs/intl-locale": "3.0.11",
|
||||||
"@formatjs/intl-numberformat": "8.3.3",
|
"@formatjs/intl-numberformat": "8.3.3",
|
||||||
|
@ -66,16 +73,9 @@
|
||||||
"@formatjs/intl-relativetimeformat": "11.1.8",
|
"@formatjs/intl-relativetimeformat": "11.1.8",
|
||||||
"async": "3.2.2",
|
"async": "3.2.2",
|
||||||
"autoprefixer": "10.4.2",
|
"autoprefixer": "10.4.2",
|
||||||
"babel-cli": "6.26.0",
|
|
||||||
"babel-core": "6.26.3",
|
|
||||||
"babel-eslint": "10.1.0",
|
"babel-eslint": "10.1.0",
|
||||||
"babel-loader": "7.1.5",
|
"babel-loader": "8.3.0",
|
||||||
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
|
||||||
"babel-plugin-transform-async-to-generator": "6.24.1",
|
|
||||||
"babel-plugin-transform-object-rest-spread": "6.26.0",
|
|
||||||
"babel-plugin-transform-require-context": "0.1.1",
|
"babel-plugin-transform-require-context": "0.1.1",
|
||||||
"babel-preset-es2015": "6.24.1",
|
|
||||||
"babel-preset-react": "6.24.1",
|
|
||||||
"bowser": "1.9.4",
|
"bowser": "1.9.4",
|
||||||
"canvas": "2.9.0",
|
"canvas": "2.9.0",
|
||||||
"chromedriver": "117.0.3",
|
"chromedriver": "117.0.3",
|
||||||
|
@ -84,6 +84,7 @@
|
||||||
"copy-webpack-plugin": "6.4.1",
|
"copy-webpack-plugin": "6.4.1",
|
||||||
"css-loader": "5.2.7",
|
"css-loader": "5.2.7",
|
||||||
"email-validator": "2.0.4",
|
"email-validator": "2.0.4",
|
||||||
|
"emit-file-webpack-plugin": "2.0.1",
|
||||||
"enzyme": "3.10.0",
|
"enzyme": "3.10.0",
|
||||||
"enzyme-adapter-react-16": "1.14.0",
|
"enzyme-adapter-react-16": "1.14.0",
|
||||||
"eslint": "5.16.0",
|
"eslint": "5.16.0",
|
||||||
|
@ -99,9 +100,9 @@
|
||||||
"git-bundle-sha": "0.0.2",
|
"git-bundle-sha": "0.0.2",
|
||||||
"glob": "5.0.15",
|
"glob": "5.0.15",
|
||||||
"google-libphonenumber": "3.2.18",
|
"google-libphonenumber": "3.2.18",
|
||||||
"html-webpack-plugin": "3.2.0",
|
"html-webpack-plugin": "5.6.0",
|
||||||
"iso-3166-2": "1.0.0",
|
"iso-3166-2": "1.0.0",
|
||||||
"jest": "23.6.0",
|
"jest": "24.9.0",
|
||||||
"jest-canvas-mock": "2.3.1",
|
"jest-canvas-mock": "2.3.1",
|
||||||
"jest-junit": "12.0.0",
|
"jest-junit": "12.0.0",
|
||||||
"keymirror": "0.1.1",
|
"keymirror": "0.1.1",
|
||||||
|
@ -141,12 +142,13 @@
|
||||||
"scratch-l10n": "3.18.0",
|
"scratch-l10n": "3.18.0",
|
||||||
"selenium-webdriver": "4.1.0",
|
"selenium-webdriver": "4.1.0",
|
||||||
"slick-carousel": "1.6.0",
|
"slick-carousel": "1.6.0",
|
||||||
|
"stream-browserify": "3.0.0",
|
||||||
"style-loader": "0.12.3",
|
"style-loader": "0.12.3",
|
||||||
"tap": "14.11.0",
|
"tap": "14.11.0",
|
||||||
"url-loader": "2.3.0",
|
"url-loader": "3.0.0",
|
||||||
"webpack": "4.47.0",
|
"webpack": "5.89.0",
|
||||||
"webpack-bundle-analyzer": "4.10.1",
|
"webpack-bundle-analyzer": "4.10.1",
|
||||||
"webpack-cli": "3.3.12",
|
"webpack-cli": "5.1.4",
|
||||||
"webpack-dev-middleware": "5.3.1",
|
"webpack-dev-middleware": "5.3.1",
|
||||||
"xhr": "2.2.0"
|
"xhr": "2.2.0"
|
||||||
},
|
},
|
||||||
|
@ -175,8 +177,11 @@
|
||||||
"all": true
|
"all": true
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"last 3 versions",
|
"Chrome >= 63",
|
||||||
"Safari >= 8",
|
"Firefox >= 57",
|
||||||
"iOS >= 8"
|
"Edge >= 15",
|
||||||
|
"Safari >= 11",
|
||||||
|
"ChromeAndroid >= 63",
|
||||||
|
"ios_saf >= 11"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ const webpack = require('webpack');
|
||||||
// Plugins
|
// Plugins
|
||||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||||
|
const EmitFilePlugin = require('emit-file-webpack-plugin');
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
const TerserPlugin = require('terser-webpack-plugin');
|
const TerserPlugin = require('terser-webpack-plugin');
|
||||||
|
@ -13,8 +14,9 @@ const TerserPlugin = require('terser-webpack-plugin');
|
||||||
// PostCss
|
// PostCss
|
||||||
const autoprefixer = require('autoprefixer');
|
const autoprefixer = require('autoprefixer');
|
||||||
|
|
||||||
|
/** @type {Array} */
|
||||||
let routes = require('./src/routes.json');
|
let routes = require('./src/routes.json');
|
||||||
const templateConfig = require('./src/template-config.js'); // eslint-disable-line global-require
|
const templateConfig = require('./src/template-config.js');
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
routes = routes.concat(require('./src/routes-dev.json')); // eslint-disable-line global-require
|
routes = routes.concat(require('./src/routes-dev.json')); // eslint-disable-line global-require
|
||||||
|
@ -22,55 +24,81 @@ if (process.env.NODE_ENV !== 'production') {
|
||||||
|
|
||||||
routes = routes.filter(route => !process.env.VIEW || process.env.VIEW === route.view);
|
routes = routes.filter(route => !process.env.VIEW || process.env.VIEW === route.view);
|
||||||
|
|
||||||
const pageRoutes = routes.filter(function (route) {
|
const pageRoutes = routes.filter(route => !route.redirect);
|
||||||
return !route.redirect;
|
|
||||||
});
|
|
||||||
let VersionPlugin = function (options) {
|
|
||||||
this.options = options || {};
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
VersionPlugin.prototype.apply = function (compiler) {
|
/**
|
||||||
const addVersion = function (compilation, versionId, callback) {
|
* Retrieve a version ID string for the current build, to be emitted into `version.txt`.
|
||||||
compilation.assets['version.txt'] = {
|
* @returns {Promise<string>} A promise that resolves to a version ID string.
|
||||||
source: function () {
|
*/
|
||||||
return versionId;
|
const getVersionId = () => {
|
||||||
},
|
if (process.env.WWW_VERSION) {
|
||||||
size: function () {
|
return Promise.resolve(process.env.WWW_VERSION);
|
||||||
return versionId.length;
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
gitsha({length: 5}, (err, sha) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve(sha);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
callback();
|
|
||||||
};
|
|
||||||
const options = this.options;
|
|
||||||
|
|
||||||
compiler.plugin('emit', function (compilation, callback) {
|
|
||||||
const sha = process.env.WWW_VERSION;
|
|
||||||
if (!sha) { // eslint-disable-line no-negated-condition
|
|
||||||
gitsha(options, function (err, _sha) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
return addVersion(compilation, _sha, callback);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return addVersion(compilation, sha, callback);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Prepare all entry points
|
// Prepare all entry points
|
||||||
let entry = {};
|
const entry = {};
|
||||||
|
|
||||||
pageRoutes.forEach(function (route) {
|
pageRoutes.forEach(route => {
|
||||||
entry[route.name] = [
|
entry[route.name] = [
|
||||||
'./src/init.js',
|
'./src/init.js',
|
||||||
`./src/views/${route.view}.jsx`
|
`./src/views/${route.view}.jsx`
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// HtmlWebpackPlugin v4 removed 'chunks' info that we need for our custom template.
|
||||||
|
// This plugin is a quick-and-dirty partial implementation of that information.
|
||||||
|
// Adapted from https://github.com/jantimon/html-webpack-plugin/issues/1369#issuecomment-1049968234
|
||||||
|
// Thanks, @daniel-nagy!
|
||||||
|
class HtmlWebpackBackwardsCompatibilityPlugin {
|
||||||
|
apply (compiler) {
|
||||||
|
compiler
|
||||||
|
.hooks
|
||||||
|
.compilation
|
||||||
|
.tap('HtmlWebpackBackwardsCompatibilityPlugin', compilation => {
|
||||||
|
HtmlWebpackPlugin
|
||||||
|
.getHooks(compilation)
|
||||||
|
.beforeAssetTagGeneration
|
||||||
|
.tapAsync(
|
||||||
|
'HtmlWebpackBackwardsCompatibilityPlugin',
|
||||||
|
(data, callback) => {
|
||||||
|
const {publicPath} = data.assets;
|
||||||
|
const chunks = {};
|
||||||
|
|
||||||
|
for (const entryPoint of compilation.entrypoints.values()) {
|
||||||
|
for (const chunk of entryPoint.chunks) {
|
||||||
|
const files = Array.from(chunk.files); // convert from Set
|
||||||
|
chunks[chunk.name] = {
|
||||||
|
entry: publicPath + files.find(file => file.endsWith('.js')),
|
||||||
|
css: files
|
||||||
|
.filter(file => file.endsWith('.css'))
|
||||||
|
.map(file => publicPath + file)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.assets.chunks = chunks;
|
||||||
|
|
||||||
|
callback(null, data);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: entry,
|
entry: entry,
|
||||||
devtool: process.env.NODE_ENV === 'production' ? 'none' : 'eval',
|
devtool: process.env.NODE_ENV === 'production' ? false : 'eval',
|
||||||
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
|
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, 'build'),
|
path: path.resolve(__dirname, 'build'),
|
||||||
|
@ -78,12 +106,16 @@ module.exports = {
|
||||||
publicPath: '/'
|
publicPath: '/'
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
|
fallback: {
|
||||||
|
// jszip uses Node's `stream` module, which is no longer polyfilled by default in Webpack 5
|
||||||
|
stream: require.resolve('stream-browserify')
|
||||||
|
},
|
||||||
symlinks: false // Fix local development with `npm link` packages
|
symlinks: false // Fix local development with `npm link` packages
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.jsx?$/,
|
test: /\.(?:js|mjs|cjs)x?$/,
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
include: [
|
include: [
|
||||||
path.resolve(__dirname, 'src'),
|
path.resolve(__dirname, 'src'),
|
||||||
|
@ -144,15 +176,13 @@ module.exports = {
|
||||||
],
|
],
|
||||||
noParse: /node_modules\/google-libphonenumber\/dist/
|
noParse: /node_modules\/google-libphonenumber\/dist/
|
||||||
},
|
},
|
||||||
node: {
|
|
||||||
fs: 'empty'
|
|
||||||
},
|
|
||||||
optimization: {
|
optimization: {
|
||||||
splitChunks: {
|
splitChunks: {
|
||||||
cacheGroups: {
|
cacheGroups: {
|
||||||
common: {
|
common: {
|
||||||
chunks: 'all',
|
chunks: 'all',
|
||||||
name: 'common',
|
name: 'common',
|
||||||
|
minSize: 1024,
|
||||||
minChunks: pageRoutes.length // Extract only chunks common to all html pages
|
minChunks: pageRoutes.length // Extract only chunks common to all html pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,16 +195,18 @@ module.exports = {
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new MiniCssExtractPlugin(),
|
new MiniCssExtractPlugin(),
|
||||||
new VersionPlugin({length: 5})
|
new HtmlWebpackBackwardsCompatibilityPlugin(),
|
||||||
].concat(pageRoutes
|
new EmitFilePlugin({
|
||||||
.map(function (route) {
|
filename: 'version.txt',
|
||||||
return new HtmlWebpackPlugin(defaults({}, {
|
content: getVersionId
|
||||||
title: route.title,
|
|
||||||
filename: route.name + '.html',
|
|
||||||
route: route,
|
|
||||||
dynamicMetaTags: route.dynamicMetaTags
|
|
||||||
}, templateConfig));
|
|
||||||
})
|
})
|
||||||
|
].concat(pageRoutes
|
||||||
|
.map(route => new HtmlWebpackPlugin(defaults({}, {
|
||||||
|
title: route.title,
|
||||||
|
filename: `${route.name}.html`,
|
||||||
|
route: route,
|
||||||
|
dynamicMetaTags: route.dynamicMetaTags
|
||||||
|
}, templateConfig)))
|
||||||
).concat([
|
).concat([
|
||||||
new CopyWebpackPlugin({
|
new CopyWebpackPlugin({
|
||||||
patterns: [
|
patterns: [
|
||||||
|
@ -206,16 +238,16 @@ module.exports = {
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env.NODE_ENV': '"' + (process.env.NODE_ENV || 'development') + '"',
|
'process.env.NODE_ENV': `"${process.env.NODE_ENV || 'development'}"`,
|
||||||
'process.env.API_HOST': '"' + (process.env.API_HOST || 'https://api.scratch.mit.edu') + '"',
|
'process.env.API_HOST': `"${process.env.API_HOST || 'https://api.scratch.mit.edu'}"`,
|
||||||
'process.env.RECAPTCHA_SITE_KEY': '"' +
|
'process.env.RECAPTCHA_SITE_KEY': `"${
|
||||||
(process.env.RECAPTCHA_SITE_KEY || '6Lf6kK4UAAAAABKTyvdSqgcSVASEnMrCquiAkjVW') + '"',
|
process.env.RECAPTCHA_SITE_KEY || '6Lf6kK4UAAAAABKTyvdSqgcSVASEnMrCquiAkjVW'}"`,
|
||||||
'process.env.ASSET_HOST': '"' + (process.env.ASSET_HOST || 'https://assets.scratch.mit.edu') + '"',
|
'process.env.ASSET_HOST': `"${process.env.ASSET_HOST || 'https://assets.scratch.mit.edu'}"`,
|
||||||
'process.env.BACKPACK_HOST': '"' + (process.env.BACKPACK_HOST || 'https://backpack.scratch.mit.edu') + '"',
|
'process.env.BACKPACK_HOST': `"${process.env.BACKPACK_HOST || 'https://backpack.scratch.mit.edu'}"`,
|
||||||
'process.env.CLOUDDATA_HOST': '"' + (process.env.CLOUDDATA_HOST || 'clouddata.scratch.mit.edu') + '"',
|
'process.env.CLOUDDATA_HOST': `"${process.env.CLOUDDATA_HOST || 'clouddata.scratch.mit.edu'}"`,
|
||||||
'process.env.PROJECT_HOST': '"' + (process.env.PROJECT_HOST || 'https://projects.scratch.mit.edu') + '"',
|
'process.env.PROJECT_HOST': `"${process.env.PROJECT_HOST || 'https://projects.scratch.mit.edu'}"`,
|
||||||
'process.env.STATIC_HOST': '"' + (process.env.STATIC_HOST || 'https://uploads.scratch.mit.edu') + '"',
|
'process.env.STATIC_HOST': `"${process.env.STATIC_HOST || 'https://uploads.scratch.mit.edu'}"`,
|
||||||
'process.env.SCRATCH_ENV': '"' + (process.env.SCRATCH_ENV || 'development') + '"'
|
'process.env.SCRATCH_ENV': `"${process.env.SCRATCH_ENV || 'development'}"`
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
.concat(process.env.ANALYZE_BUNDLE === 'true' ? [
|
.concat(process.env.ANALYZE_BUNDLE === 'true' ? [
|
||||||
|
|
Loading…
Reference in a new issue