mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2025-03-27 05:11:42 -04:00
Split server and routes/config
Turn HtmlGeneratorPlugin into a module Turn server into dev-server and simplify it
This commit is contained in:
parent
707af8dbe9
commit
43788eb7d8
14 changed files with 117 additions and 177 deletions
2
Makefile
2
Makefile
|
@ -50,7 +50,7 @@ configure-fastly:
|
|||
# ------------------------------------
|
||||
|
||||
start:
|
||||
$(NODE) ./server/index.js
|
||||
$(NODE) ./dev-server/index.js
|
||||
|
||||
# ------------------------------------
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ var defaults = require('lodash.defaults');
|
|||
var glob = require('glob');
|
||||
var path = require('path');
|
||||
|
||||
var routes = require('../server/routes.json');
|
||||
var routes = require('../src/routes.json');
|
||||
|
||||
const FASTLY_SERVICE_ID = process.env.FASTLY_SERVICE_ID || '';
|
||||
const S3_BUCKET_NAME = process.env.S3_BUCKET_NAME || '';
|
||||
|
|
18
dev-server/handler.js
Normal file
18
dev-server/handler.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* Constructor
|
||||
*/
|
||||
function Handler (route) {
|
||||
var url = '/' + route.view + '.html';
|
||||
|
||||
return function (req, res, next) {
|
||||
req.url = url;
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a new instance
|
||||
*/
|
||||
module.exports = function (route) {
|
||||
return new Handler(route);
|
||||
};
|
40
dev-server/index.js
Normal file
40
dev-server/index.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
var express = require('express');
|
||||
var proxy = require('express-http-proxy');
|
||||
var webpackDevMiddleware = require('webpack-dev-middleware');
|
||||
var webpack = require('webpack');
|
||||
|
||||
var compiler = webpack(require('../webpack.config.js'));
|
||||
var handler = require('./handler');
|
||||
var log = require('./log');
|
||||
var routes = require('../src/routes.json');
|
||||
|
||||
// Create server
|
||||
var app = express();
|
||||
app.disable('x-powered-by');
|
||||
|
||||
// Server setup
|
||||
app.use(log());
|
||||
|
||||
// Bind routes
|
||||
for (var routeId in routes) {
|
||||
var route = routes[routeId];
|
||||
app.get(route.pattern, handler(route));
|
||||
}
|
||||
|
||||
app.use(webpackDevMiddleware(compiler));
|
||||
|
||||
var proxyHost = process.env.FALLBACK || '';
|
||||
if (proxyHost !== '') {
|
||||
// Fall back to scratchr2 in development
|
||||
// This proxy middleware must come last
|
||||
app.use('/', proxy(proxyHost));
|
||||
}
|
||||
|
||||
// Start listening
|
||||
var port = process.env.PORT || 8333;
|
||||
app.listen(port, function () {
|
||||
process.stdout.write('Server listening on port ' + port + '\n');
|
||||
if (proxyHost) {
|
||||
process.stdout.write('Proxy host: ' + proxyHost + '\n');
|
||||
}
|
||||
});
|
51
mustache-renderer-webpack-plugin/index.js
Normal file
51
mustache-renderer-webpack-plugin/index.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
var defaults = require('lodash.defaults');
|
||||
var fs = require('fs');
|
||||
var mustache = require('mustache');
|
||||
var path = require('path');
|
||||
|
||||
render = function (template, route, config) {
|
||||
config = config || {};
|
||||
// Route definition
|
||||
defaults(route, config);
|
||||
|
||||
// Render template
|
||||
return mustache.render(template, route);
|
||||
};
|
||||
|
||||
function MustacheRendererPlugin (options) {
|
||||
if (!options.templatePath) throw new Error('MustacheRendererPlugin requires a templatePath option');
|
||||
// Read template
|
||||
var template = fs.readFileSync(options.templatePath, 'utf8');
|
||||
this.template = template;
|
||||
this.routes = options.routes || {};
|
||||
this.config = options.config || {};
|
||||
return this;
|
||||
}
|
||||
|
||||
MustacheRendererPlugin.prototype.apply = function (compiler) {
|
||||
var template = this.template;
|
||||
var config = this.config;
|
||||
var routes = this.routes;
|
||||
|
||||
compiler.plugin('emit', function (compilation, callback) {
|
||||
var outputRoutes = {};
|
||||
routes.forEach(function (route) {
|
||||
var filename = route.view + '.html';
|
||||
var content = render(template, route, config);
|
||||
outputRoutes[route.pattern] = filename;
|
||||
compilation.assets[filename] = {
|
||||
source: function () {return content;},
|
||||
size: function () {return content.length;}
|
||||
};
|
||||
});
|
||||
var routeJson = JSON.stringify(outputRoutes);
|
||||
compilation.assets['routes.json'] = {
|
||||
source: function () {return routeJson;},
|
||||
size: function () {return routeJson.length;}
|
||||
};
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = MustacheRendererPlugin;
|
||||
|
|
@ -63,7 +63,6 @@
|
|||
"react-redux": "4.4.0",
|
||||
"react-slick": "0.9.2",
|
||||
"redux-thunk": "2.0.1",
|
||||
"routes-to-nginx-conf": "0.0.4",
|
||||
"sass-lint": "1.5.1",
|
||||
"sass-loader": "2.0.1",
|
||||
"scratchr2_translations": "git://github.com/LLK/scratchr2_translations.git#master",
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
var crypto = require('crypto');
|
||||
|
||||
var render = require('./render.js');
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
function Handler (route) {
|
||||
var output = render(route);
|
||||
var checksum = crypto.createHash('md5').update(output).digest('hex');
|
||||
|
||||
return function (req, res) {
|
||||
res.set({
|
||||
'Content-Type': 'text/html',
|
||||
'Cache-Control': 'public, max-age=31536000',
|
||||
'Etag': '"' + checksum + '"'
|
||||
});
|
||||
res.send(output);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a new instance
|
||||
*/
|
||||
module.exports = function (route) {
|
||||
return new Handler(route);
|
||||
};
|
|
@ -1,97 +0,0 @@
|
|||
if (typeof process.env.NEW_RELIC_LICENSE_KEY === 'string') {
|
||||
require('newrelic');
|
||||
}
|
||||
|
||||
var compression = require('compression');
|
||||
var express = require('express');
|
||||
var path = require('path');
|
||||
var proxy = require('express-http-proxy');
|
||||
var url = require('url');
|
||||
|
||||
var handler = require('./handler');
|
||||
var log = require('./log');
|
||||
var routes = require('./routes.json');
|
||||
|
||||
var isProduction = process.env.NODE_ENV === 'production';
|
||||
|
||||
// Create server
|
||||
var app = express();
|
||||
app.disable('x-powered-by');
|
||||
|
||||
// Block POST & PUT requests in production
|
||||
if (isProduction) {
|
||||
app.use(function (req, res, next) {
|
||||
if (req.method === 'GET') return next();
|
||||
if (req.method === 'OPTIONS') return next();
|
||||
if (req.method === 'HEAD') return next();
|
||||
|
||||
res.writeHead(405, {'content-type' : 'application/json'});
|
||||
res.end('{"error": "Method not allowed"}');
|
||||
});
|
||||
}
|
||||
|
||||
// Server setup
|
||||
app.use(log());
|
||||
app.use(compression());
|
||||
if (isProduction) {
|
||||
app.use(express.static(path.resolve(__dirname, '../build'), {
|
||||
etag: 'strong',
|
||||
maxAge: '1y'
|
||||
}));
|
||||
}
|
||||
app.use(function (req, res, next) {
|
||||
req._path = url.parse(req.url).path;
|
||||
next();
|
||||
});
|
||||
|
||||
// Bind routes
|
||||
for (var routeId in routes) {
|
||||
var route = routes[routeId];
|
||||
app.get(route.pattern, handler(route));
|
||||
}
|
||||
|
||||
if (typeof process.env.NODE_SENTRY_DSN === 'string') {
|
||||
var raven = require('raven');
|
||||
app.get('/sentrythrow', function mainHandler () { throw new Error('Sentry Test'); });
|
||||
|
||||
// These handlers must be applied _AFTER_ other routes have been applied
|
||||
app.use(raven.middleware.express.requestHandler(process.env.NODE_SENTRY_DSN));
|
||||
app.use(raven.middleware.express.errorHandler(process.env.NODE_SENTRY_DSN));
|
||||
app.use(function errorHandler (err, req, res, next) {
|
||||
res.append('X-Sentry-ID:' + res.sentry);
|
||||
res.status(500);
|
||||
next(err);
|
||||
});
|
||||
|
||||
raven.patchGlobal(process.env.NODE_SENTRY_DSN, function () {
|
||||
process.exit(-1);
|
||||
});
|
||||
}
|
||||
|
||||
if (!isProduction) {
|
||||
// Use webpack-dev-server in development
|
||||
var webpackDevMiddleware = require('webpack-dev-middleware');
|
||||
var webpack = require('webpack');
|
||||
var compiler = webpack(require('../webpack.config.js'));
|
||||
app.use(webpackDevMiddleware(compiler, {
|
||||
headers: {
|
||||
'X-From-Webpack': true
|
||||
}
|
||||
}));
|
||||
|
||||
var proxyHost = process.env.FALLBACK || '';
|
||||
if (proxyHost !== '') {
|
||||
// Fall back to scratchr2 in development
|
||||
// This proxy middleware must come last
|
||||
app.use('/', proxy(proxyHost));
|
||||
}
|
||||
}
|
||||
|
||||
// Start listening
|
||||
var port = process.env.PORT || 8333;
|
||||
app.listen(port, function () {
|
||||
process.stdout.write('Server listening on port ' + port + '\n');
|
||||
if (proxyHost) {
|
||||
process.stdout.write('Proxy host: ' + proxyHost + '\n');
|
||||
}
|
||||
});
|
|
@ -1,16 +0,0 @@
|
|||
var defaults = require('lodash.defaults');
|
||||
var fs = require('fs');
|
||||
var mustache = require('mustache');
|
||||
var path = require('path');
|
||||
|
||||
var config = require('./config');
|
||||
|
||||
module.exports = function (route) {
|
||||
// Route definition
|
||||
defaults(route, config);
|
||||
|
||||
// Render template
|
||||
var location = path.resolve(__dirname, './template.html');
|
||||
var template = fs.readFileSync(location, 'utf8');
|
||||
return mustache.render(template, route);
|
||||
};
|
|
@ -1,39 +1,10 @@
|
|||
var autoprefixer = require('autoprefixer');
|
||||
var CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
var MustacheRendererPlugin = require('./mustache-renderer-webpack-plugin');
|
||||
var path = require('path');
|
||||
var webpack = require('webpack');
|
||||
|
||||
var routes = require('./server/routes.json');
|
||||
|
||||
|
||||
function HtmlGeneratorPlugin (options) {
|
||||
this.options = options;
|
||||
return this;
|
||||
}
|
||||
|
||||
HtmlGeneratorPlugin.prototype.apply = function (compiler) {
|
||||
var render = this.options.render;
|
||||
var routes = this.options.routes;
|
||||
|
||||
compiler.plugin('emit', function (compilation, callback) {
|
||||
var outputRoutes = {};
|
||||
routes.forEach(function (route) {
|
||||
var filename = route.view + '.html';
|
||||
var content = render(route);
|
||||
outputRoutes[route.pattern] = filename;
|
||||
compilation.assets[filename] = {
|
||||
source: function () {return content;},
|
||||
size: function () {return content.length;}
|
||||
};
|
||||
});
|
||||
var routeJson = JSON.stringify(outputRoutes);
|
||||
compilation.assets['routes.json'] = {
|
||||
source: function () {return routeJson;},
|
||||
size: function () {return routeJson.length;}
|
||||
};
|
||||
callback();
|
||||
});
|
||||
};
|
||||
var routes = require('./src/routes.json');
|
||||
|
||||
// Prepare all entry points
|
||||
var entry = {
|
||||
|
@ -86,9 +57,10 @@ module.exports = {
|
|||
fs: 'empty'
|
||||
},
|
||||
plugins: [
|
||||
new HtmlGeneratorPlugin({
|
||||
render: require('./server/render.js'),
|
||||
routes: routes
|
||||
new MustacheRendererPlugin({
|
||||
templatePath: path.resolve(__dirname, './src/template.html'),
|
||||
routes: routes,
|
||||
config: require('./src/template-config.js')
|
||||
}),
|
||||
new CopyWebpackPlugin([
|
||||
{from: 'static'},
|
||||
|
|
Loading…
Add table
Reference in a new issue