350 open graph react #360

Merged
bones7242 merged 30 commits from 350-open-graph-react into master 2018-02-24 17:55:00 +01:00
8 changed files with 134 additions and 43 deletions
Showing only changes of commit fd3fc0f620 - Show all commits

View file

@ -17,7 +17,7 @@ spee.ch is a single-serving site that reads and publishes images and videos to a
* create your `speechConfig.js` file * create your `speechConfig.js` file
* copy `speechConfig.js.example` and name it `speechConfig.js` * copy `speechConfig.js.example` and name it `speechConfig.js`
* replace the `null` values in the config file with the appropriate values for your environement * replace the `null` values in the config file with the appropriate values for your environement
* to start the server, from your command line run `node speech.js` * to start the server, from your command line run `node serverindex.js`
* To run hot, use `nodemon` instead of `node` * To run hot, use `nodemon` instead of `node`
* visit [localhost:3000](http://localhost:3000) * visit [localhost:3000](http://localhost:3000)

32
helpers/handleRender.jsx Normal file
View file

@ -0,0 +1,32 @@
import { renderToString } from 'react-dom/server';
import { createStore } from 'redux';
import Reducer from '../react/reducers';
import renderFullPage from './renderFullPage.js';
import StaticRouter from 'react-router-dom/StaticRouter';
import GAListener from '../react/components/GAListener';
import App from '../react/app';
module.exports = (req, res) => {
let context = {};
// create a new Redux store instance
const store = createStore(Reducer);
// render component to a string
const html = renderToString(
<Provider store={store}>
<StaticRouter location={req.url} context={context}>
<GAListener>
<App />
</GAListener>
</StaticRouter>
</Provider>
);
// get the initial state from our Redux store
const preloadedState = store.getState();
// send the rendered page back to the client
res.send(renderFullPage(html, preloadedState));
};

21
helpers/renderFullPage.js Normal file
View file

@ -0,0 +1,21 @@
module.exports = (html, preloadedState) => {
// take the html and preloadedState and return the full page
return `
<!DOCTYPE html>
<html lang="en" prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">
<head>
<!--google font-->
<link href="https://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet">
</head>
<body id="main-body">
<div class="row row--tall flex-container--column">
<div id="react-app" class="row row--tall flex-container--column">${html}</div>
</div>
<script>
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\\u003c')}
</script>
<script src="/static/bundle.js"></script>
</body>
</html>
`;
};

View file

@ -7,7 +7,6 @@ const handlebarsHelpers = require('./helpers/handlebarsHelpers.js');
const { populateLocalsDotUser, serializeSpeechUser, deserializeSpeechUser } = require('./helpers/authHelpers.js'); const { populateLocalsDotUser, serializeSpeechUser, deserializeSpeechUser } = require('./helpers/authHelpers.js');
const config = require('./config/speechConfig.js'); const config = require('./config/speechConfig.js');
const logger = require('winston'); const logger = require('winston');
const { getDownloadDirectory } = require('./helpers/lbryApi');
const helmet = require('helmet'); const helmet = require('helmet');
const PORT = 3000; // set port const PORT = 3000; // set port
const app = express(); // create an Express application const app = express(); // create an Express application
@ -67,14 +66,7 @@ app.use(populateLocalsDotUser);
// start the server // start the server
db.sequelize db.sequelize
.sync() // sync sequelize .sync() // sync sequelize
.then(() => { // get the download directory from the daemon .then(() => { // require routes
logger.info('Retrieving daemon download directory...');
return getDownloadDirectory();
})
.then(hostedContentPath => {
// add the hosted content folder at a static path
app.use('/media', express.static(hostedContentPath));
// require routes
require('./routes/auth-routes.js')(app); require('./routes/auth-routes.js')(app);
require('./routes/api-routes.js')(app); require('./routes/api-routes.js')(app);
require('./routes/page-routes.js')(app); require('./routes/page-routes.js')(app);

View file

@ -6,7 +6,7 @@
"scripts": { "scripts": {
"test": "mocha --recursive", "test": "mocha --recursive",
"test-all": "mocha --recursive", "test-all": "mocha --recursive",
"start": "node speech.js", "start": "node server.js",
"lint": "eslint .", "lint": "eslint .",
"fix": "eslint . --fix", "fix": "eslint . --fix",
"precommit": "eslint .", "precommit": "eslint .",
@ -57,6 +57,7 @@
"sequelize-cli": "^3.0.0-3", "sequelize-cli": "^3.0.0-3",
"sleep": "^5.1.1", "sleep": "^5.1.1",
"universal-analytics": "^0.4.13", "universal-analytics": "^0.4.13",
"webpack-node-externals": "^1.6.0",
"whatwg-fetch": "^2.0.3", "whatwg-fetch": "^2.0.3",
"winston": "^2.3.1", "winston": "^2.3.1",
"winston-slack-webhook": "billbitt/winston-slack-webhook" "winston-slack-webhook": "billbitt/winston-slack-webhook"
@ -64,12 +65,15 @@
"devDependencies": { "devDependencies": {
"babel-core": "^6.26.0", "babel-core": "^6.26.0",
"babel-loader": "^7.1.2", "babel-loader": "^7.1.2",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",
"babel-preset-es2015": "^6.24.1", "babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1", "babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1", "babel-preset-stage-2": "^6.24.1",
"babel-register": "^6.26.0",
"chai": "^4.1.2", "chai": "^4.1.2",
"chai-http": "^3.0.0", "chai-http": "^3.0.0",
"css-loader": "^0.28.9",
"eslint": "3.19.0", "eslint": "3.19.0",
"eslint-config-standard": "10.2.1", "eslint-config-standard": "10.2.1",
"eslint-plugin-import": "^2.2.0", "eslint-plugin-import": "^2.2.0",

View file

@ -10,18 +10,24 @@ import rootSaga from 'sagas';
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
import GAListener from 'components/GAListener'; import GAListener from 'components/GAListener';
import App from './app'; import App from './app';
// get the state from a global variable injected into the server-generated HTML
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
const preloadedState = window.__PRELOADED_STATE__ || null;
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
// Allow the passed state to be garbage-collected
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
delete window.__PRELOADED_STATE__
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
// create and apply middleware
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
const sagaMiddleware = createSagaMiddleware(); const sagaMiddleware = createSagaMiddleware();
const middleware = applyMiddleware(sagaMiddleware); const middleware = applyMiddleware(sagaMiddleware);
const reduxMiddleware = window.__REDUX_DEVTOOLS_EXTENSION__ ? compose(middleware, window.__REDUX_DEVTOOLS_EXTENSION__()) : middleware;
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
const enhancer = window.__REDUX_DEVTOOLS_EXTENSION__ ? compose(middleware, window.__REDUX_DEVTOOLS_EXTENSION__()) : middleware; // create teh store
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
let store = createStore(Reducer, preloadedState, reduxMiddleware);
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
let store = createStore(
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
Reducer,
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
enhancer,
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
);
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
// run the saga middlweare
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
sagaMiddleware.run(rootSaga); sagaMiddleware.run(rootSaga);
// render the app
neb-b commented 2018-02-23 20:57:29 +01:00 (Migrated from github.com)
Review

Probably don't need these console.logs here.

Probably don't need these `console.log`s here.
render( render(
<Provider store={store}> <Provider store={store}>
<BrowserRouter> <BrowserRouter>

View file

@ -1,4 +1,5 @@
const { site } = require('../config/speechConfig.js'); const { site } = require('../config/speechConfig.js');
// const handleRender = require('../helpers/handleRender.jsx');
module.exports = (app) => { module.exports = (app) => {
// route for the home page // route for the home page

View file

@ -1,11 +1,16 @@
const Path = require('path'); const Path = require('path');
neb-b commented 2018-02-23 21:17:39 +01:00 (Migrated from github.com)
Review

I would recommend creating separate webpack configs for dev/prod. Before we did our big restructure changes the apps webpack setup had three files:

A base config: contains the generic stuff like babel, entry/output points, css loader, etc.
A dev config which extends the base config: contains stuff like watch: true (not needed in prod) and source maps
A prod config which extends the base config: contains stuff like minification (that's the main thing)

webpack-merge is a great tool for this
https://github.com/survivejs/webpack-merge

I would recommend creating separate webpack configs for dev/prod. Before we did our big restructure changes the apps webpack setup had three files: A base config: contains the generic stuff like babel, entry/output points, css loader, etc. A dev config which extends the base config: contains stuff like `watch: true` (not needed in prod) and source maps A prod config which extends the base config: contains stuff like minification (that's the main thing) `webpack-merge` is a great tool for this https://github.com/survivejs/webpack-merge
const nodeExternals = require('webpack-node-externals');
const REACT_ROOT = Path.resolve(__dirname, 'react/'); const REACT_ROOT = Path.resolve(__dirname, 'react/');
module.exports = { console.log('REACT_ROOT:', REACT_ROOT);
entry : ['babel-polyfill', 'whatwg-fetch', './react/index.js'],
module.exports = [
{
target: 'web',
entry : ['babel-polyfill', 'whatwg-fetch', './react/client.js'],
output: { output: {
path : Path.join(__dirname, '/public/bundle/'), path : Path.join(__dirname, 'public/bundle/'),
publicPath: 'public/bundle/',
filename : 'bundle.js', filename : 'bundle.js',
}, },
watch : true, watch : true,
@ -29,4 +34,34 @@ module.exports = {
], ],
extensions: ['.js', '.jsx', '.scss'], extensions: ['.js', '.jsx', '.scss'],
}, },
}; },
{
target : 'node',
externals: nodeExternals(),
entry : ['./index.js'],
output : {
path : __dirname,
publicPath: '',
filename : 'server.js',
},
watch : true,
module: {
loaders: [
{
loader : 'babel-loader',
exclude: /node_modules/,
query : {
presets: ['es2015'],
},
},
],
},
resolve: {
modules: [
'node_modules',
__dirname,
],
extensions: ['.js'],
},
},
];