ff-stream-web

git clone git://archive.git.mtrnord.blog/MTRNord/ff-stream-web.git
Log | Files | Refs | README | LICENSE

commit e188388f87069cdc7d501b385d6b0e46c98fed60
parent 4d62b4fd00897193bb4fc124203f29fc3beb1d3d
Author: Konstantin Tarkus <hello@tarkus.me>
Date:   Tue,  1 Mar 2016 21:21:04 +0300

Add global error handling, compiled Jade templates for index and error pages

Diffstat:
Mpackage.json | 20+++++++++++---------
Dsrc/components/Html/Html.js | 57---------------------------------------------------------
Dsrc/components/Html/package.json | 6------
Msrc/server.js | 33++++++++++++++++++++++++++++-----
Asrc/views/error.jade | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/views/index.jade | 18++++++++++++++++++
Mtools/webpack.config.js | 3+++
7 files changed, 123 insertions(+), 77 deletions(-)

diff --git a/package.json b/package.json @@ -5,8 +5,8 @@ "npm": ">=3.3 <4" }, "dependencies": { - "babel-polyfill": "6.5.0", - "babel-runtime": "6.5.0", + "babel-polyfill": "6.6.1", + "babel-runtime": "6.6.1", "bluebird": "3.3.3", "body-parser": "1.15.0", "classnames": "2.2.3", @@ -24,12 +24,13 @@ "isomorphic-style-loader": "0.0.10", "jade": "1.11.0", "jsonwebtoken": "5.7.0", - "markdown-it": "^6.0.0", + "markdown-it": "6.0.0", "node-fetch": "1.3.3", "normalize.css": "3.0.3", "passport": "0.3.2", "passport-facebook": "2.1.0", "pg": "4.5.1", + "pretty-error": "2.0.0", "react": "0.14.7", "react-dom": "0.14.7", "react-routing": "0.0.7", @@ -39,16 +40,16 @@ "devDependencies": { "assets-webpack-plugin": "^3.3.0", "autoprefixer": "^6.3.3", - "babel-cli": "^6.5.1", + "babel-cli": "^6.6.0", "babel-eslint": "^5.0.0", "babel-loader": "^6.2.4", "babel-plugin-react-transform": "^2.0.0", - "babel-plugin-transform-runtime": "^6.5.2", - "babel-preset-es2015": "^6.5.0", + "babel-plugin-transform-runtime": "^6.6.0", + "babel-preset-es2015": "^6.6.0", "babel-preset-react": "^6.5.0", "babel-preset-stage-0": "^6.5.0", "browser-sync": "^2.11.1", - "core-js": "^2.1.1", + "core-js": "^2.1.3", "css-loader": "^0.23.1", "csscomb": "^3.1.8", "del": "^2.2.0", @@ -61,15 +62,16 @@ "gaze": "^0.5.2", "git-repository": "^0.1.1", "glob": "^7.0.0", + "jade-loader": "^0.8.0", "jest-cli": "^0.8.2", "jscs": "^2.10.1", "json-loader": "^0.5.4", "mkdirp": "^0.5.1", "ncp": "^2.0.0", - "postcss": "^5.0.17", + "postcss": "^5.0.18", "postcss-import": "^8.0.2", "postcss-loader": "^0.8.1", - "postcss-scss": "^0.1.5", + "postcss-scss": "^0.1.6", "precss": "^1.4.0", "raw-loader": "^0.5.1", "react-transform-catch-errors": "^1.0.2", diff --git a/src/components/Html/Html.js b/src/components/Html/Html.js @@ -1,57 +0,0 @@ -/** - * React Starter Kit (https://www.reactstarterkit.com/) - * - * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE.txt file in the root directory of this source tree. - */ - -import React, { Component, PropTypes } from 'react'; -import { analytics } from '../../config'; - -// https://analytics.google.com/ -const trackingCode = - 'window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;' + - `ga('create','${analytics.google.trackingId}','auto');ga('send','pageview')`; - -class Html extends Component { - - static propTypes = { - title: PropTypes.string, - description: PropTypes.string, - css: PropTypes.string, - body: PropTypes.string.isRequired, - entry: PropTypes.string.isRequired, - }; - - static defaultProps = { - title: '', - description: '', - }; - - render() { - return ( - <html className="no-js" lang=""> - <head> - <meta charSet="utf-8" /> - <meta httpEquiv="X-UA-Compatible" content="IE=edge" /> - <title>{this.props.title}</title> - <meta name="description" content={this.props.description} /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <link rel="apple-touch-icon" href="apple-touch-icon.png" /> - <style id="css" dangerouslySetInnerHTML={{ __html: this.props.css }} /> - </head> - <body> - <div id="app" dangerouslySetInnerHTML={{ __html: this.props.body }} /> - <script src={this.props.entry}></script> - <script dangerouslySetInnerHTML={{ __html: trackingCode }} /> - <script src="https://www.google-analytics.com/analytics.js" async defer /> - </body> - </html> - ); - } - -} - -export default Html; diff --git a/src/components/Html/package.json b/src/components/Html/package.json @@ -1,6 +0,0 @@ -{ - "name": "Html", - "version": "0.0.0", - "private": true, - "main": "./Html.js" -} diff --git a/src/server.js b/src/server.js @@ -15,14 +15,13 @@ import bodyParser from 'body-parser'; import expressJwt from 'express-jwt'; import expressGraphQL from 'express-graphql'; import jwt from 'jsonwebtoken'; -import React from 'react'; import ReactDOM from 'react-dom/server'; +import PrettyError from 'pretty-error'; import passport from './core/passport'; import schema from './data/schema'; import Router from './routes'; -import Html from './components/Html'; import assets from './assets'; -import { port, auth } from './config'; +import { port, auth, analytics } from './config'; const server = global.server = express(); @@ -82,7 +81,13 @@ server.use('/graphql', expressGraphQL(req => ({ server.get('*', async (req, res, next) => { try { let statusCode = 200; + const template = require('./views/index.jade'); const data = { title: '', description: '', css: '', body: '', entry: assets.main.js }; + + if (process.env.NODE_ENV === 'production') { + data.trackingId = analytics.google.trackingId; + } + const css = []; const context = { insertCss: styles => css.push(styles._getCss()), @@ -96,14 +101,32 @@ server.get('*', async (req, res, next) => { data.css = css.join(''); }); - const html = ReactDOM.renderToStaticMarkup(<Html {...data} />); - res.status(statusCode).send(`<!doctype html>\n${html}`); + res.status(statusCode); + res.send(template(data)); } catch (err) { next(err); } }); // +// Error handling +// ----------------------------------------------------------------------------- +const pe = new PrettyError(); +pe.skipNodeFiles(); +pe.skipPackage('express'); + +server.use((err, req, res, next) => { // eslint-disable-line no-unused-vars + console.log(pe.render(err)); // eslint-disable-line no-console + const template = require('./views/error.jade'); + const statusCode = err.status || 500; + res.status(statusCode); + res.send(template({ + message: err.message, + stack: process.env.NODE_ENV === 'production' ? '' : err.stack, + })); +}); + +// // Launch the server // ----------------------------------------------------------------------------- server.listen(port, () => { diff --git a/src/views/error.jade b/src/views/error.jade @@ -0,0 +1,63 @@ +doctype html +html(lang="en") + head + meta(charset="utf-8") + title Internal Server Error + meta(name="viewport", content="width=device-width, initial-scale=1") + style. + + * { + line-height: 1.2; + margin: 0; + } + + html { + color: #888; + display: table; + font-family: sans-serif; + height: 100%; + text-align: center; + width: 100%; + } + + body { + display: table-cell; + vertical-align: middle; + margin: 2em auto; + } + + h1 { + color: #555; + font-size: 2em; + font-weight: 400; + } + + p { + margin: 0 auto; + width: 280px; + } + + pre { + text-align: left; + max-width: 1000px; + margin: 0 auto; + } + + @media only screen and (max-width: 280px) { + + body, p { + width: 95%; + } + + h1 { + font-size: 1.5em; + margin: 0 0 0.3em; + } + + } + + body + h1 Internal Server Error + p Sorry, something went wrong. + pre= stack +// IE needs 512+ bytes: http://blogs.msdn.com/b/ieinternals/archive/2010/08/19/http-error-pages-in-internet-explorer.aspx diff --git a/src/views/index.jade b/src/views/index.jade @@ -0,0 +1,18 @@ +doctype html +html(class="no-js", lang="") + head + meta(charset="utf-8") + meta(http-equiv="x-ua-compatible", content="ie=edge") + title= title + meta(name="description", description=description) + meta(name="viewport", content="width=device-width, initial-scale=1") + link(rel="apple-touch-icon", href="apple-touch-icon.png") + style#css!= css + body + #app!= body + script(src=entry) + script. + window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date; + ga('create','#{trackingId}','auto');ga('send','pageview') + if trackingId + script(src="https://www.google-analytics.com/analytics.js", async=true, defer=true) diff --git a/tools/webpack.config.js b/tools/webpack.config.js @@ -92,6 +92,9 @@ const config = { }, { test: /\.(eot|ttf|wav|mp3)$/, loader: 'file-loader', + }, { + test: /\.jade$/, + loader: 'jade-loader', }, ], },