mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-22 15:17:53 -05:00
Merge pull request #2 from thisandagain/router
Extend project to support multiple views
This commit is contained in:
commit
cfb6941ef9
13 changed files with 152 additions and 20 deletions
16
Makefile
16
Makefile
|
@ -1,5 +1,5 @@
|
|||
ESLINT=./node_modules/.bin/eslint
|
||||
LIVE=./node_modules/.bin/live-server
|
||||
NODE=node
|
||||
WATCH=./node_modules/.bin/watch
|
||||
WEBPACK=./node_modules/.bin/webpack
|
||||
|
||||
|
@ -11,7 +11,7 @@ build:
|
|||
@make webpack
|
||||
|
||||
clean:
|
||||
rm -rf ./build/*.*
|
||||
rm -rf ./build
|
||||
mkdir -p build
|
||||
|
||||
static:
|
||||
|
@ -27,6 +27,7 @@ test:
|
|||
|
||||
lint:
|
||||
$(ESLINT) ./*.js
|
||||
$(ESLINT) ./server/*.js
|
||||
$(ESLINT) ./src/*.jsx
|
||||
$(ESLINT) ./src/mixins/*.jsx
|
||||
$(ESLINT) ./src/views/**/*.jsx
|
||||
|
@ -34,15 +35,14 @@ lint:
|
|||
|
||||
# ------------------------------------
|
||||
|
||||
start:
|
||||
@make watch
|
||||
$(LIVE) ./build --port=8888 --wait=200 --no-browser
|
||||
|
||||
watch:
|
||||
$(WATCH) "make clean && make static" ./static &
|
||||
$(WEBPACK) -d --watch &
|
||||
$(WATCH) "make static" ./static &
|
||||
wait
|
||||
|
||||
start:
|
||||
$(NODE) ./server/index.js
|
||||
|
||||
# ------------------------------------
|
||||
|
||||
.PHONY: build clean static webpack test lint start watch
|
||||
.PHONY: build clean static webpack test lint watch start
|
||||
|
|
|
@ -6,10 +6,17 @@
|
|||
### To Build
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
During development, you can use `npm run watch` to cause any update you make to files in either `./static` or `./src` to trigger a rebuild of the project.
|
||||
|
||||
### To Run
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
Once running, open `http://localhost:8888` in your browser. Any update you make to files in either `./static` or `./src` should trigger a rebuild of the project and cause your browser to refresh to reflect those changes.
|
||||
Once running, open `http://localhost:8888` in your browser. If you wish to have the server reload automatically, you can install either [nodemon](https://github.com/remy/nodemon) or [forever](https://github.com/foreverjs/forever).
|
||||
|
||||
### To Test
|
||||
```bash
|
||||
|
|
13
package.json
13
package.json
|
@ -5,7 +5,9 @@
|
|||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "make start",
|
||||
"test": "make test"
|
||||
"test": "make test",
|
||||
"watch": "make watch",
|
||||
"build": "make build"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -17,7 +19,13 @@
|
|||
"url": "https://github.com/llk/scratch-www/issues"
|
||||
},
|
||||
"homepage": "https://github.com/llk/scratch-www#readme",
|
||||
"dependencies": {},
|
||||
"dependencies": {
|
||||
"bunyan": "1.4.0",
|
||||
"compression": "1.5.2",
|
||||
"express": "4.13.3",
|
||||
"lodash.defaults": "3.1.2",
|
||||
"mustache": "2.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer-loader": "2.1.0",
|
||||
"css-loader": "0.17.0",
|
||||
|
@ -25,7 +33,6 @@
|
|||
"eslint-plugin-react": "3.3.1",
|
||||
"json-loader": "0.5.2",
|
||||
"jsx-loader": "0.13.2",
|
||||
"live-server": "0.8.1",
|
||||
"node-sass": "3.3.2",
|
||||
"react": "0.13.3",
|
||||
"sass-loader": "2.0.1",
|
||||
|
|
4
server/defaults.json
Normal file
4
server/defaults.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"title": "Scratch - Imagine, Program, Share",
|
||||
"description": "Scratch is a free programming language and online community where you can create your own interactive stories, games, and animations."
|
||||
}
|
35
server/handler.js
Normal file
35
server/handler.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
var crypto = require('crypto');
|
||||
var defaults = require('lodash.defaults');
|
||||
var fs = require('fs');
|
||||
var mustache = require('mustache');
|
||||
var path = require('path');
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
function Handler (route) {
|
||||
// Route definition
|
||||
defaults(route, require('./defaults.json'));
|
||||
|
||||
// Render template
|
||||
var location = path.resolve(__dirname, './template.html');
|
||||
var template = fs.readFileSync(location, 'utf8');
|
||||
var output = mustache.render(template, 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': 'W/"' + checksum + '"'
|
||||
});
|
||||
res.send(output);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a new instance
|
||||
*/
|
||||
module.exports = function (route) {
|
||||
return new Handler(route);
|
||||
};
|
29
server/index.js
Normal file
29
server/index.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
var compression = require('compression');
|
||||
var express = require('express');
|
||||
var path = require('path');
|
||||
|
||||
var handler = require('./handler');
|
||||
var log = require('./log');
|
||||
var routes = require('./routes.json');
|
||||
|
||||
// Server setup
|
||||
var app = express();
|
||||
app.disable('x-powered-by');
|
||||
app.use(log());
|
||||
app.use(compression());
|
||||
app.use(express.static(path.resolve(__dirname, '../build'), {
|
||||
lastModified: true,
|
||||
maxAge: '1y'
|
||||
}));
|
||||
|
||||
// Bind routes
|
||||
for (var item in routes) {
|
||||
var route = routes[item];
|
||||
app.get(route.pattern, handler(route));
|
||||
}
|
||||
|
||||
// Start listening
|
||||
var port = process.env.PORT || 8888;
|
||||
app.listen(port, function () {
|
||||
process.stdout.write('Server listening on port ' + port + '\n');
|
||||
});
|
14
server/log.js
Normal file
14
server/log.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
var bunyan = require('bunyan');
|
||||
|
||||
module.exports = function () {
|
||||
var logger = bunyan.createLogger({
|
||||
name: 'www',
|
||||
serializers: {req: bunyan.stdSerializers.req}
|
||||
});
|
||||
|
||||
return function (req, res, next) {
|
||||
req.log = logger;
|
||||
req.log.info({req: req});
|
||||
next();
|
||||
};
|
||||
};
|
11
server/routes.json
Normal file
11
server/routes.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
[
|
||||
{
|
||||
"pattern": "/",
|
||||
"view": "splash"
|
||||
},
|
||||
{
|
||||
"pattern": "/about",
|
||||
"view": "about",
|
||||
"title": "About"
|
||||
}
|
||||
]
|
|
@ -8,8 +8,8 @@
|
|||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>Scratch - Imagine, Program, Share</title>
|
||||
<meta name="description" content="Scratch is a free programming language and online community where you can create your own interactive stories, games, and animations." />
|
||||
<title>Scratch - {{title}}</title>
|
||||
<meta name="description" content="{{description}}" />
|
||||
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:type" content="website" />
|
||||
|
@ -33,7 +33,7 @@
|
|||
<!-- Scripts -->
|
||||
<script src="/js/lib/react.js"></script>
|
||||
<script src="/js/main.bundle.js"></script>
|
||||
<script src="/js/splash.bundle.js"></script>
|
||||
<script src="/js/{{view}}.bundle.js"></script>
|
||||
|
||||
<!-- @todo Analytics (GA) -->
|
||||
<!-- @todo Monitoring (Raven) -->
|
|
@ -1,7 +1,7 @@
|
|||
module.exports = {
|
||||
getInitialState: function () {
|
||||
return {
|
||||
session: null
|
||||
session: {}
|
||||
};
|
||||
},
|
||||
componentWillMount: function () {
|
||||
|
|
15
src/views/about/about.jsx
Normal file
15
src/views/about/about.jsx
Normal file
|
@ -0,0 +1,15 @@
|
|||
var React = require('react');
|
||||
|
||||
require('./about.scss');
|
||||
|
||||
var View = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h1>I am the about page!</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.render(<View />, document.getElementById('view'));
|
3
src/views/about/about.scss
Normal file
3
src/views/about/about.scss
Normal file
|
@ -0,0 +1,3 @@
|
|||
#view {
|
||||
|
||||
}
|
|
@ -1,11 +1,18 @@
|
|||
var path = require('path');
|
||||
var webpack = require('webpack');
|
||||
var routes = require('./server/routes.json');
|
||||
|
||||
// Prepare all entry points
|
||||
var entry = {
|
||||
main: './src/main.jsx'
|
||||
};
|
||||
routes.forEach(function (route) {
|
||||
entry[route.view] = './src/views/' + route.view + '/' + route.view + '.jsx';
|
||||
});
|
||||
|
||||
// Config
|
||||
module.exports = {
|
||||
entry: {
|
||||
main: './src/main.jsx',
|
||||
splash: './src/views/splash/splash.jsx'
|
||||
},
|
||||
entry: entry,
|
||||
devtool: 'source-map',
|
||||
externals: {
|
||||
'react': 'React',
|
||||
|
|
Loading…
Reference in a new issue