├── .gitattributes
├── .gitignore
├── Chapter 01
└── 1-started
│ ├── .DS_Store
│ ├── .babelrc
│ ├── .editorconfig
│ ├── .eslintrc
│ ├── .gitignore
│ ├── README.md
│ ├── client.js
│ ├── components
│ ├── App.js
│ └── Html.js
│ ├── core
│ └── .gitignore
│ ├── data
│ └── .gitignore
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ └── robots.txt
│ ├── routes
│ └── .gitignore
│ ├── server.js
│ ├── test
│ └── .gitignore
│ ├── tools
│ ├── .eslintrc
│ ├── build.js
│ ├── clean.js
│ ├── run.js
│ ├── runServer.js
│ ├── serve.js
│ ├── start.js
│ └── webpack.config.js
│ └── yarn.lock
├── Chapter 02
└── 2-react
│ ├── .babelrc
│ ├── .editorconfig
│ ├── .eslintrc
│ ├── .gitignore
│ ├── README.md
│ ├── client.js
│ ├── components
│ ├── App.js
│ ├── Header
│ │ ├── Header.js
│ │ └── package.json
│ ├── Html
│ │ ├── Html.js
│ │ └── package.json
│ └── Layout
│ │ ├── Layout.js
│ │ └── package.json
│ ├── core
│ └── Router.js
│ ├── data
│ └── .gitignore
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ └── robots.txt
│ ├── routes
│ ├── .gitignore
│ ├── Home
│ │ ├── Hero.js
│ │ ├── Home.js
│ │ └── package.json
│ └── NotFound
│ │ ├── NotFound.js
│ │ └── package.json
│ ├── server.js
│ ├── test
│ └── .gitignore
│ ├── tools
│ ├── .eslintrc
│ ├── build.js
│ ├── clean.js
│ ├── run.js
│ ├── runServer.js
│ ├── serve.js
│ ├── start.js
│ └── webpack.config.js
│ └── yarn.lock
├── Chapter 04
└── 4-browsersync
│ ├── .babelrc
│ ├── .editorconfig
│ ├── .eslintrc
│ ├── .gitignore
│ ├── README.md
│ ├── client.js
│ ├── components
│ ├── App.js
│ ├── Header
│ │ ├── Header.js
│ │ ├── header.jpg
│ │ └── package.json
│ ├── Html
│ │ ├── Html.js
│ │ └── package.json
│ ├── Layout
│ │ ├── Layout.js
│ │ ├── Layout.scss
│ │ ├── header.jpg
│ │ └── package.json
│ └── variables.scss
│ ├── core
│ └── Router.js
│ ├── data
│ └── .gitignore
│ ├── package-lock.json
│ ├── package.json
│ ├── postcss.config.js
│ ├── public
│ ├── favicon.ico
│ └── robots.txt
│ ├── routes
│ ├── .gitignore
│ ├── Home
│ │ ├── Hero.js
│ │ ├── Home.js
│ │ └── package.json
│ └── NotFound
│ │ ├── NotFound.js
│ │ └── package.json
│ ├── server.js
│ ├── test
│ └── .gitignore
│ ├── tools
│ ├── .eslintrc
│ ├── build.js
│ ├── clean.js
│ ├── run.js
│ ├── runServer.js
│ ├── serve.js
│ ├── start.js
│ └── webpack.config.js
│ └── yarn.lock
├── Chapter 05
└── 5-react-server
│ ├── .babelrc
│ ├── .editorconfig
│ ├── .eslintrc
│ ├── .gitignore
│ ├── README.md
│ ├── api
│ └── test.js
│ ├── client.js
│ ├── components
│ ├── App.js
│ ├── Context.js
│ ├── CurrentTime
│ │ ├── CurrentTime.js
│ │ └── package.json
│ ├── Header
│ │ ├── Header.js
│ │ ├── header.jpg
│ │ └── package.json
│ ├── Html
│ │ ├── Html.js
│ │ └── package.json
│ ├── Layout
│ │ ├── Layout.js
│ │ ├── Layout.scss
│ │ ├── header.jpg
│ │ └── package.json
│ ├── LikeButton
│ │ ├── LikeButton.js
│ │ └── package.json
│ └── variables.scss
│ ├── core
│ ├── Router.js
│ └── fetch
│ │ ├── fetch.client.js
│ │ ├── fetch.server.js
│ │ └── package.json
│ ├── data
│ └── .gitignore
│ ├── package-lock.json
│ ├── package.json
│ ├── postcss.config.js
│ ├── public
│ ├── Thumbs.db
│ ├── favicon.ico
│ └── robots.txt
│ ├── routes
│ ├── .gitignore
│ ├── Home
│ │ ├── Hero.js
│ │ ├── Home.js
│ │ └── package.json
│ ├── NotFound
│ │ ├── NotFound.js
│ │ └── package.json
│ └── Test
│ │ ├── Test.js
│ │ └── package.json
│ ├── server.js
│ ├── test
│ └── .gitignore
│ ├── tools
│ ├── .eslintrc
│ ├── build.js
│ ├── clean.js
│ ├── run.js
│ ├── runServer.js
│ ├── serve.js
│ ├── start.js
│ └── webpack.config.js
│ └── yarn.lock
├── Chapter 06
└── 6-graphql
│ ├── .DS_Store
│ ├── .babelrc
│ ├── .editorconfig
│ ├── .gitignore
│ ├── README.md
│ ├── client.js
│ ├── components
│ ├── .DS_Store
│ ├── App.js
│ ├── Context.js
│ ├── CurrentTime
│ │ ├── CurrentTime.js
│ │ └── package.json
│ ├── Header
│ │ ├── Header.js
│ │ └── header.jpg
│ ├── Html
│ │ ├── Html.js
│ │ └── package.json
│ ├── Layout
│ │ ├── Layout.js
│ │ ├── Layout.scss
│ │ ├── header.jpg
│ │ └── package.json
│ ├── LikeButton
│ │ ├── LikeButton.js
│ │ └── package.json
│ └── variables.scss
│ ├── core
│ ├── .DS_Store
│ ├── Router.js
│ └── fetch
│ │ ├── fetch.client.js
│ │ ├── fetch.server.js
│ │ └── package.json
│ ├── data
│ ├── models
│ │ ├── .eslintrc
│ │ ├── Offer.js
│ │ ├── Tag.js
│ │ ├── User.js
│ │ └── index.js
│ ├── queries
│ │ ├── greeting.js
│ │ ├── offer.js
│ │ └── viewer.js
│ ├── schema.js
│ ├── sequelize.js
│ └── types
│ │ ├── OfferType.js
│ │ └── UserType.js
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ └── robots.txt
│ ├── routes
│ ├── .DS_Store
│ ├── Home
│ │ ├── Hero.js
│ │ ├── Home.js
│ │ └── package.json
│ ├── NotFound
│ │ ├── NotFound.js
│ │ └── package.json
│ └── Test
│ │ ├── Test.js
│ │ └── package.json
│ ├── server.js
│ ├── test
│ └── .gitignore
│ ├── tools
│ ├── .eslintrc
│ ├── build.js
│ ├── clean.js
│ ├── run.js
│ ├── runServer.js
│ ├── serve.js
│ ├── start.js
│ └── webpack.config.js
│ └── yarn.lock
├── Chapter 07
└── 7-routing
│ ├── .babelrc
│ ├── README.md
│ ├── index.js
│ ├── modules
│ ├── About.js
│ ├── App.js
│ ├── Home.js
│ ├── Repo.js
│ ├── Repos.js
│ ├── ReposWithRouter.js
│ ├── Root.js
│ └── RouteWithSubRoutes.js
│ ├── package.json
│ ├── public
│ ├── bundle.js
│ └── bundle.js.map
│ ├── routesConfig.js
│ ├── server.js
│ ├── serverWithInitialData.js
│ ├── webpack.config.js
│ └── yarn.lock
├── Chapter 08
├── 8-auth
│ ├── .DS_Store
│ ├── .babelrc
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── bundle.js
│ │ └── bundle.js.map
│ ├── routesConfig.js
│ ├── serverWithInitialData.js
│ ├── src
│ │ ├── .DS_Store
│ │ ├── actions
│ │ │ └── types.js
│ │ ├── components
│ │ │ ├── About.js
│ │ │ ├── App.js
│ │ │ ├── Home.js
│ │ │ ├── Repo.js
│ │ │ ├── Repos.js
│ │ │ ├── ReposWithRouter.js
│ │ │ ├── Root.js
│ │ │ ├── RouteWithSubRoutes.js
│ │ │ └── hoc
│ │ │ │ └── require_auth.js
│ │ ├── index.js
│ │ └── reducers
│ │ │ ├── auth_reducer.js
│ │ │ └── index.js
│ ├── webpack.config.js
│ └── yarn.lock
└── __MACOSX
│ └── 8-auth
│ └── ._.DS_Store
├── Chapter 09
└── B05226_09_Code
│ ├── .DS_Store
│ ├── .babelrc
│ ├── README.md
│ ├── nightwatch.json
│ ├── package.json
│ ├── public
│ ├── bundle.js
│ └── bundle.js.map
│ ├── routesConfig.js
│ ├── selenium-debug.log
│ ├── serverWithInitialData.js
│ ├── src
│ ├── .DS_Store
│ ├── actions
│ │ └── types.js
│ ├── components
│ │ ├── About.js
│ │ ├── App.js
│ │ ├── Home.js
│ │ ├── Repo.js
│ │ ├── Repos.js
│ │ ├── ReposWithRouter.js
│ │ ├── Root.js
│ │ ├── RouteWithSubRoutes.js
│ │ └── hoc
│ │ │ └── require_auth.js
│ ├── index.js
│ ├── reducers
│ │ ├── auth_reducer.js
│ │ └── index.js
│ └── tests
│ │ ├── EnzymeTest.js
│ │ ├── PlainTest.js
│ │ ├── it
│ │ └── NightwatchTest.js
│ │ └── tests_helper.js
│ ├── webpack.config.js
│ └── yarn.lock
├── LICENSE
├── README.md
└── Software and Hardware List.pdf
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | node_modules
3 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/c3589be168397c7594090b9fa1a15bf8b25dd188/Chapter 01/1-started/.DS_Store
--------------------------------------------------------------------------------
/Chapter 01/1-started/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env", "stage-2", "react"],
3 | "plugins": [
4 | "transform-runtime"
5 | ]
6 | }
--------------------------------------------------------------------------------
/Chapter 01/1-started/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 2
12 |
13 | # We recommend you to keep these unchanged
14 | end_of_line = lf
15 | charset = utf-8
16 | trim_trailing_whitespace = true
17 | insert_final_newline = true
18 |
19 | [*.md]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-quotes": 0,
5 | "jsx-quotes": [2, "prefer-double"],
6 | "comma-dangle": [2, "never"]
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/.gitignore:
--------------------------------------------------------------------------------
1 | # Include your project-specific ignores in this file
2 | # Read about how to use .gitignore: https://help.github.com/articles/ignoring-files
3 |
4 | build
5 | node_modules
6 | ncp-debug.log
7 | npm-debug.log
8 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/README.md:
--------------------------------------------------------------------------------
1 | ## Learning Isomorphic Web Application Development
2 |
3 | > Example source code accompanying "Learning Isomorphic Web Application Development" book
4 |
5 | 
6 |
7 | ### Table of Contents
8 |
9 | > **Chapter 01: Getting Started with Isomorphic Web Apps**
10 | Chapter 1: Getting Started with Isomorphic Web Apps
11 | Chapter 2: How to Compose Web UIs by Using React
12 | Chapter 3: Working with CSS Styles and Media Assets
13 | Chapter 4: Configuring Server-side Rendering
14 | Chapter 5: Creating an API Backend with GraphQL
15 | Chapter 6: Fetching Data with Relay
16 | Chapter 7: Implementing Routing and Navigation
17 | Chapter 8: Authentication and authorization
18 | Chapter 9: Testing and Deploying
19 |
20 | ### Prerequisites
21 |
22 | * Node.js v4.0, NPM v3.0 and newer ([download](https://nodejs.org/en/download/))
23 | * Text editor or IDE with ES6/ES2015 and JSX support
24 | * React Developer Tools ([download](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en))
25 |
26 | ### Getting Started
27 |
28 | Before you can launch the app, install project's dependencies by running:
29 |
30 | ```sh
31 | $ npm install
32 | ```
33 |
34 | To build the project and start a development web server run:
35 |
36 | ```sh
37 | $ npm run serve
38 | ```
39 |
40 | Then open [http://localhost:3000/](http://localhost:3000/) in your browser to test the app.
41 |
42 | ### Copyright
43 |
44 | © 2015 by Konstantin Tarkus ([@koistya](https://twitter.com/koistya)), Packt Publishing. All rights reserved.
45 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/client.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2015 Konstantin Tarkus, Packt Publishing
4 | * All rights reserved.
5 | */
6 |
7 | import 'babel-core/register';
8 | import React from 'react';
9 | import ReactDOM from 'react-dom';
10 | import App from './components/App';
11 |
12 | function run() {
13 | ReactDOM.hydrate(
Current date and time is {timeString}
37 |);
26 | res.send('\n' + html);
27 | });
28 |
29 | server.listen(port, () => console.log(
30 | `Node.js server is listening at http://localhost:${port}/`
31 | ));
32 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/test/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/c3589be168397c7594090b9fa1a15bf8b25dd188/Chapter 01/1-started/test/.gitignore
--------------------------------------------------------------------------------
/Chapter 01/1-started/tools/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-console": 0
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/tools/build.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import fs from 'fs';
7 | import del from 'del';
8 | import webpack from 'webpack';
9 | import Promise from 'bluebird';
10 | import run from './run';
11 | import webpackConfig from './webpack.config';
12 |
13 | async function clean() {
14 | await del(['build/*']);
15 | }
16 |
17 | async function copy() {
18 | const ncp = Promise.promisify(require('ncp'));
19 | if (!fs.existsSync('build')) fs.mkdirSync('build');
20 | await ncp('public', 'build/public');
21 | await ncp('package.json', 'build/package.json');
22 | }
23 |
24 | function bundle({ watch }) {
25 | return new Promise((resolve, reject) => {
26 | let bundlerRunCount = 0;
27 | const bundler = webpack(webpackConfig);
28 | const cb = (err, stats) => {
29 | if (err) {
30 | reject(err);
31 | return;
32 | }
33 |
34 | console.log(stats.toString(webpackConfig[0].stats));
35 |
36 | if (++bundlerRunCount === (watch ? webpackConfig.length : 1)) {
37 | resolve();
38 | }
39 | };
40 |
41 | if (watch) {
42 | bundler.watch(200, cb);
43 | } else {
44 | bundler.run(cb);
45 | }
46 | });
47 | }
48 |
49 | async function build(options = { watch: false }) {
50 | await run(clean);
51 | await run(copy);
52 | await run(bundle, options);
53 | }
54 |
55 | export default build;
56 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/tools/clean.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import del from 'del';
7 |
8 | async function clean() {
9 | await del(['build/*']);
10 | }
11 |
12 | export default clean;
13 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/tools/run.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | function format(time) {
7 | return time.toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, '$1');
8 | }
9 |
10 | function run(fn, options) {
11 | const task = typeof fn.default === 'undefined' ? fn : fn.default;
12 | const start = new Date();
13 | console.log(
14 | `[${format(start)}] Starting '${task.name}${options ? `(${options})` : ''}'...`
15 | );
16 | return task(options).then(() => {
17 | const end = new Date();
18 | const time = end.getTime() - start.getTime();
19 | console.log(
20 | `[${format(end)}] Finished '${task.name}${options ? `(${options})` : ''}' after ${time} ms`
21 | );
22 | });
23 | }
24 |
25 | if (process.mainModule.children.length === 0 && process.argv.length > 2) {
26 | delete require.cache[__filename];
27 | const module = require(`./${process.argv[2]}.js`).default;
28 | run(module).catch(err => console.error(err.stack));
29 | }
30 |
31 | export default run;
32 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/tools/runServer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import path from 'path';
7 | import cp from 'child_process';
8 | import webpackConfig from './webpack.config';
9 |
10 | // Should match the text string used in `server.js/server.listen(...)`
11 | const RUNNING_REGEXP = /Node\.js server is listening at http:\/\/(.*?)\//;
12 |
13 | let server;
14 | const { output } = webpackConfig.find(x => x.target === 'node');
15 | const serverPath = path.join(output.path, output.filename);
16 |
17 | // Launch or restart the Node.js server
18 | function runServer(cb) {
19 | function onStdOut(data) {
20 | const time = new Date().toTimeString();
21 | const match = data.toString('utf8').match(RUNNING_REGEXP);
22 |
23 | process.stdout.write(time.replace(/.*(\d{2}:\d{2}:\d{2}).*/, '[$1] '));
24 | process.stdout.write(data);
25 |
26 | if (match) {
27 | server.stdout.removeListener('data', onStdOut);
28 | server.stdout.on('data', message => process.stdout.write(message));
29 | if (cb) {
30 | cb(null, match[1]);
31 | }
32 | }
33 | }
34 |
35 | if (server) {
36 | server.kill('SIGTERM');
37 | }
38 |
39 | server = cp.spawn('node', [serverPath], {
40 | env: Object.assign({ NODE_ENV: 'development' }, process.env),
41 | silent: false
42 | });
43 |
44 | server.stdout.on('data', onStdOut);
45 | server.stderr.on('data', x => process.stderr.write(x));
46 | }
47 |
48 | process.on('exit', () => {
49 | if (server) {
50 | server.kill('SIGTERM');
51 | }
52 | });
53 |
54 | export default runServer;
55 |
56 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/tools/serve.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import path from 'path';
7 | import cp from 'child_process';
8 | import Promise from 'bluebird';
9 | import build from './build';
10 | import run from './run';
11 |
12 | async function serve() {
13 | const watch = true;
14 | const gaze = Promise.promisify(require('gaze'));
15 | await run(build, { watch });
16 | await new Promise((resolve, reject) => {
17 | function start() {
18 | const server = cp.spawn(
19 | 'node',
20 | [path.join(__dirname, '../build/server.js')],
21 | {
22 | env: Object.assign({ NODE_ENV: 'development' }, process.env),
23 | silent: false
24 | }
25 | );
26 |
27 | server.stdout.on('data', (data) => {
28 | process.stdout.write(new Date().toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, '[$1] '));
29 | process.stdout.write(data);
30 | if (data.toString('utf8').includes('Node.js server is listening at')) {
31 | resolve();
32 | }
33 | });
34 | server.stderr.on('data', data => process.stderr.write(data));
35 | server.once('error', err => reject(err));
36 | process.on('exit', () => server.kill('SIGTERM'));
37 | return server;
38 | }
39 |
40 | let server = start();
41 |
42 | if (watch) {
43 | gaze('build/server.js').then((watcher) => {
44 | watcher.on('changed', () => {
45 | server.kill('SIGTERM');
46 | server = start();
47 | });
48 | });
49 | }
50 | });
51 | }
52 |
53 | export default serve;
54 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/tools/start.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import path from 'path';
7 | import Browsersync from 'browser-sync';
8 | import webpack from 'webpack';
9 | import webpackDevMiddleware from 'webpack-dev-middleware';
10 | import webpackHotMiddleware from 'webpack-hot-middleware';
11 | import run from './run';
12 | import runServer from './runServer';
13 | import webpackConfig from './webpack.config';
14 |
15 | // Launch the development web server with Browsersync and HMR
16 | async function start() {
17 | await run(require('./clean'));
18 | await new Promise((resolve) => {
19 | // Inject HMR functionality into client-side bundle configurations
20 | /* eslint-disable no-param-reassign */
21 | webpackConfig.filter(x => x.target !== 'node').forEach((x) => {
22 | x.entry = [x.entry, 'webpack-hot-middleware/client'];
23 | x.plugins.push(new webpack.HotModuleReplacementPlugin());
24 | x.plugins.push(new webpack.NoErrorsPlugin());
25 | });
26 | /* eslint-enable no-param-reassign */
27 |
28 | const bundler = webpack(webpackConfig);
29 | const middleware = [
30 | webpackDevMiddleware(bundler, {
31 | stats: webpackConfig[0].stats
32 | }),
33 | ...(bundler.compilers
34 | .filter(compiler => compiler.options.target !== 'node')
35 | .map(compiler => webpackHotMiddleware(compiler)))
36 | ];
37 | let handleServerBundleComplete = () => {
38 | runServer((err, host) => {
39 | if (!err) {
40 | const bs = Browsersync.create();
41 | bs.init({
42 | proxy: { target: host, middleware },
43 | serveStatic: [
44 | path.join(__dirname, '../public'),
45 | path.join(__dirname, '../node_modules/graphiql'),
46 | path.join(__dirname, '../node_modules/react/dist'),
47 | path.join(__dirname, '../node_modules/react-dom/dist'),
48 | path.join(__dirname, '../node_modules/whatwg-fetch')
49 | ]
50 | }, resolve);
51 | handleServerBundleComplete = runServer;
52 | }
53 | });
54 | };
55 |
56 | bundler.plugin('done', () => handleServerBundleComplete());
57 | });
58 | }
59 |
60 | export default start;
61 |
62 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env", "stage-2", "react"],
3 | "plugins": [
4 | "transform-runtime"
5 | ]
6 | }
--------------------------------------------------------------------------------
/Chapter 02/2-react/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 2
12 |
13 | # We recommend you to keep these unchanged
14 | end_of_line = lf
15 | charset = utf-8
16 | trim_trailing_whitespace = true
17 | insert_final_newline = true
18 |
19 | [*.md]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-quotes": 0,
5 | "jsx-quotes": [2, "prefer-double"],
6 | "comma-dangle": [2, "never"]
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/.gitignore:
--------------------------------------------------------------------------------
1 | # Include your project-specific ignores in this file
2 | # Read about how to use .gitignore: https://help.github.com/articles/ignoring-files
3 |
4 | build
5 | node_modules
6 | ncp-debug.log
7 | npm-debug.log
8 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/README.md:
--------------------------------------------------------------------------------
1 | ## Learning Isomorphic Web Application Development
2 |
3 | > Example source code accompanying "Learning Isomorphic Web Application Development" book
4 |
5 | 
6 |
7 | ### Table of Contents
8 |
9 | Chapter 1: Getting Started with Isomorphic Web Apps
10 | > **Chapter 2: Creating a web UI with React**
11 | Chapter 3: Working with CSS Styles and Media Assets
12 | Chapter 4: Configuring Server-side Rendering
13 | Chapter 5: Creating an API Backend with GraphQL
14 | Chapter 6: Fetching Data with Relay
15 | Chapter 7: Implementing Routing and Navigation
16 | Chapter 8: Authentication and authorization
17 | Chapter 9: Testing and Deploying
18 |
19 | ### Prerequisites
20 |
21 | * Node.js v4.0, NPM v3.0 and newer ([download](https://nodejs.org/en/download/))
22 | * Text editor or IDE with ES6/ES2015 and JSX support
23 | * React Developer Tools ([download](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en))
24 |
25 | ### Getting Started
26 |
27 | Before you can launch the app, install project's dependencies by running:
28 |
29 | ```sh
30 | $ npm install
31 | ```
32 |
33 | To build the project and start a development web server run:
34 |
35 | ```sh
36 | $ npm run serve
37 | ```
38 |
39 | Then open [http://localhost:3000/](http://localhost:3000/) in your browser to test the app.
40 |
41 | ### Copyright
42 |
43 | © 2015 by Konstantin Tarkus ([@koistya](https://twitter.com/koistya)), Packt Publishing. All rights reserved.
44 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/client.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import 'babel-core/register';
7 | import React from 'react';
8 | import ReactDOM from 'react-dom';
9 | import Router from './core/Router';
10 |
11 | function run() {
12 | const component = Router.match({ path: window.location.pathname });
13 | ReactDOM.hydrate(component, document.getElementById('app'));
14 | }
15 |
16 | const loadedStates = ['complete', 'loaded', 'interactive'];
17 |
18 | if (loadedStates.includes(document.readyState) && document.body) {
19 | run();
20 | } else {
21 | window.addEventListener('DOMContentLoaded', run, false);
22 | }
23 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/components/App.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React, { Component } from 'react';
7 | import moment from 'moment';
8 |
9 | class App extends Component {
10 |
11 | constructor(props) {
12 | super(props);
13 | this.state = { time: null };
14 | }
15 |
16 | componentDidMount() {
17 | this.tick();
18 | this.interval = setInterval(this.tick.bind(this), 200);
19 | }
20 |
21 | componentWillUnmount() {
22 | clearInterval(this.interval);
23 | }
24 |
25 | tick() {
26 | this.setState({ time: new Date() });
27 | }
28 |
29 | render() {
30 | const time = this.state.time;
31 | const timeString = time && moment(time).format('h:mm:ss a');
32 | return (
33 |
Current date and time is {timeString}
36 |
37 | );
38 | }
39 |
40 | }
41 |
42 | export default App;
43 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/components/Header/Header.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 | import PropTypes from 'prop-types';
8 |
9 | function Header({ children }) {
10 | return (
11 |
21 |
13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 |