├── .gitignore
├── Chapter 01
└── 1-started
│ ├── core
│ └── .gitignore
│ ├── data
│ └── .gitignore
│ ├── routes
│ └── .gitignore
│ ├── test
│ └── .gitignore
│ ├── tools
│ ├── .eslintrc
│ ├── clean.js
│ ├── run.js
│ ├── build.js
│ ├── runServer.js
│ ├── serve.js
│ └── start.js
│ ├── .babelrc
│ ├── public
│ ├── robots.txt
│ └── favicon.ico
│ ├── .DS_Store
│ ├── .eslintrc
│ ├── .gitignore
│ ├── .editorconfig
│ ├── client.js
│ ├── server.js
│ ├── components
│ ├── App.js
│ └── Html.js
│ ├── package.json
│ └── README.md
├── Chapter 02
└── 2-react
│ ├── data
│ └── .gitignore
│ ├── routes
│ ├── .gitignore
│ ├── Home
│ │ ├── package.json
│ │ ├── Hero.js
│ │ └── Home.js
│ └── NotFound
│ │ ├── package.json
│ │ └── NotFound.js
│ ├── test
│ └── .gitignore
│ ├── tools
│ ├── .eslintrc
│ ├── clean.js
│ ├── run.js
│ ├── build.js
│ ├── runServer.js
│ ├── serve.js
│ └── start.js
│ ├── components
│ ├── Html
│ │ ├── package.json
│ │ └── Html.js
│ ├── Header
│ │ ├── package.json
│ │ └── Header.js
│ ├── Layout
│ │ ├── package.json
│ │ └── Layout.js
│ └── App.js
│ ├── .babelrc
│ ├── public
│ ├── robots.txt
│ └── favicon.ico
│ ├── .eslintrc
│ ├── .gitignore
│ ├── .editorconfig
│ ├── client.js
│ ├── core
│ └── Router.js
│ ├── server.js
│ ├── package.json
│ └── README.md
├── Chapter 06
└── 6-graphql
│ ├── test
│ └── .gitignore
│ ├── tools
│ ├── .eslintrc
│ ├── clean.js
│ ├── run.js
│ ├── build.js
│ ├── runServer.js
│ ├── serve.js
│ └── start.js
│ ├── data
│ ├── models
│ │ ├── .eslintrc
│ │ ├── Tag.js
│ │ ├── Offer.js
│ │ ├── User.js
│ │ └── index.js
│ ├── sequelize.js
│ ├── queries
│ │ ├── viewer.js
│ │ ├── greeting.js
│ │ └── offer.js
│ ├── schema.js
│ └── types
│ │ ├── UserType.js
│ │ └── OfferType.js
│ ├── components
│ ├── LikeButton
│ │ ├── package.json
│ │ └── LikeButton.js
│ ├── Html
│ │ ├── package.json
│ │ └── Html.js
│ ├── Layout
│ │ ├── package.json
│ │ ├── header.jpg
│ │ ├── Layout.scss
│ │ └── Layout.js
│ ├── CurrentTime
│ │ ├── package.json
│ │ └── CurrentTime.js
│ ├── .DS_Store
│ ├── Header
│ │ ├── header.jpg
│ │ └── Header.js
│ ├── variables.scss
│ ├── Context.js
│ └── App.js
│ ├── routes
│ ├── Home
│ │ ├── package.json
│ │ ├── Hero.js
│ │ └── Home.js
│ ├── Test
│ │ ├── package.json
│ │ └── Test.js
│ ├── NotFound
│ │ ├── package.json
│ │ └── NotFound.js
│ └── .DS_Store
│ ├── .babelrc
│ ├── public
│ ├── robots.txt
│ └── favicon.ico
│ ├── .DS_Store
│ ├── core
│ ├── .DS_Store
│ ├── fetch
│ │ ├── package.json
│ │ ├── fetch.client.js
│ │ └── fetch.server.js
│ └── Router.js
│ ├── .gitignore
│ ├── .editorconfig
│ ├── client.js
│ ├── README.md
│ ├── server.js
│ └── package.json
├── Chapter 04
└── 4-browsersync
│ ├── data
│ └── .gitignore
│ ├── routes
│ ├── .gitignore
│ ├── Home
│ │ ├── package.json
│ │ ├── Hero.js
│ │ └── Home.js
│ └── NotFound
│ │ ├── package.json
│ │ └── NotFound.js
│ ├── test
│ └── .gitignore
│ ├── postcss.config.js
│ ├── tools
│ ├── .eslintrc
│ ├── clean.js
│ ├── run.js
│ ├── build.js
│ ├── runServer.js
│ ├── serve.js
│ └── start.js
│ ├── components
│ ├── Html
│ │ ├── package.json
│ │ └── Html.js
│ ├── Header
│ │ ├── package.json
│ │ ├── header.jpg
│ │ └── Header.js
│ ├── Layout
│ │ ├── package.json
│ │ ├── header.jpg
│ │ ├── Layout.scss
│ │ └── Layout.js
│ ├── variables.scss
│ └── App.js
│ ├── .babelrc
│ ├── public
│ ├── robots.txt
│ └── favicon.ico
│ ├── .gitignore
│ ├── .eslintrc
│ ├── .editorconfig
│ ├── client.js
│ ├── core
│ └── Router.js
│ ├── server.js
│ ├── package.json
│ └── README.md
├── Chapter 05
└── 5-react-server
│ ├── data
│ └── .gitignore
│ ├── routes
│ ├── .gitignore
│ ├── Home
│ │ ├── package.json
│ │ ├── Hero.js
│ │ └── Home.js
│ ├── Test
│ │ ├── package.json
│ │ └── Test.js
│ └── NotFound
│ │ ├── package.json
│ │ └── NotFound.js
│ ├── test
│ └── .gitignore
│ ├── postcss.config.js
│ ├── tools
│ ├── .eslintrc
│ ├── clean.js
│ ├── run.js
│ ├── build.js
│ ├── runServer.js
│ ├── serve.js
│ └── start.js
│ ├── components
│ ├── LikeButton
│ │ ├── package.json
│ │ └── LikeButton.js
│ ├── Html
│ │ ├── package.json
│ │ └── Html.js
│ ├── Header
│ │ ├── package.json
│ │ ├── header.jpg
│ │ └── Header.js
│ ├── Layout
│ │ ├── package.json
│ │ ├── header.jpg
│ │ ├── Layout.scss
│ │ └── Layout.js
│ ├── CurrentTime
│ │ ├── package.json
│ │ └── CurrentTime.js
│ ├── variables.scss
│ ├── Context.js
│ └── App.js
│ ├── .babelrc
│ ├── public
│ ├── robots.txt
│ ├── Thumbs.db
│ └── favicon.ico
│ ├── core
│ ├── fetch
│ │ ├── package.json
│ │ ├── fetch.client.js
│ │ └── fetch.server.js
│ └── Router.js
│ ├── .gitignore
│ ├── .eslintrc
│ ├── api
│ └── test.js
│ ├── .editorconfig
│ ├── client.js
│ ├── server.js
│ ├── package.json
│ └── README.md
├── Chapter 08
├── 8-auth
│ ├── .babelrc
│ ├── .DS_Store
│ ├── src
│ │ ├── .DS_Store
│ │ ├── actions
│ │ │ └── types.js
│ │ ├── reducers
│ │ │ ├── index.js
│ │ │ └── auth_reducer.js
│ │ ├── components
│ │ │ ├── Home.js
│ │ │ ├── RouteWithSubRoutes.js
│ │ │ ├── Repo.js
│ │ │ ├── Root.js
│ │ │ ├── About.js
│ │ │ ├── hoc
│ │ │ │ └── require_auth.js
│ │ │ ├── Repos.js
│ │ │ ├── ReposWithRouter.js
│ │ │ └── App.js
│ │ └── index.js
│ ├── README.md
│ ├── webpack.config.js
│ ├── routesConfig.js
│ ├── package.json
│ └── serverWithInitialData.js
└── __MACOSX
│ └── 8-auth
│ └── ._.DS_Store
├── .gitattributes
├── Chapter 07
└── 7-routing
│ ├── .babelrc
│ ├── modules
│ ├── Home.js
│ ├── RouteWithSubRoutes.js
│ ├── Repo.js
│ ├── About.js
│ ├── Root.js
│ ├── Repos.js
│ ├── ReposWithRouter.js
│ └── App.js
│ ├── README.md
│ ├── index.js
│ ├── webpack.config.js
│ ├── routesConfig.js
│ ├── package.json
│ ├── server.js
│ └── serverWithInitialData.js
├── Chapter 09
└── B05226_09_Code
│ ├── .babelrc
│ ├── .DS_Store
│ ├── src
│ ├── .DS_Store
│ ├── actions
│ │ └── types.js
│ ├── reducers
│ │ ├── index.js
│ │ └── auth_reducer.js
│ ├── components
│ │ ├── Home.js
│ │ ├── RouteWithSubRoutes.js
│ │ ├── Repo.js
│ │ ├── Root.js
│ │ ├── About.js
│ │ ├── hoc
│ │ │ └── require_auth.js
│ │ ├── Repos.js
│ │ ├── ReposWithRouter.js
│ │ └── App.js
│ ├── index.js
│ └── tests
│ │ ├── it
│ │ └── NightwatchTest.js
│ │ ├── tests_helper.js
│ │ ├── EnzymeTest.js
│ │ └── PlainTest.js
│ ├── README.md
│ ├── nightwatch.json
│ ├── webpack.config.js
│ ├── routesConfig.js
│ ├── package.json
│ └── serverWithInitialData.js
├── Software and Hardware List.pdf
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | node_modules
3 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/core/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/data/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/routes/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/test/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/data/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/routes/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/test/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/test/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/data/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/routes/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/test/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/data/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/routes/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/test/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
--------------------------------------------------------------------------------
/Chapter 08/8-auth/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env", "stage-2", "react"]
3 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
--------------------------------------------------------------------------------
/Chapter 07/7-routing/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env", "stage-2", "react"]
3 | }
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env", "stage-2", "react"]
3 | }
--------------------------------------------------------------------------------
/Chapter 01/1-started/tools/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-console": 0
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/tools/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-console": 0
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/tools/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-console": 0
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/tools/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-console": 0
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/tools/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-console": 0
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/data/models/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "new-cap": 0
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/routes/Home/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Home",
4 | "main": "./Home.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/LikeButton/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "LikeButton",
3 | "main": "./LikeButton.js"
4 | }
5 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/routes/Home/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Home",
4 | "main": "./Home.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/routes/Test/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Test",
4 | "main": "./Test.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/components/Html/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Html",
4 | "main": "./Html.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/routes/Home/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Home",
4 | "main": "./Home.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/LikeButton/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "LikeButton",
3 | "main": "./LikeButton.js"
4 | }
5 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/routes/Home/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Home",
4 | "main": "./Home.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/routes/Test/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Test",
4 | "main": "./Test.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/Html/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Html",
4 | "main": "./Html.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env", "stage-2", "react"],
3 | "plugins": [
4 | "transform-runtime"
5 | ]
6 | }
--------------------------------------------------------------------------------
/Chapter 01/1-started/public/robots.txt:
--------------------------------------------------------------------------------
1 | # www.robotstxt.org/
2 |
3 | # Allow crawling of all content
4 | User-agent: *
5 | Disallow:
6 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env", "stage-2", "react"],
3 | "plugins": [
4 | "transform-runtime"
5 | ]
6 | }
--------------------------------------------------------------------------------
/Chapter 02/2-react/components/Header/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Header",
4 | "main": "./Header.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/components/Layout/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Layout",
4 | "main": "./Layout.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/public/robots.txt:
--------------------------------------------------------------------------------
1 | # www.robotstxt.org/
2 |
3 | # Allow crawling of all content
4 | User-agent: *
5 | Disallow:
6 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/routes/NotFound/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "NotFound",
4 | "main": "./NotFound.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/components/Html/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Html",
4 | "main": "./Html.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/Html/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Html",
4 | "main": "./Html.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env", "stage-2", "react"],
3 | "plugins": [
4 | "transform-runtime"
5 | ]
6 | }
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/Layout/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Layout",
4 | "main": "./Layout.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/public/robots.txt:
--------------------------------------------------------------------------------
1 | # www.robotstxt.org/
2 |
3 | # Allow crawling of all content
4 | User-agent: *
5 | Disallow:
6 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env", "stage-2", "react"],
3 | "plugins": [
4 | "transform-runtime"
5 | ]
6 | }
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/components/Header/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Header",
4 | "main": "./Header.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/components/Layout/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Layout",
4 | "main": "./Layout.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/public/robots.txt:
--------------------------------------------------------------------------------
1 | # www.robotstxt.org/
2 |
3 | # Allow crawling of all content
4 | User-agent: *
5 | Disallow:
6 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env", "stage-2", "react"],
3 | "plugins": [
4 | "transform-runtime"
5 | ]
6 | }
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/Header/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Header",
4 | "main": "./Header.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/Layout/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Layout",
4 | "main": "./Layout.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/public/robots.txt:
--------------------------------------------------------------------------------
1 | # www.robotstxt.org/
2 |
3 | # Allow crawling of all content
4 | User-agent: *
5 | Disallow:
6 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/routes/NotFound/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "NotFound",
4 | "main": "./NotFound.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 08/8-auth/.DS_Store
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/routes/NotFound/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "NotFound",
4 | "main": "./NotFound.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/routes/NotFound/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "NotFound",
4 | "main": "./NotFound.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 01/1-started/.DS_Store
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 06/6-graphql/.DS_Store
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/CurrentTime/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "CurrentTime",
4 | "main": "./CurrentTime.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 08/8-auth/src/.DS_Store
--------------------------------------------------------------------------------
/Software and Hardware List.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Software and Hardware List.pdf
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/CurrentTime/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "CurrentTime",
4 | "main": "./CurrentTime.js"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 08/__MACOSX/8-auth/._.DS_Store:
--------------------------------------------------------------------------------
1 | Mac OS X 2 F x @ ATTR x x
--------------------------------------------------------------------------------
/Chapter 02/2-react/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 02/2-react/public/favicon.ico
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/core/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 06/6-graphql/core/.DS_Store
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/routes/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 06/6-graphql/routes/.DS_Store
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 09/B05226_09_Code/.DS_Store
--------------------------------------------------------------------------------
/Chapter 01/1-started/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 01/1-started/public/favicon.ico
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 06/6-graphql/public/favicon.ico
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 09/B05226_09_Code/src/.DS_Store
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/public/Thumbs.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 05/5-react-server/public/Thumbs.db
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 06/6-graphql/components/.DS_Store
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/README.md:
--------------------------------------------------------------------------------
1 | # Instructions
2 |
3 | ## Unit Tests
4 | 1. npm run test
5 |
6 | ## Integration Tests
7 | 1. npm run start:prod:server
8 | 2. npm run it
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 04/4-browsersync/public/favicon.ico
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 05/5-react-server/public/favicon.ico
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/core/fetch/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "fetch",
4 | "main": "./fetch.server.js",
5 | "browser": "./fetch.client.js"
6 | }
7 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/Header/header.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 06/6-graphql/components/Header/header.jpg
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/Layout/header.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 06/6-graphql/components/Layout/header.jpg
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/core/fetch/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "fetch",
4 | "main": "./fetch.server.js",
5 | "browser": "./fetch.client.js"
6 | }
7 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/components/Header/header.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 04/4-browsersync/components/Header/header.jpg
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/components/Layout/header.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 04/4-browsersync/components/Layout/header.jpg
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/Header/header.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 05/5-react-server/components/Header/header.jpg
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/Layout/header.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Isomorphic-JavaScript-Web-Development/HEAD/Chapter 05/5-react-server/components/Layout/header.jpg
--------------------------------------------------------------------------------
/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 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 08/8-auth/src/actions/types.js:
--------------------------------------------------------------------------------
1 | export const AUTH_USER = 'auth_user';
2 | export const UNAUTH_USER = 'unauth_user';
3 | export const AUTH_ERROR = 'auth_error';
4 | export const FETCH_MESSAGE = 'fetch_message';
5 |
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/actions/types.js:
--------------------------------------------------------------------------------
1 | export const AUTH_USER = 'auth_user';
2 | export const UNAUTH_USER = 'unauth_user';
3 | export const AUTH_ERROR = 'auth_error';
4 | export const FETCH_MESSAGE = 'fetch_message';
5 |
--------------------------------------------------------------------------------
/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 08/8-auth/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 | import authReducer from './auth_reducer';
3 |
4 | const rootReducer = combineReducers({
5 | auth: authReducer
6 | });
7 |
8 | export default rootReducer;
--------------------------------------------------------------------------------
/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 04/4-browsersync/.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 05/5-react-server/.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 09/B05226_09_Code/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 | import authReducer from './auth_reducer';
3 |
4 | const rootReducer = combineReducers({
5 | auth: authReducer
6 | });
7 |
8 | export default rootReducer;
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/.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 | database.sqlite
6 | node_modules
7 | ncp-debug.log
8 | npm-debug.log
9 |
--------------------------------------------------------------------------------
/Chapter 07/7-routing/modules/Home.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default class Home extends React.Component{
4 |
5 | constructor(props){
6 | super(props);
7 | }
8 |
9 | render() {
10 | return
Home
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-quotes": 0,
5 | "id-length": [2, {"exceptions": ["x", "s"]}],
6 | "jsx-quotes": [2, "prefer-double"],
7 | "comma-dangle": [2, "never"]
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-quotes": 0,
5 | "id-length": [2, {"exceptions": ["x", "s"]}],
6 | "jsx-quotes": [2, "prefer-double"],
7 | "comma-dangle": [2, "never"]
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/src/components/Home.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default class Home extends React.Component{
4 |
5 | constructor(props){
6 | super(props);
7 | }
8 |
9 | render() {
10 | return Home
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/components/Home.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default class Home extends React.Component{
4 |
5 | constructor(props){
6 | super(props);
7 | }
8 |
9 | render() {
10 | return Home
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/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 02/2-react/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 06/6-graphql/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 04/4-browsersync/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 05/5-react-server/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 07/7-routing/README.md:
--------------------------------------------------------------------------------
1 | # Instructions
2 |
3 | 1. For development: run `npm run start:dev:server` in one terminal, and `npm run start:dev:client` and connect to `http://localhost:8080/`
4 | 1. For development: run `npm run start:prod:server` in one terminal, and `npm run start:prod:client` and connect to `http://localhost:8080/`
5 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/README.md:
--------------------------------------------------------------------------------
1 | # Instructions
2 |
3 | 1. For development: run `npm run start:dev:server` in one terminal, and `npm run start:dev:client` and connect to `http://localhost:8080/`
4 | 1. For development: run `npm run start:prod:server` in one terminal, and `npm run start:prod:client` and connect to `http://localhost:8080/`
5 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/core/fetch/fetch.client.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import 'whatwg-fetch';
7 |
8 | export default self.fetch.bind(self);
9 | export const Headers = self.Headers;
10 | export const Request = self.Request;
11 | export const Response = self.Response;
12 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/core/fetch/fetch.client.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import 'whatwg-fetch';
7 |
8 | export default self.fetch.bind(self);
9 | export const Headers = self.Headers;
10 | export const Request = self.Request;
11 | export const Response = self.Response;
12 |
--------------------------------------------------------------------------------
/Chapter 07/7-routing/modules/RouteWithSubRoutes.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Route} from 'react-router-dom'
3 |
4 | export default (route, initialData) => (
5 | (
6 | // pass the sub-routes down to keep nesting
7 |
8 | )}/>
9 | );
10 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/api/test.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import express from 'express';
7 |
8 | const router = express.Router();
9 |
10 | router.get('/test', (req, res) => {
11 | res.send({ message: 'Hello from REST API' });
12 | });
13 |
14 | export default router;
15 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/src/components/RouteWithSubRoutes.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Route} from 'react-router-dom'
3 |
4 | export default (route, initialData) => (
5 | (
6 | // pass the sub-routes down to keep nesting
7 |
8 | )}/>
9 | );
10 |
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/components/RouteWithSubRoutes.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Route} from 'react-router-dom'
3 |
4 | export default (route, initialData) => (
5 | (
6 | // pass the sub-routes down to keep nesting
7 |
8 | )}/>
9 | );
10 |
--------------------------------------------------------------------------------
/Chapter 07/7-routing/modules/Repo.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default class Repo extends React.Component {
4 |
5 | constructor(props){
6 | super(props);
7 | }
8 |
9 | render() {
10 | const { userName, repoName } = this.props.params;
11 | return (
12 |
13 |
{userName} / {repoName}
14 |
15 | )
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/src/components/Repo.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default class Repo extends React.Component {
4 |
5 | constructor(props){
6 | super(props);
7 | }
8 |
9 | render() {
10 | const { userName, repoName } = this.props.params;
11 | return (
12 |
13 |
{userName} / {repoName}
14 |
15 | )
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Chapter 07/7-routing/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render } from 'react-dom'
3 | import { BrowserRouter } from 'react-router-dom'
4 |
5 | import Root from './modules/Root'
6 |
7 | const initialData = JSON.parse(window.__INITIAL_STATE__);
8 |
9 | render((
10 |
11 |
12 |
13 | ), document.getElementById('app'));
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/components/Repo.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default class Repo extends React.Component {
4 |
5 | constructor(props){
6 | super(props);
7 | }
8 |
9 | render() {
10 | const { userName, repoName } = this.props.params;
11 | return (
12 |
13 |
{userName} / {repoName}
14 |
15 | )
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/data/sequelize.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import Sequelize from 'sequelize';
7 |
8 | const databaseUrl = process.env.DATABASE_URL || 'sqlite:database.sqlite';
9 | const sequelize = new Sequelize(databaseUrl, { define: { freezeTableName: true } });
10 |
11 | export default sequelize;
12 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/data/queries/viewer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import User from '../models/User';
7 | import UserType from '../types/UserType';
8 |
9 | const viewer = {
10 |
11 | type: UserType,
12 |
13 | resolve({ user }) {
14 | return User.load(user && user.id);
15 | }
16 |
17 | };
18 |
19 | export default viewer;
20 |
--------------------------------------------------------------------------------
/Chapter 07/7-routing/modules/About.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default class About extends React.Component {
4 |
5 | constructor(props){
6 | super(props);
7 | console.log(`about props: ${Object.keys(props)}`)
8 | }
9 |
10 | static loadData(){
11 | return Promise.resolve({
12 | data: 'Hello About'
13 | });
14 | }
15 |
16 | render() {
17 | return About
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/core/fetch/fetch.server.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import fetch, { Request, Headers, Response } from 'node-fetch';
7 |
8 | function localFetch(url, options) {
9 | return fetch(url.startsWith('http') ?
10 | url : `http://localhost:3000${url}`, options);
11 | }
12 |
13 | export { localFetch as default, Request, Headers, Response };
14 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/core/fetch/fetch.server.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import fetch, { Request, Headers, Response } from 'node-fetch';
7 |
8 | function localFetch(url, options) {
9 | return fetch(url.startsWith('http') ?
10 | url : 'http://localhost:3000' + url, options);
11 | }
12 |
13 | export { localFetch as default, Request, Headers, Response };
14 |
--------------------------------------------------------------------------------
/Chapter 07/7-routing/modules/Root.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import routes from '../routesConfig'
3 | import RouteWithSubRoutes from './RouteWithSubRoutes'
4 |
5 | export default class Root extends React.Component {
6 |
7 | render() {
8 | return (
9 |
10 | {
11 | routes.map((route, i) => (
12 |
13 | ))
14 | }
15 |
16 | )
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/src/components/Root.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import routes from '../../routesConfig'
3 | import RouteWithSubRoutes from './RouteWithSubRoutes'
4 |
5 | export default class Root extends React.Component {
6 |
7 | render() {
8 | return (
9 |
10 | {
11 | routes.map((route, i) => (
12 |
13 | ))
14 | }
15 |
16 | )
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/data/queries/greeting.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import { GraphQLString as StringType } from 'graphql';
7 |
8 | const greeting = {
9 |
10 | type: StringType,
11 |
12 | args: {
13 | name: {
14 | type: StringType,
15 | },
16 | },
17 |
18 | resolve(_, { name }) {
19 | return `Welcome, ${name || 'Guest'}!`;
20 | },
21 |
22 | };
23 |
24 | export default greeting;
25 |
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/components/Root.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import routes from '../../routesConfig'
3 | import RouteWithSubRoutes from './RouteWithSubRoutes'
4 |
5 | export default class Root extends React.Component {
6 |
7 | render() {
8 | return (
9 |
10 | {
11 | routes.map((route, i) => (
12 |
13 | ))
14 | }
15 |
16 | )
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/routes/NotFound/NotFound.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 |
8 | const path = '/404';
9 | const action = () => ;
10 |
11 | function NotFound() {
12 | return (
13 |
14 |
Page Not Found
15 |
Sorry, but the page you were trying to view does not exist.
16 |
17 | );
18 | }
19 |
20 | export default { path, action };
21 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/routes/NotFound/NotFound.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 |
8 | const path = '/404';
9 | const action = () => ;
10 |
11 | function NotFound() {
12 | return (
13 |
14 |
Page Not Found
15 |
Sorry, but the page you were trying to view does not exist.
16 |
17 | );
18 | }
19 |
20 | export default { path, action };
21 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/routes/NotFound/NotFound.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 |
8 | const path = '/404';
9 | const action = () => ;
10 |
11 | function NotFound() {
12 | return (
13 |
14 |
Page Not Found
15 |
Sorry, but the page you were trying to view does not exist.
16 |
17 | );
18 | }
19 |
20 | export default { path, action };
21 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/routes/NotFound/NotFound.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 |
8 | const path = '/404';
9 | const action = () => ;
10 |
11 | function NotFound() {
12 | return (
13 |
14 |
Page Not Found
15 |
Sorry, but the page you were trying to view does not exist.
16 |
17 | );
18 | }
19 |
20 | export default { path, action };
21 |
--------------------------------------------------------------------------------
/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 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 06/6-graphql/.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 04/4-browsersync/.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 05/5-react-server/.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 06/6-graphql/data/models/Tag.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import DataType from 'sequelize';
7 | import Model from '../sequelize';
8 |
9 | const Tag = Model.define('Tag', {
10 |
11 | id: {
12 | type: DataType.INTEGER,
13 | primaryKey: true,
14 | autoIncrement: true
15 | },
16 |
17 | slug: {
18 | type: DataType.TEXT
19 | },
20 |
21 | name: {
22 | type: DataType.TEXT
23 | }
24 |
25 | });
26 |
27 | export default Tag;
28 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/routes/Home/Hero.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 |
8 | function Hero() {
9 | return (
10 |
11 |
Rent Anything You Want
12 |
From people around you
13 |
19 |
20 | );
21 | }
22 |
23 | export default Hero;
24 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/routes/Home/Hero.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 |
8 | function Hero() {
9 | return (
10 |
11 |
Rent Anything You Want
12 |
From people around you
13 |
19 |
20 | );
21 | }
22 |
23 | export default Hero;
24 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/routes/Home/Hero.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 |
8 | function Hero() {
9 | return (
10 |
11 |
Rent Anything You Want
12 |
From people around you
13 |
19 |
20 | );
21 | }
22 |
23 | export default Hero;
24 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/data/schema.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import {
7 | GraphQLSchema as Schema,
8 | GraphQLObjectType as ObjectType,
9 | } from 'graphql';
10 |
11 | import viewer from './queries/viewer';
12 | import greeting from './queries/greeting';
13 |
14 | const schema = new Schema({
15 | query: new ObjectType({
16 | name: 'Query',
17 | fields: {
18 | viewer,
19 | greeting
20 | }
21 | })
22 | });
23 |
24 | export default schema;
25 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/routes/Home/Hero.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 |
8 | function Hero() {
9 | return (
10 |
11 |
Rent Anything You Want
12 |
From people around you
13 |
20 |
21 | );
22 | }
23 |
24 | export default Hero;
25 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/data/queries/offer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import {
7 | GraphQLID as ID,
8 | GraphQLNonNull as NonNull
9 | } from 'graphql';
10 |
11 | import Offer from '../models/Offer';
12 | import OfferType from '../types/OfferType';
13 |
14 | const viewer = {
15 |
16 | type: OfferType,
17 |
18 | args: {
19 | id: { type: new NonNull(ID) }
20 | },
21 |
22 | resolve(root, { id }) {
23 | return Offer.findById(id);
24 | }
25 |
26 | };
27 |
28 | export default viewer;
29 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {render} from 'react-dom'
3 | import {BrowserRouter} from 'react-router-dom'
4 | import {Provider} from 'react-redux'
5 | import {createStore} from 'redux'
6 | import reducers from './reducers';
7 |
8 | import Root from './components/Root'
9 |
10 | const initialData = JSON.parse(window.__INITIAL_STATE__);
11 |
12 | const store = createStore(reducers, initialData);
13 |
14 | render((
15 |
16 |
17 |
18 |
19 |
20 | ), document.getElementById('app'));
--------------------------------------------------------------------------------
/Chapter 08/8-auth/src/reducers/auth_reducer.js:
--------------------------------------------------------------------------------
1 | import {
2 | AUTH_USER,
3 | UNAUTH_USER,
4 | AUTH_ERROR,
5 | FETCH_MESSAGE
6 | } from '../actions/types';
7 |
8 | export default function(state = {}, action) {
9 | switch(action.type) {
10 | case AUTH_USER:
11 | return { ...state, error: '', authenticated: true };
12 | case UNAUTH_USER:
13 | return { ...state, authenticated: false };
14 | case AUTH_ERROR:
15 | return { ...state, error: action.payload };
16 | case FETCH_MESSAGE:
17 | return { ...state, message: action.payload };
18 | }
19 |
20 | return state;
21 | }
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {render} from 'react-dom'
3 | import {BrowserRouter} from 'react-router-dom'
4 | import {Provider} from 'react-redux'
5 | import {createStore} from 'redux'
6 | import reducers from './reducers';
7 |
8 | import Root from './components/Root'
9 |
10 | const initialData = JSON.parse(window.__INITIAL_STATE__);
11 |
12 | const store = createStore(reducers, initialData);
13 |
14 | render((
15 |
16 |
17 |
18 |
19 |
20 | ), document.getElementById('app'));
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/reducers/auth_reducer.js:
--------------------------------------------------------------------------------
1 | import {
2 | AUTH_USER,
3 | UNAUTH_USER,
4 | AUTH_ERROR,
5 | FETCH_MESSAGE
6 | } from '../actions/types';
7 |
8 | export default function(state = {}, action) {
9 | switch(action.type) {
10 | case AUTH_USER:
11 | return { ...state, error: '', authenticated: true };
12 | case UNAUTH_USER:
13 | return { ...state, authenticated: false };
14 | case AUTH_ERROR:
15 | return { ...state, error: action.payload };
16 | case FETCH_MESSAGE:
17 | return { ...state, message: action.payload };
18 | }
19 |
20 | return state;
21 | }
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/CurrentTime/CurrentTime.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 | import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
8 |
9 | function CurrentTime() {
10 | const elem = canUseDOM && document.querySelector('.time[data-time]');
11 | const time = elem ? +elem.dataset.time : Date.now();
12 | return (
13 |
14 | Current time (timestamp in ms): {time}
15 |
16 | );
17 | }
18 |
19 | export default CurrentTime;
20 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/CurrentTime/CurrentTime.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 | import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
8 |
9 | function CurrentTime() {
10 | const elem = canUseDOM && document.querySelector('.time[data-time]');
11 | const time = elem ? +elem.dataset.time : Date.now();
12 | return (
13 |
14 | Current time (timestamp in ms): {time}
15 |
16 | );
17 | }
18 |
19 | export default CurrentTime;
20 |
--------------------------------------------------------------------------------
/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(, 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 09/B05226_09_Code/nightwatch.json:
--------------------------------------------------------------------------------
1 | {
2 | "src_folders" : ["src/tests/it/"],
3 |
4 | "selenium" : {
5 | "start_process" : true,
6 | "server_path" : "/Users/talabes/Documents/MyProjects/selenium-server-standalone-3.4.0.jar"
7 | },
8 |
9 | "test_runner" : "mocha",
10 |
11 | "test_settings" : {
12 | "default" : {
13 | "launch_url" : "http://localhost",
14 | "selenium_port" : 4444,
15 | "selenium_host" : "localhost",
16 | "silent": true,
17 | "screenshots" : {
18 | "enabled" : false,
19 | "path" : ""
20 | },
21 | "desiredCapabilities": {
22 | "browserName": "chrome"
23 | }
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Chapter 08/8-auth/src/components/About.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default class About extends React.Component {
4 |
5 | constructor(props){
6 | super(props);
7 | this.state = {
8 | msg: 'Hello'
9 | }
10 | }
11 |
12 | static loadData(){
13 | return Promise.resolve({
14 | data: 'Hello About'
15 | });
16 | }
17 |
18 | changeMsg(){
19 | this.setState({
20 | msg: 'World'
21 | })
22 | }
23 |
24 | render() {
25 | return
26 | {this.state.msg}
27 |
28 |
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/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/Layout/Layout.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 | import Header from '../Header';
9 |
10 | function Layout({ hero, children }) {
11 | return (
12 |
13 |
14 |
15 | {children}
16 |
17 |
20 |
21 | );
22 | }
23 |
24 | Layout.propTypes = {
25 | hero: PropTypes.element,
26 | children: PropTypes.element.isRequired
27 | };
28 |
29 | export default Layout;
30 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/core/Router.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | const routes = [
7 | require('../routes/Home').default,
8 | require('../routes/NotFound').default
9 | ];
10 |
11 | const router = {
12 | match(location) {
13 | const route = routes.find(x => x.path === location.path);
14 |
15 | if (route) {
16 | try {
17 | return route.action();
18 | } catch (err) {
19 | return routes.find(x => x.path === '/500').action();
20 | }
21 | } else {
22 | return routes.find(x => x.path === '/404').action();
23 | }
24 | }
25 | };
26 |
27 | export default router;
28 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/data/types/UserType.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import {
7 | GraphQLID as ID,
8 | GraphQLObjectType as ObjectType,
9 | GraphQLString as StringType,
10 | GraphQLNonNull as NonNull
11 | } from 'graphql';
12 |
13 | const UserType = new ObjectType({
14 |
15 | name: 'User',
16 |
17 | fields: {
18 |
19 | id: { type: new NonNull(ID) },
20 |
21 | username: { type: new NonNull(StringType) },
22 |
23 | email: { type: new NonNull(StringType) },
24 |
25 | displayName: { type: new NonNull(StringType) }
26 |
27 | }
28 |
29 | });
30 |
31 | export default UserType;
32 |
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/components/About.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default class About extends React.Component {
4 |
5 | constructor(props){
6 | super(props);
7 | this.state = {
8 | msg: 'Hello'
9 | }
10 | }
11 |
12 | static loadData(){
13 | return Promise.resolve({
14 | data: 'Hello About'
15 | });
16 | }
17 |
18 | changeMsg(){
19 | this.setState({
20 | msg: 'World'
21 | })
22 | }
23 |
24 | render() {
25 | return
26 | {this.state.msg}
27 |
28 |
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/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 04/4-browsersync/core/Router.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | const routes = [
7 | require('../routes/Home').default,
8 | require('../routes/NotFound').default
9 | ];
10 |
11 | const router = {
12 | match(location) {
13 | const route = routes.find(x => x.path === location.path);
14 |
15 | if (route) {
16 | try {
17 | return route.action();
18 | } catch (err) {
19 | return routes.find(x => x.path === '/500').action();
20 | }
21 | } else {
22 | return routes.find(x => x.path === '/404').action();
23 | }
24 | }
25 | };
26 |
27 | export default router;
28 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/data/types/OfferType.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import {
7 | GraphQLID as ID,
8 | GraphQLObjectType as ObjectType,
9 | GraphQLString as StringType,
10 | GraphQLNonNull as NonNull
11 | } from 'graphql';
12 |
13 | import UserType from './UserType';
14 |
15 | const OfferType = new ObjectType({
16 |
17 | name: 'Offer',
18 |
19 | fields: {
20 |
21 | id: { type: new NonNull(ID) },
22 |
23 | title: { type: new NonNull(StringType) },
24 |
25 | author: { type: new NonNull(UserType) },
26 |
27 | description: { type: new NonNull(StringType) }
28 |
29 | }
30 |
31 | });
32 |
33 | export default OfferType;
34 |
--------------------------------------------------------------------------------
/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 |
25 | );
26 | }
27 |
28 | Header.propTypes = {
29 | children: PropTypes.element
30 | };
31 |
32 | export default Header;
33 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/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 |
25 | );
26 | }
27 |
28 | Header.propTypes = {
29 | children: PropTypes.element
30 | };
31 |
32 | export default Header;
33 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/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 |
25 | );
26 | }
27 |
28 | Header.propTypes = {
29 | children: PropTypes.element
30 | };
31 |
32 | export default Header;
33 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/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 |
25 | );
26 | }
27 |
28 | Header.propTypes = {
29 | children: PropTypes.element
30 | };
31 |
32 | export default Header;
33 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/data/models/Offer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import DataType from 'sequelize';
7 | import Model from '../sequelize';
8 |
9 | const Offer = Model.define('Offer', {
10 |
11 | id: {
12 | type: DataType.INTEGER,
13 | primaryKey: true,
14 | autoIncrement: true
15 | },
16 |
17 | slug: {
18 | type: DataType.TEXT
19 | },
20 |
21 | name: {
22 | type: DataType.TEXT
23 | },
24 |
25 | priceHourly: {
26 | type: DataType.REAL
27 | },
28 |
29 | priceDaily: {
30 | type: DataType.REAL
31 | },
32 |
33 | priceWeekly: {
34 | type: DataType.REAL
35 | }
36 |
37 | });
38 |
39 | export default Offer;
40 |
--------------------------------------------------------------------------------
/Chapter 07/7-routing/webpack.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const path = require('path');
3 |
4 | module.exports = {
5 | entry: './index.js',
6 |
7 | output: {
8 | path: path.resolve('public'),
9 | filename: 'bundle.js',
10 | publicPath: '/'
11 | },
12 |
13 | plugins: process.env.NODE_ENV === 'production' ? [
14 | new webpack.optimize.DedupePlugin(),
15 | new webpack.optimize.OccurrenceOrderPlugin(),
16 | new webpack.optimize.UglifyJsPlugin()
17 | ] : [],
18 |
19 | module: {
20 | rules: [
21 | {
22 | test: /\.jsx?$/,
23 | exclude: /(node_modules)/,
24 | use: {
25 | loader: 'babel-loader'
26 | }
27 | }
28 | ]
29 | },
30 |
31 | devtool: 'source-map'
32 | };
33 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/webpack.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const path = require('path');
3 |
4 | module.exports = {
5 | entry: './src/index.js',
6 |
7 | output: {
8 | path: path.resolve('public'),
9 | filename: 'bundle.js',
10 | publicPath: '/'
11 | },
12 |
13 | plugins: process.env.NODE_ENV === 'production' ? [
14 | new webpack.optimize.DedupePlugin(),
15 | new webpack.optimize.OccurrenceOrderPlugin(),
16 | new webpack.optimize.UglifyJsPlugin()
17 | ] : [],
18 |
19 | module: {
20 | rules: [
21 | {
22 | test: /\.jsx?$/,
23 | exclude: /(node_modules)/,
24 | use: {
25 | loader: 'babel-loader'
26 | }
27 | }
28 | ]
29 | },
30 |
31 | devtool: 'source-map'
32 | };
33 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/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 ReactDOM from 'react-dom';
8 | import Router from './core/Router';
9 |
10 | function run() {
11 | const location = { path: window.location.pathname };
12 | const [component, page] = Router.match(location, window.AppState);
13 | ReactDOM.hydrate(component, document.getElementById('app'), () => {
14 | document.title = page.title;
15 | });
16 | }
17 |
18 | const loadedStates = ['complete', 'loaded', 'interactive'];
19 |
20 | if (loadedStates.includes(document.readyState) && document.body) {
21 | run();
22 | } else {
23 | window.addEventListener('DOMContentLoaded', run, false);
24 | }
25 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/src/components/hoc/require_auth.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { connect } from 'react-redux';
3 | import {Redirect} from 'react-router-dom'
4 | import PropTypes from 'prop-types';
5 |
6 | export default function(ComposedComponent) {
7 | class Authentication extends Component {
8 | static contextTypes = {
9 | router: PropTypes.object
10 | };
11 |
12 | render() {
13 | if (!this.props.authenticated) {
14 | return
15 | } else{
16 | return
17 | }
18 | }
19 | }
20 |
21 | function mapStateToProps(state) {
22 | return { authenticated: state.auth.authenticated };
23 | }
24 |
25 | return connect(mapStateToProps)(Authentication);
26 | }
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/components/hoc/require_auth.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { connect } from 'react-redux';
3 | import {Redirect} from 'react-router-dom'
4 | import PropTypes from 'prop-types';
5 |
6 | export default function(ComposedComponent) {
7 | class Authentication extends Component {
8 | static contextTypes = {
9 | router: PropTypes.object
10 | };
11 |
12 | render() {
13 | if (!this.props.authenticated) {
14 | return
15 | } else{
16 | return
17 | }
18 | }
19 | }
20 |
21 | function mapStateToProps(state) {
22 | return { authenticated: state.auth.authenticated };
23 | }
24 |
25 | return connect(mapStateToProps)(Authentication);
26 | }
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/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 location = { path: window.location.pathname };
13 | const [component, page] = Router.match(location, window.AppState);
14 | ReactDOM.hydrate(component, document.getElementById('app'), () => {
15 | document.title = page.title;
16 | });
17 | }
18 |
19 | const loadedStates = ['complete', 'loaded', 'interactive'];
20 |
21 | if (loadedStates.includes(document.readyState) && document.body) {
22 | run();
23 | } else {
24 | window.addEventListener('DOMContentLoaded', run, false);
25 | }
26 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/variables.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | /* //// Colors ////////////////////////////////////////////////////////////// */
7 |
8 | $color-primary: #0275d8;
9 | $color-success: #5cb85c;
10 | $color-info: #5bc0de;
11 | $color-warning: #f0ad4e;
12 | $color-danger: #d9534f;
13 |
14 | /* //// Shadows ///////////////////////////////////////////////////////////// */
15 |
16 | $shadow-2dp: 0 2px 2px 0 rgba(0, 0, 0, .14),
17 | 0 3px 1px -2px rgba(0, 0, 0, .2),
18 | 0 1px 5px 0 rgba(0, 0, 0, .12);
19 |
20 | /* //// Animations ////////////////////////////////////////////////////////// */
21 |
22 | $animation-duration-default: .2s;
23 | $animation-curve-default: cubic-bezier(.4, 0, .2, 1);
24 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/components/variables.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | /* //// Colors ////////////////////////////////////////////////////////////// */
7 |
8 | $color-primary: #0275d8;
9 | $color-success: #5cb85c;
10 | $color-info: #5bc0de;
11 | $color-warning: #f0ad4e;
12 | $color-danger: #d9534f;
13 |
14 | /* //// Shadows ///////////////////////////////////////////////////////////// */
15 |
16 | $shadow-2dp: 0 2px 2px 0 rgba(0, 0, 0, .14),
17 | 0 3px 1px -2px rgba(0, 0, 0, .2),
18 | 0 1px 5px 0 rgba(0, 0, 0, .12);
19 |
20 | /* //// Animations ////////////////////////////////////////////////////////// */
21 |
22 | $animation-duration-default: .2s;
23 | $animation-curve-default: cubic-bezier(.4, 0, .2, 1);
24 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/variables.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | /* //// Colors ////////////////////////////////////////////////////////////// */
7 |
8 | $color-primary: #0275d8;
9 | $color-success: #5cb85c;
10 | $color-info: #5bc0de;
11 | $color-warning: #f0ad4e;
12 | $color-danger: #d9534f;
13 |
14 | /* //// Shadows ///////////////////////////////////////////////////////////// */
15 |
16 | $shadow-2dp: 0 2px 2px 0 rgba(0, 0, 0, .14),
17 | 0 3px 1px -2px rgba(0, 0, 0, .2),
18 | 0 1px 5px 0 rgba(0, 0, 0, .12);
19 |
20 | /* //// Animations ////////////////////////////////////////////////////////// */
21 |
22 | $animation-duration-default: .2s;
23 | $animation-curve-default: cubic-bezier(.4, 0, .2, 1);
24 |
--------------------------------------------------------------------------------
/Chapter 07/7-routing/routesConfig.js:
--------------------------------------------------------------------------------
1 | import ReposWithRouter from './modules/ReposWithRouter'
2 | import About from './modules/About'
3 | import Repo from './modules/Repo'
4 | import App from './modules/App'
5 |
6 | const routeConfig = [
7 | {
8 | path: '/',
9 | component: App,
10 | loadData: App.loadData,
11 | routes: [
12 | {
13 | path: '/repos',
14 | component: ReposWithRouter,
15 | loadData: About.loadData,
16 | routes: [
17 | {
18 | path: '/repos/:userName/:repoName',
19 | component: Repo,
20 | loadData: About.loadData
21 | }
22 | ]
23 | },
24 | {
25 | path: '/about',
26 | component: About,
27 | loadData: About.loadData
28 | }
29 | ]
30 | }
31 | ];
32 |
33 | export default routeConfig;
34 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/Context.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 PropTypes from 'prop-types';
8 |
9 | class Context extends Component {
10 |
11 | static childContextTypes = {
12 | page: PropTypes.shape({
13 | title: PropTypes.string,
14 | description: PropTypes.string,
15 | status: PropTypes.number
16 | }),
17 | user: PropTypes.shape({
18 | name: PropTypes.string.isRequired
19 | })
20 | };
21 |
22 | getChildContext() {
23 | return {
24 | page: this.props.page,
25 | user: this.props.user
26 | };
27 | }
28 |
29 | render() {
30 | return React.Children.only(this.props.children);
31 | }
32 |
33 | }
34 |
35 | export default Context;
36 |
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/webpack.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const path = require('path');
3 |
4 | module.exports = {
5 | entry: './src/index.js',
6 |
7 | output: {
8 | path: path.resolve('public'),
9 | filename: 'bundle.js',
10 | publicPath: '/'
11 | },
12 |
13 | plugins: process.env.NODE_ENV === 'production' ? [
14 | new webpack.optimize.DedupePlugin(),
15 | new webpack.optimize.OccurrenceOrderPlugin(),
16 | new webpack.optimize.UglifyJsPlugin()
17 | ] : [],
18 |
19 | module: {
20 | rules: [
21 | {
22 | test: /\.jsx?$/,
23 | exclude: /(node_modules|bower_components)/,
24 | use: {
25 | loader: 'babel-loader',
26 | options: {
27 | presets: ["env", "stage-2", "react"]
28 | }
29 | }
30 | }
31 | ]
32 | },
33 |
34 | devtool: 'source-map'
35 | };
36 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/routesConfig.js:
--------------------------------------------------------------------------------
1 | import ReposWithRouter from './src/components/ReposWithRouter'
2 | import About from './src/components/About'
3 | import Repo from './src/components/Repo'
4 | import App from './src/components/App'
5 | import RequireAuth from './src/components/hoc/require_auth';
6 |
7 | const routeConfig = [
8 | {
9 | path: '/',
10 | component: App,
11 | loadData: App.loadData,
12 | routes: [
13 | {
14 | path: '/repos',
15 | component: ReposWithRouter,
16 | loadData: About.loadData,
17 | routes: [
18 | {
19 | path: '/repos/:userName/:repoName',
20 | component: Repo,
21 | loadData: About.loadData
22 | }
23 | ]
24 | },
25 | {
26 | path: '/about',
27 | component: RequireAuth(About),
28 | loadData: About.loadData
29 | }
30 | ]
31 | }
32 | ];
33 |
34 | export default routeConfig;
35 |
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/routesConfig.js:
--------------------------------------------------------------------------------
1 | import ReposWithRouter from './src/components/ReposWithRouter'
2 | import About from './src/components/About'
3 | import Repo from './src/components/Repo'
4 | import App from './src/components/App'
5 | import RequireAuth from './src/components/hoc/require_auth';
6 |
7 | const routeConfig = [
8 | {
9 | path: '/',
10 | component: App,
11 | loadData: App.loadData,
12 | routes: [
13 | {
14 | path: '/repos',
15 | component: ReposWithRouter,
16 | loadData: About.loadData,
17 | routes: [
18 | {
19 | path: '/repos/:userName/:repoName',
20 | component: Repo,
21 | loadData: About.loadData
22 | }
23 | ]
24 | },
25 | {
26 | path: '/about',
27 | component: RequireAuth(About),
28 | loadData: About.loadData
29 | }
30 | ]
31 | }
32 | ];
33 |
34 | export default routeConfig;
35 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/Context.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 PropTypes from 'prop-types';
8 |
9 | class Context extends Component {
10 | static propTypes = {
11 | page: PropTypes.any,
12 | user: PropTypes.any,
13 | children: PropTypes.element
14 | };
15 |
16 | static childContextTypes = {
17 | page: PropTypes.shape({
18 | title: PropTypes.string,
19 | description: PropTypes.string,
20 | status: PropTypes.number
21 | }),
22 | user: PropTypes.shape({
23 | name: PropTypes.string.isRequired
24 | })
25 | };
26 |
27 | getChildContext() {
28 | return {
29 | page: this.props.page,
30 | user: this.props.user
31 | };
32 | }
33 |
34 | render() {
35 | return React.Children.only(this.props.children);
36 | }
37 | }
38 |
39 | export default Context;
40 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/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 | constructor(props) {
11 | super(props);
12 | this.state = { time: null };
13 | }
14 |
15 | componentDidMount() {
16 | this.tick();
17 | this.interval = setInterval(this.tick.bind(this), 200);
18 | }
19 |
20 | componentWillUnmount() {
21 | clearInterval(this.interval);
22 | }
23 |
24 | tick() {
25 | this.setState({ time: new Date() });
26 | }
27 |
28 | render() {
29 | const time = this.state.time;
30 | const timeString = time && moment(time).format('h:mm:ss a');
31 | return (
32 |
33 |
Sample Application
34 |
Current date and time is {timeString}
35 |
36 | );
37 | }
38 | }
39 |
40 | export default App;
41 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/Layout/Layout.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | @import '../variables.scss';
7 |
8 | .root {
9 | position: relative;
10 | display: flex;
11 | width: 100%;
12 | height: 100%;
13 | overflow-x: hidden;
14 | overflow-y: auto;
15 | -webkit-overflow-scrolling: touch;
16 | flex-direction: column;
17 | }
18 |
19 | .header {
20 | z-index: 3;
21 | display: flex;
22 | width: 100%;
23 | min-height: 64px;
24 | max-height: 1000px;
25 | box-sizing: border-box;
26 | padding: 0;
27 | margin: 0;
28 | color: white;
29 | flex-direction: column;
30 | background: url(./header.jpg) center / cover;
31 | border: none;
32 | box-shadow: $shadow-2dp;
33 | transition-timing-function: $animation-curve-default;
34 | transition-duration: $animation-duration-default;
35 |
36 | flex-wrap: nowrap;
37 | justify-content: flex-start;
38 | flex-shrink: 0;
39 | }
40 |
--------------------------------------------------------------------------------
/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 |
34 |
Sample Application
35 |
Current date and time is {timeString}
36 |
37 | );
38 | }
39 |
40 | }
41 |
42 | export default App;
43 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/components/Layout/Layout.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | @import '../variables.scss';
7 |
8 | .root {
9 | position: relative;
10 | display: flex;
11 | width: 100%;
12 | height: 100%;
13 | overflow-x: hidden;
14 | overflow-y: auto;
15 | -webkit-overflow-scrolling: touch;
16 | flex-direction: column;
17 | }
18 |
19 | .header {
20 | z-index: 3;
21 | display: flex;
22 | width: 100%;
23 | min-height: 64px;
24 | max-height: 1000px;
25 | box-sizing: border-box;
26 | padding: 0;
27 | margin: 0;
28 | color: white;
29 | flex-direction: column;
30 | background: url(./header.jpg) center / cover;
31 | border: none;
32 | box-shadow: $shadow-2dp;
33 | transition-timing-function: $animation-curve-default;
34 | transition-duration: $animation-duration-default;
35 |
36 | flex-wrap: nowrap;
37 | justify-content: flex-start;
38 | flex-shrink: 0;
39 | }
40 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/Layout/Layout.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | @import '../variables.scss';
7 |
8 | .root {
9 | position: relative;
10 | display: flex;
11 | width: 100%;
12 | height: 100%;
13 | overflow-x: hidden;
14 | overflow-y: auto;
15 | -webkit-overflow-scrolling: touch;
16 | flex-direction: column;
17 | }
18 |
19 | .header {
20 | z-index: 3;
21 | display: flex;
22 | width: 100%;
23 | min-height: 64px;
24 | max-height: 1000px;
25 | box-sizing: border-box;
26 | padding: 0;
27 | margin: 0;
28 | color: white;
29 | flex-direction: column;
30 | background: url(./header.jpg) center / cover;
31 | border: none;
32 | box-shadow: $shadow-2dp;
33 | transition-timing-function: $animation-curve-default;
34 | transition-duration: $animation-duration-default;
35 |
36 | flex-wrap: nowrap;
37 | justify-content: flex-start;
38 | flex-shrink: 0;
39 | }
40 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/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 |
34 |
Sample Application
35 |
Current date and time is {timeString}
36 |
37 | );
38 | }
39 |
40 | }
41 |
42 | export default App;
43 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/server.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 path from 'path';
9 | import express from 'express';
10 | import React from 'react';
11 | import ReactDOM from 'react-dom/server';
12 | import Html from './components/Html';
13 | import App from './components/App';
14 |
15 | const server = express();
16 | const port = process.env.PORT || 3000;
17 |
18 | server.use(express.static(path.join(__dirname, 'public')));
19 |
20 | server.get('*', (req, res) => {
21 | const body = ReactDOM.renderToString();
22 | const html = ReactDOM.renderToStaticMarkup();
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 02/2-react/routes/Home/Home.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 Layout from '../../components/Layout';
8 | import Hero from './Hero';
9 |
10 | const path = '/';
11 | const action = () => }>;
12 |
13 | class Home extends Component {
14 | handleClick(event) {
15 | event.preventDefault();
16 | window.location = event.currentTarget.pathname;
17 | }
18 | render() {
19 | return (
20 |
21 |
Popular things to rent
22 |
31 |
32 | );
33 | }
34 | }
35 |
36 | export default { path, action };
37 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/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 |
34 |
Sample Application
35 |
Current date and time is {timeString}
36 |
37 | );
38 | }
39 |
40 | }
41 |
42 | export default App;
43 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/components/Html/Html.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 Html({ title, description, body }) {
10 | return (
11 |
12 |
13 |
14 |
15 | {title}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
27 | Html.propTypes = {
28 | title: PropTypes.string.isRequired,
29 | description: PropTypes.string.isRequired,
30 | body: PropTypes.string.isRequired
31 | };
32 |
33 | export default Html;
34 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/components/Html/Html.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 Html({ title, description, body }) {
10 | return (
11 |
12 |
13 |
14 |
15 | {title}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
27 | Html.propTypes = {
28 | title: PropTypes.string.isRequired,
29 | description: PropTypes.string.isRequired,
30 | body: PropTypes.string.isRequired
31 | };
32 |
33 | export default Html;
34 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/routes/Home/Home.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 Layout from '../../components/Layout';
8 | import Hero from './Hero';
9 |
10 | const path = '/';
11 | const action = () => }>;
12 |
13 | class Home extends Component {
14 | handleClick(event) {
15 | event.preventDefault();
16 | window.location = event.currentTarget.pathname;
17 | }
18 | render() {
19 | return (
20 |
21 |
Popular things to rent
22 |
31 |
32 | );
33 | }
34 | }
35 |
36 | export default { path, action };
37 |
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/routes/Home/Home.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 Layout from '../../components/Layout';
8 | import Hero from './Hero';
9 |
10 | const path = '/';
11 | const action = () => }>;
12 |
13 | class Home extends Component {
14 | handleClick(event) {
15 | event.preventDefault();
16 | window.location = event.currentTarget.pathname;
17 | }
18 | render() {
19 | return (
20 |
21 |
Popular things to rent
22 |
31 |
32 | );
33 | }
34 | }
35 |
36 | export default { path, action };
37 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/routes/Home/Home.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 Layout from '../../components/Layout';
8 | import Hero from './Hero';
9 |
10 | const path = '/';
11 | const action = () => }>;
12 |
13 | class Home extends Component {
14 | handleClick(event) {
15 | event.preventDefault();
16 | window.location = event.currentTarget.pathname;
17 | }
18 | render() {
19 | return (
20 |
21 |
Popular things to rent
22 |
31 |
32 | );
33 | }
34 | }
35 |
36 | export default { path, action };
37 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/LikeButton/LikeButton.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 PropTypes from 'prop-types';
8 |
9 | class LikeButton extends Component {
10 | static propTypes = {
11 | likes: PropTypes.number.isRequired,
12 | liked: PropTypes.bool.isRequired
13 | };
14 |
15 | state = { liked: this.props.liked };
16 |
17 | handleClick = (event) => {
18 | event.preventDefault();
19 | this.setState({ liked: !this.state.liked });
20 | };
21 |
22 | render() {
23 | const { likes, ...other } = this.props;
24 | const color = this.state.liked ? 'inherit' : 'grey';
25 | const count = likes + (this.state.liked ? 1 : 0);
26 |
27 | return (
28 |
31 | );
32 | }
33 | }
34 |
35 | export default LikeButton;
36 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/components/App.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2015 Konstantin Tarkus, Packt Publishing
4 | * All rights reserved.
5 | */
6 |
7 | import React, { Component } from 'react';
8 | import moment from 'moment';
9 |
10 | class App extends Component {
11 |
12 | constructor(props) {
13 | super(props);
14 | this.state = { time: null };
15 | }
16 |
17 | componentDidMount() {
18 | this.tick();
19 | this.interval = setInterval(this.tick.bind(this), 200);
20 | }
21 |
22 | componentWillUnmount() {
23 | clearInterval(this.interval);
24 | }
25 |
26 | tick() {
27 | this.setState({ time: new Date() });
28 | }
29 |
30 | render() {
31 | const time = this.state.time;
32 | const timeString = time && moment(time).format('h:mm:ss a');
33 | return (
34 |
35 |
Sample Application
36 |
Current date and time is {timeString}
37 |
38 | );
39 | }
40 |
41 | }
42 |
43 | export default App;
44 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/server.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import 'babel-core/register';
7 | import path from 'path';
8 | import express from 'express';
9 | import React from 'react';
10 | import ReactDOM from 'react-dom/server';
11 | import Router from './core/Router';
12 | import Html from './components/Html/Html';
13 |
14 | const server = express();
15 | const port = process.env.PORT || 3000;
16 |
17 | server.use(express.static(path.join(__dirname, 'public')));
18 |
19 | server.get('*', (req, res) => {
20 | const component = Router.match(req);
21 | const body = ReactDOM.renderToString(component);
22 | const html = ReactDOM.renderToStaticMarkup();
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 04/4-browsersync/server.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import 'babel-core/register';
7 | import path from 'path';
8 | import express from 'express';
9 | import React from 'react';
10 | import ReactDOM from 'react-dom/server';
11 | import Router from './core/Router';
12 | import Html from './components/Html/Html';
13 |
14 | const server = express();
15 | const port = process.env.PORT || 3000;
16 |
17 | server.use(express.static(path.join(__dirname, 'public')));
18 |
19 | server.get('*', (req, res) => {
20 | const component = Router.match(req);
21 | const body = ReactDOM.renderToString(component);
22 | const html = ReactDOM.renderToStaticMarkup();
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/components/Html.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2015 Konstantin Tarkus, Packt Publishing
4 | * All rights reserved.
5 | */
6 |
7 | import React from 'react';
8 | import PropTypes from 'prop-types';
9 |
10 | function Html({ title, description, body }) {
11 | return (
12 |
13 |
14 |
15 |
16 | {title}
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | );
26 | }
27 |
28 | Html.propTypes = {
29 | title: PropTypes.string.isRequired,
30 | description: PropTypes.string.isRequired,
31 | body: PropTypes.string.isRequired
32 | };
33 |
34 | export default Html;
35 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/LikeButton/LikeButton.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 PropTypes from 'prop-types';
8 |
9 | class LikeButton extends Component {
10 |
11 | static propTypes = {
12 | likes: PropTypes.number.isRequired,
13 | liked: PropTypes.bool.isRequired
14 | };
15 |
16 | state = { liked: this.props.liked };
17 |
18 | handleClick = (event) => {
19 | event.preventDefault();
20 | this.setState({ liked: !this.state.liked });
21 | };
22 |
23 | render() {
24 | const { likes, liked, ...other } = this.props;
25 | const color = this.state.liked ? 'inherit' : 'grey';
26 | const count = likes + (this.state.liked ? 1 : 0);
27 |
28 | return (
29 |
32 | );
33 | }
34 |
35 | }
36 |
37 | export default LikeButton;
38 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/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 06/6-graphql/components/Layout/Layout.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 | import s from './Layout.scss';
10 |
11 | function Layout({ hero, children }) {
12 | return (
13 |
14 |
28 |
29 | {children}
30 |
31 |
34 |
35 | );
36 | }
37 |
38 | Layout.propTypes = {
39 | hero: PropTypes.element,
40 | children: PropTypes.element.isRequired
41 | };
42 |
43 | export default Layout;
44 |
--------------------------------------------------------------------------------
/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 04/4-browsersync/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 06/6-graphql/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 05/5-react-server/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 04/4-browsersync/components/Layout/Layout.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 | import s from './Layout.scss';
9 | import Header from '../Header';
10 |
11 | function Layout({ hero, children }) {
12 | return (
13 |
14 |
28 |
29 | {children}
30 |
31 |
34 |
35 | );
36 | }
37 |
38 | Layout.propTypes = {
39 | hero: PropTypes.element,
40 | children: PropTypes.element.isRequired
41 | };
42 |
43 | export default Layout;
44 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/Layout/Layout.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 | import s from './Layout.scss';
9 | import Header from '../Header';
10 |
11 | function Layout({ hero, children }) {
12 | return (
13 |
14 |
28 |
29 | {children}
30 |
31 |
34 |
35 | );
36 | }
37 |
38 | Layout.propTypes = {
39 | hero: PropTypes.element,
40 | children: PropTypes.element.isRequired
41 | };
42 |
43 | export default Layout;
44 |
--------------------------------------------------------------------------------
/Chapter 07/7-routing/modules/Repos.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 |
4 | export default React.createClass({
5 | contextTypes: {
6 | router: React.PropTypes.object
7 | },
8 |
9 | handleSubmit(event) {
10 | event.preventDefault();
11 | const userName = event.target.elements[0].value;
12 | const repo = event.target.elements[1].value;
13 | const path = `/repos/${userName}/${repo}`;
14 | this.context.router.history.push(path);
15 | },
16 |
17 | render() {
18 | return (
19 |
20 |
Repos
21 |
22 | - React Router
23 | - React
24 | -
25 |
30 |
31 |
32 |
33 | )
34 | }
35 | })
36 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/src/components/Repos.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 |
4 | export default React.createClass({
5 | contextTypes: {
6 | router: React.PropTypes.object
7 | },
8 |
9 | handleSubmit(event) {
10 | event.preventDefault();
11 | const userName = event.target.elements[0].value;
12 | const repo = event.target.elements[1].value;
13 | const path = `/repos/${userName}/${repo}`;
14 | this.context.router.history.push(path);
15 | },
16 |
17 | render() {
18 | return (
19 |
20 |
Repos
21 |
22 | - React Router
23 | - React
24 | -
25 |
30 |
31 |
32 |
33 | )
34 | }
35 | })
36 |
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/components/Repos.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 |
4 | export default React.createClass({
5 | contextTypes: {
6 | router: React.PropTypes.object
7 | },
8 |
9 | handleSubmit(event) {
10 | event.preventDefault();
11 | const userName = event.target.elements[0].value;
12 | const repo = event.target.elements[1].value;
13 | const path = `/repos/${userName}/${repo}`;
14 | this.context.router.history.push(path);
15 | },
16 |
17 | render() {
18 | return (
19 |
20 |
Repos
21 |
22 | - React Router
23 | - React
24 | -
25 |
30 |
31 |
32 |
33 | )
34 | }
35 | })
36 |
--------------------------------------------------------------------------------
/Chapter 08/8-auth/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "auth-chapter",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "start:dev:client": "webpack-dev-server --inline --content-base public/ --history-api-fallback",
6 | "start:dev:server": "webpack && babel-node serverWithInitialData.js",
7 | "start:prod:client": "webpack -p",
8 | "start:prod:server": "webpack && babel-node serverWithInitialData.js"
9 | },
10 | "dependencies": {
11 | "express": "4.15.4",
12 | "jquery": "3.2.1",
13 | "react": "16.0.0",
14 | "react-dom": "16.0.0",
15 | "react-redux": "5.0.6",
16 | "react-router": "4.2.0",
17 | "react-router-config": "1.0.0-beta.4",
18 | "react-router-dom": "4.2.2",
19 | "redux": "3.7.2"
20 | },
21 | "devDependencies": {
22 | "babel-cli": "6.26.0",
23 | "babel-core": "6.26.0",
24 | "babel-loader": "7.1.2",
25 | "babel-preset-env": "1.6.0",
26 | "babel-preset-react": "6.24.1",
27 | "babel-preset-stage-2": "6.24.1",
28 | "http-server": "0.10.0",
29 | "source-map-support": "0.4.18",
30 | "webpack": "3.5.6",
31 | "webpack-dev-server": "2.7.1"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Packt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Chapter 07/7-routing/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "routing-chapter",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "start:dev:client": "webpack-dev-server --inline --content-base public/ --history-api-fallback",
6 | "start:dev:server": "webpack && babel-node serverWithInitialData.js",
7 | "start:prod:client": "webpack -p",
8 | "start:prod:server": "webpack && babel-node serverWithInitialData.js"
9 | },
10 | "dependencies": {
11 | "express": "4.15.4",
12 | "jquery": "3.2.1",
13 | "react": "16.0.0",
14 | "react-dom": "16.0.0",
15 | "react-redux": "5.0.6",
16 | "react-router": "4.2.0",
17 | "react-router-config": "1.0.0-beta.4",
18 | "react-router-dom": "4.2.2",
19 | "redux": "3.7.2"
20 | },
21 | "devDependencies": {
22 | "babel-cli": "6.26.0",
23 | "babel-core": "6.26.0",
24 | "babel-loader": "7.1.2",
25 | "babel-preset-env": "1.6.0",
26 | "babel-preset-react": "6.24.1",
27 | "babel-preset-stage-2": "6.24.1",
28 | "http-server": "0.10.0",
29 | "source-map-support": "0.4.18",
30 | "webpack": "3.5.6",
31 | "webpack-dev-server": "2.7.1"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Chapter 01/1-started/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "dependencies": {
4 | "bluebird": "3.5.0",
5 | "express": "4.15.4",
6 | "moment": "2.18.1",
7 | "react": "16.0.0",
8 | "react-dom": "16.0.0"
9 | },
10 | "devDependencies": {
11 | "autoprefixer": "7.1.4",
12 | "babel-cli": "6.26.0",
13 | "babel-core": "6.26.0",
14 | "babel-eslint": "8.0.0",
15 | "babel-loader": "7.1.2",
16 | "babel-plugin-transform-runtime": "6.23.0",
17 | "babel-preset-env": "1.6.0",
18 | "babel-preset-react": "6.24.1",
19 | "babel-preset-stage-0": "6.24.1",
20 | "del": "3.0.0",
21 | "eslint": "4.7.0",
22 | "eslint-config-airbnb": "15.1.0",
23 | "eslint-plugin-react": "7.3.0",
24 | "extend": "3.0.1",
25 | "gaze": "1.1.2",
26 | "ncp": "2.0.0",
27 | "node-style-loader": "0.0.1-alpha",
28 | "postcss-loader": "2.0.6",
29 | "precss": "2.0.0",
30 | "webpack-dev-middleware": "2.0.4",
31 | "webpack": "3.6.0"
32 | },
33 | "scripts": {
34 | "lint": "eslint components core data routes test tools",
35 | "build": "babel-node tools/run build",
36 | "serve": "node build/server.js"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/components/Html/Html.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 Html({ title, description, body, state }) {
10 | return (
11 |
12 |
13 |
14 |
15 | {title}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | );
26 | }
27 |
28 | Html.propTypes = {
29 | title: PropTypes.string.isRequired,
30 | description: PropTypes.string.isRequired,
31 | body: PropTypes.string.isRequired,
32 | state: PropTypes.object.isRequired
33 | };
34 |
35 | export default Html;
36 |
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/core/Router.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 | import Context from '../components/Context';
8 |
9 | const routes = [
10 | require('../routes/Home').default,
11 | require('../routes/Test').default,
12 | require('../routes/NotFound').default
13 | ];
14 |
15 | const router = {
16 | match(location, state) {
17 | let component;
18 | const page = {
19 | title: 'My Application',
20 | description: 'Isomorphic web application sample',
21 | status: 200
22 | };
23 | const route = routes.find(x => x.path === location.path);
24 |
25 | if (route) {
26 | try {
27 | component = route.action();
28 | } catch (err) {
29 | component = routes.find(x => x.path === '/500').action();
30 | page.status = 500;
31 | }
32 | } else {
33 | component = routes.find(x => x.path === '/404').action();
34 | page.status = 404;
35 | }
36 |
37 | return [{component}, page];
38 | }
39 | };
40 |
41 | export default router;
42 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/core/Router.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import React from 'react';
7 | import Context from '../components/Context';
8 |
9 | const routes = [
10 | require('../routes/Home').default,
11 | require('../routes/Test').default,
12 | require('../routes/NotFound').default
13 | ];
14 |
15 | const router = {
16 | match(location, state) {
17 | let component;
18 | const page = {
19 | title: 'My Application',
20 | description: 'Isomorphic web application sample',
21 | status: 200
22 | };
23 | const route = routes.find(x => x.path === location.path);
24 |
25 | if (route) {
26 | try {
27 | component = route.action();
28 | } catch (err) {
29 | component = routes.find(x => x.path === '/500').action();
30 | page.status = 500;
31 | }
32 | } else {
33 | component = routes.find(x => x.path === '/404').action();
34 | page.status = 404;
35 | }
36 |
37 | return [{component}, page];
38 | }
39 | };
40 |
41 | export default router;
42 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/components/Html/Html.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 Html({ title, description, body, state }) {
10 | return (
11 |
12 |
13 |
14 |
15 | {title}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | );
26 | }
27 |
28 | Html.propTypes = {
29 | title: PropTypes.string.isRequired,
30 | description: PropTypes.string.isRequired,
31 | body: PropTypes.string.isRequired,
32 | state: PropTypes.object.isRequired
33 | };
34 |
35 | export default Html;
36 |
--------------------------------------------------------------------------------
/Chapter 07/7-routing/modules/ReposWithRouter.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 | import {withRouter} from 'react-router'
4 |
5 | class ReposWithRouter extends React.Component{
6 |
7 | constructor(props){
8 | super(props);
9 | }
10 |
11 | handleSubmit(event) {
12 | event.preventDefault();
13 | const userName = event.target.elements[0].value;
14 | const repo = event.target.elements[1].value;
15 | const path = `/repos/${userName}/${repo}`;
16 | this.props.history.push(path);
17 | }
18 |
19 | render() {
20 | return (
21 |
22 |
Repos
23 |
24 | - React Router
25 | - React
26 | -
27 |
32 |
33 |
34 |
35 | )
36 | }
37 | }
38 |
39 | export default withRouter(ReposWithRouter);
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/tests/it/NightwatchTest.js:
--------------------------------------------------------------------------------
1 | describe('Testing our app', function() {
2 |
3 | describe('with Nightwatch', function() {
4 |
5 | before(function(client, done) {
6 | done();
7 | });
8 |
9 | after(function(client, done) {
10 | client.end(function() {
11 | done();
12 | });
13 | });
14 |
15 | afterEach(function(client, done) {
16 | done();
17 | });
18 |
19 | beforeEach(function(client, done) {
20 | done();
21 | });
22 |
23 | it('testing navigation to repos', function(client) {
24 | client
25 | .url('http://localhost:8080')
26 | .expect.element('body').to.be.present.before(1000);
27 |
28 | client.click('.repos-link', function () {
29 | client.expect.element('.repos-title').text.to.equal('Repos');
30 | client.assert.urlEquals('http://localhost:8080/repos');
31 | })
32 | });
33 |
34 | it('testing url navigation to repos', function(client) {
35 | client
36 | .url('http://localhost:8080/repos');
37 |
38 | // now we navigate to repos directly
39 | client.expect.element('.repos-title').text.to.equal('Repos');
40 | });
41 |
42 | });
43 | });
--------------------------------------------------------------------------------
/Chapter 08/8-auth/src/components/ReposWithRouter.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 | import {withRouter} from 'react-router'
4 |
5 | class ReposWithRouter extends React.Component{
6 |
7 | constructor(props){
8 | super(props);
9 | }
10 |
11 | handleSubmit(event) {
12 | event.preventDefault();
13 | const userName = event.target.elements[0].value;
14 | const repo = event.target.elements[1].value;
15 | const path = `/repos/${userName}/${repo}`;
16 | this.props.history.push(path);
17 | }
18 |
19 | render() {
20 | return (
21 |
22 |
Repos
23 |
24 | - React Router
25 | - React
26 | -
27 |
32 |
33 |
34 |
35 | )
36 | }
37 | }
38 |
39 | export default withRouter(ReposWithRouter);
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/components/ReposWithRouter.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 | import {withRouter} from 'react-router'
4 |
5 | class ReposWithRouter extends React.Component{
6 |
7 | constructor(props){
8 | super(props);
9 | }
10 |
11 | handleSubmit(event) {
12 | event.preventDefault();
13 | const userName = event.target.elements[0].value;
14 | const repo = event.target.elements[1].value;
15 | const path = `/repos/${userName}/${repo}`;
16 | this.props.history.push(path);
17 | }
18 |
19 | render() {
20 | return (
21 |
22 |
Repos
23 |
24 | - React Router
25 | - React
26 | -
27 |
32 |
33 |
34 |
35 | )
36 | }
37 | }
38 |
39 | export default withRouter(ReposWithRouter);
--------------------------------------------------------------------------------
/Chapter 07/7-routing/modules/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 | import RouteWithSubRoutes from './RouteWithSubRoutes'
4 |
5 | export default class App extends React.Component {
6 |
7 | constructor(props){
8 | super(props);
9 | this.state = {
10 | msg: "Loading..."
11 | };
12 | }
13 |
14 | static loadData() {
15 | return Promise.resolve({
16 | data: 'Hello App'
17 | });
18 | }
19 |
20 | componentDidMount() {
21 | if(!this.props.initialData){
22 | this.constructor.loadData().then((data) => {
23 | this.setState({msg: data.data});
24 | });
25 | } else {
26 | this.setState({msg: this.props.initialData[0].data});
27 | }
28 | }
29 |
30 | render() {
31 | return (
32 |
33 |
React Router Tutorial
34 |
35 | - Home
36 | - About
37 | - Repos
38 |
39 |
40 |
{this.state.msg}
41 | {
42 | this.props.routes.map((route, i) => (
43 |
44 | ))
45 | }
46 |
47 | )
48 | }
49 | };
50 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/server.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import 'babel-core/register';
7 | import path from 'path';
8 | import express from 'express';
9 | import React from 'react';
10 | import ReactDOM from 'react-dom/server';
11 | import Router from './core/Router';
12 | import Html from './components/Html/Html';
13 |
14 | const server = express();
15 | const port = process.env.PORT || 3000;
16 |
17 | server.use(express.static(path.join(__dirname, 'public')));
18 |
19 | server.use((req, res, next) => {
20 | if (typeof req.query.admin !== 'undefined') {
21 | req.user = { name: 'Tarkus '};
22 | } else {
23 | req.user = null;
24 | }
25 | next();
26 | });
27 |
28 | server.use('/api', require('./api/test').default);
29 |
30 | server.get('*', (req, res) => {
31 | const state = { user: req.user };
32 | const [component, page] = Router.match(req, state);
33 | const body = ReactDOM.renderToString(component);
34 | const html = ReactDOM.renderToStaticMarkup(');
13 | global.window = dom.window;
14 | global.document = dom.window.document;
15 | const $ = jquery(global.window);
16 |
17 | // build 'renderComponent' helper that should render a given react class
18 | function renderComponent(ComponentClass, props, state) {
19 | const componentInstance = TestUtils.renderIntoDocument(
20 | state, state)}>
21 |
22 |
23 | );
24 |
25 | return $(ReactDOM.findDOMNode(componentInstance)); // produces HTML
26 | }
27 |
28 | // Build helper for simulating events
29 | $.fn.simulate = function (eventName, value) {
30 | if (value) {
31 | this.val(value);
32 | }
33 | TestUtils.Simulate[eventName](this[0]);
34 | };
35 |
36 | // Set up chai-jquery
37 | chaiJquery(chai, chai.util, $);
38 |
39 | export {renderComponent, expect};
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/data/models/User.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import DataType from 'sequelize';
7 | import Model from '../sequelize';
8 |
9 | const batch = { keys: new Set(), task: null };
10 |
11 | const User = Model.define('User', {
12 |
13 | id: {
14 | type: DataType.INTEGER,
15 | primaryKey: true,
16 | autoIncrement: true
17 | },
18 |
19 | username: {
20 | type: DataType.TEXT
21 | },
22 |
23 | email: {
24 | type: DataType.TEXT,
25 | validate: { isEmail: true }
26 | },
27 |
28 | password: {
29 | type: DataType.TEXT
30 | },
31 |
32 | displayName: {
33 | type: DataType.TEXT
34 | }
35 |
36 | }, {
37 | classMethods: {
38 | load(id) {
39 | if (!batch.keys.size) {
40 | batch.task = new Promise((resolve, reject) => {
41 | process.nextTick(() => {
42 | this.constructor.prototype.findAll.call(this, {
43 | where: { id: Array.from(batch.keys) }
44 | }).then((data) => {
45 | batch.keys.clear();
46 | resolve(data);
47 | }, reject);
48 | });
49 | });
50 | }
51 | batch.keys.add(id);
52 | return batch.task.then(data => data.find(x => x.id === id));
53 | }
54 | }
55 | });
56 |
57 | export default User;
58 |
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/tests/EnzymeTest.js:
--------------------------------------------------------------------------------
1 | import { MemoryRouter } from 'react-router-dom'
2 | import About from '../components/About'
3 | import chai, {expect} from 'chai';
4 |
5 | import {Provider} from 'react-redux'
6 | import {createStore} from 'redux'
7 | import reducers from './../reducers';
8 |
9 | import React from 'react';
10 |
11 | import { configure, mount, shallow, render } from 'enzyme';
12 | import chaiEnzyme from 'chai-enzyme'
13 | import Adapter from 'enzyme-adapter-react-16';
14 |
15 | configure({ adapter: new Adapter() });
16 |
17 | chai.use(chaiEnzyme());
18 |
19 | suite('Enzyme test suite', function () {
20 |
21 | test('simple dom test', function () {
22 | const component = render(
23 |
24 | );
25 | expect(component.find('.about-msg')).to.have.text('Hello');
26 | });
27 |
28 | test('simple test', function () {
29 | const $node = shallow(
30 |
31 | );
32 | expect($node.find('.about-msg')).to.have.text('Hello');
33 | });
34 |
35 | test('test router', function () {
36 | const $node = mount(
37 |
38 |
39 |
40 |
41 |
42 | );
43 |
44 | $node.find('.about-btn').simulate('click');
45 |
46 | expect($node.find('.about-msg').text()).to.equal('World');
47 | });
48 |
49 |
50 |
51 | });
--------------------------------------------------------------------------------
/Chapter 08/8-auth/src/components/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 | import RouteWithSubRoutes from './RouteWithSubRoutes'
4 |
5 | export default class App extends React.Component {
6 |
7 | constructor(props){
8 | super(props);
9 | this.state = {
10 | msg: "Loading..."
11 | };
12 | }
13 |
14 | static loadData() {
15 | return Promise.resolve({
16 | data: 'Hello App'
17 | });
18 | }
19 |
20 | componentDidMount() {
21 | if(!this.props.initialData){
22 | this.constructor.loadData().then((data) => {
23 | this.setState({msg: data.data});
24 | });
25 | } else {
26 | this.setState({msg: this.props.initialData[0].data});
27 | console.log(`I already have the data: ${this.props.initialData}`);
28 | }
29 | }
30 |
31 | render() {
32 | return (
33 |
34 |
React Router Tutorial
35 |
36 | - Home
37 | - About
38 | - Repos
39 |
40 |
41 |
{this.state.msg}
42 | {
43 | this.props.routes.map((route, i) => (
44 |
45 | ))
46 | }
47 |
48 | )
49 | }
50 | };
51 |
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/components/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 | import RouteWithSubRoutes from './RouteWithSubRoutes'
4 |
5 | export default class App extends React.Component {
6 |
7 | constructor(props){
8 | super(props);
9 | this.state = {
10 | msg: "Loading..."
11 | };
12 | }
13 |
14 | static loadData() {
15 | return Promise.resolve({
16 | data: 'Hello App'
17 | });
18 | }
19 |
20 | componentDidMount() {
21 | if(!this.props.initialData){
22 | this.constructor.loadData().then((data) => {
23 | this.setState({msg: data.data});
24 | });
25 | } else {
26 | this.setState({msg: this.props.initialData[0].data});
27 | console.log(`I already have the data: ${this.props.initialData}`);
28 | }
29 | }
30 |
31 | render() {
32 | return (
33 |
34 |
React Router Tutorial
35 |
36 | - Home
37 | - About
38 | - Repos
39 |
40 |
41 |
{this.state.msg}
42 | {
43 | this.props.routes.map((route, i) => (
44 |
45 | ))
46 | }
47 |
48 | )
49 | }
50 | };
51 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/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 06/6-graphql/data/models/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import faker from 'faker';
7 | import sequelize from '../sequelize';
8 | import User from './User';
9 | import Tag from './Tag';
10 | import Offer from './Offer';
11 |
12 | Offer.belongsTo(User, {
13 | as: 'author'
14 | });
15 |
16 | User.hasMany(Offer, {
17 | as: 'offers',
18 | foreignKey: 'authorId'
19 | });
20 |
21 | Tag.belongsToMany(Offer, {
22 | as: 'offers',
23 | through: 'TagOffer'
24 | });
25 |
26 | async function sync(options) {
27 | // Create db tables
28 | await sequelize.sync(options);
29 | if (!options.force) return;
30 |
31 | // Import seed data
32 | for (let i = 0; i < 50; i++) {
33 | const firstName = faker.name.firstName();
34 | const lastName = faker.name.lastName();
35 | await User.create({
36 | username: faker.internet.userName(firstName, lastName),
37 | email: faker.internet.email(firstName, lastName),
38 | password: faker.internet.password(),
39 | displayName: faker.name.findName(firstName, lastName)
40 | });
41 | }
42 |
43 | for (let i = 0; i < 100; i++) {
44 | const departament = faker.commerce.department();
45 | Tag.create({
46 | slug: departament.toLowerCase().replace(/\s+/g, '_'),
47 | name: departament
48 | });
49 | }
50 | }
51 |
52 | export default { sync };
53 | export { User, Tag, Offer };
54 |
--------------------------------------------------------------------------------
/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 04/4-browsersync/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 06/6-graphql/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 05/5-react-server/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 06/6-graphql/routes/Test/Test.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 PropTypes from 'prop-types';
8 | import fetch from '../../core/fetch';
9 | import CurrentTime from '../../components/CurrentTime';
10 | import LikeButton from '../../components/LikeButton';
11 | import Layout from '../../components/Layout';
12 |
13 | const path = '/test';
14 | const action = () => ;
15 |
16 | class Test extends Component {
17 | static contextTypes = {
18 | page: PropTypes.shape({
19 | title: PropTypes.string
20 | }),
21 | user: PropTypes.shape({
22 | name: PropTypes.string.isRequired
23 | })
24 | };
25 |
26 | state = { data: 'loading...' };
27 |
28 | async componentWillMount() {
29 | try {
30 | const response = await fetch('/api/test');
31 | const data = await response.text();
32 | this.setState({ data });
33 | } catch (err) {
34 | this.setState({ data: `Error: ${err.message}` });
35 | }
36 | }
37 |
38 | render() {
39 | const { page, user } = this.context;
40 | page.title = 'Test Page';
41 |
42 | return (
43 |
44 |
{page.title}
45 |
46 |
47 |
Welcome, {user ? user.name : 'Guest'}!
48 |
49 |
Server response: {this.state.data}
50 |
51 | );
52 | }
53 | }
54 |
55 | export default { path, action };
56 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "eslintConfig": {
4 | "parser": "babel-eslint",
5 | "extends": "airbnb",
6 | "rules": {
7 | "comma-dangle": 0,
8 | "id-length": [
9 | 2,
10 | {
11 | "exceptions": [
12 | "i",
13 | "_",
14 | "x",
15 | "s"
16 | ]
17 | }
18 | ]
19 | }
20 | },
21 | "dependencies": {
22 | "bluebird": "3.5.0",
23 | "express": "4.15.4",
24 | "moment": "2.18.1",
25 | "react": "16.0.0",
26 | "react-dom": "16.0.0"
27 | },
28 | "devDependencies": {
29 | "autoprefixer": "7.1.4",
30 | "babel-cli": "6.7.5",
31 | "babel-core": "6.26.0",
32 | "babel-eslint": "8.0.0",
33 | "babel-loader": "7.1.2",
34 | "babel-plugin-transform-runtime": "6.7.5",
35 | "babel-preset-env": "1.6.0",
36 | "babel-preset-react": "6.5.0",
37 | "babel-preset-stage-0": "6.5.0",
38 | "del": "3.0.0",
39 | "eslint": "4.7.0",
40 | "eslint-config-airbnb": "15.1.0",
41 | "eslint-plugin-import": "2.7.0",
42 | "eslint-plugin-jsx-a11y": "6.0.2",
43 | "eslint-plugin-react": "7.3.0",
44 | "extend": "3.0.1",
45 | "gaze": "1.1.2",
46 | "ncp": "2.0.0",
47 | "node-style-loader": "0.0.1-alpha",
48 | "postcss-loader": "2.0.6",
49 | "precss": "2.0.0",
50 | "webpack-dev-middleware": "2.0.4",
51 | "webpack": "3.6.0"
52 | },
53 | "scripts": {
54 | "lint": "eslint components core data routes test tools",
55 | "build": "babel-node tools/run build",
56 | "serve": "node build/server.js"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/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 02/2-react/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 06/6-graphql/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 04/4-browsersync/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 05/5-react-server/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 02/2-react/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 06/6-graphql/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 04/4-browsersync/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 05/5-react-server/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 09/B05226_09_Code/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tutorial",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start:dev:client": "webpack-dev-server --inline --content-base public/ --history-api-fallback",
8 | "start:dev:server": "webpack && babel-node serverWithInitialData.js",
9 | "start:prod:client": "webpack -p",
10 | "start:prod:server": "webpack && babel-node serverWithInitialData.js",
11 | "test": "mocha --ui tdd --compilers js:babel-register src/tests/*Test.js",
12 | "it": "nightwatch --config nightwatch.json"
13 | },
14 | "author": "",
15 | "license": "ISC",
16 | "dependencies": {
17 | "express": "4.15.4",
18 | "jquery": "3.2.1",
19 | "react": "16.0.0",
20 | "react-dom": "16.0.0",
21 | "react-redux": "5.0.6",
22 | "react-router": "4.2.0",
23 | "react-router-config": "1.0.0-beta.4",
24 | "react-router-dom": "4.2.2",
25 | "redux": "3.7.2"
26 | },
27 | "devDependencies": {
28 | "babel-cli": "6.26.0",
29 | "babel-core": "6.26.0",
30 | "babel-loader": "7.1.2",
31 | "babel-preset-env": "1.6.0",
32 | "babel-preset-react": "6.24.1",
33 | "babel-preset-stage-2": "6.24.1",
34 | "babel-register": "^6.26.0",
35 | "chai": "4.1.2",
36 | "chai-enzyme": "1.0.0-beta.0",
37 | "chai-jquery": "2.0.0",
38 | "enzyme": "^3.1.0",
39 | "enzyme-adapter-react-16": "^1.0.1",
40 | "http-server": "0.10.0",
41 | "jsdom": "11.3.0",
42 | "mocha": "3.5.3",
43 | "nightwatch": "0.9.16",
44 | "react-test-renderer": "16.0.0",
45 | "source-map-support": "0.4.18",
46 | "webpack": "3.5.6",
47 | "webpack-dev-server": "2.7.1"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Chapter 07/7-routing/server.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import express from 'express'
3 | // we'll use this to render our app to an html string
4 | import { renderToString } from 'react-dom/server'
5 | // and these to match the url to routes and then render
6 | import { StaticRouter } from 'react-router'
7 | import App from './modules/App'
8 |
9 | import path from 'path';
10 |
11 | const app = express();
12 |
13 | // serve our static stuff like index.css
14 | app.use(express.static(path.join(__dirname, 'public')));
15 |
16 | app.get('*', (req, res) => {
17 |
18 | const context = {};
19 | const html = renderToString(
20 |
23 |
24 |
25 |
26 |
27 | );
28 |
29 | if (context.url) {
30 | // Somewhere a `` was rendered
31 | res.redirect(302, context.url);
32 | } else {
33 | res.set('content-type', 'text/html');
34 | res.send(renderPage(html, {}));
35 | //res.sendFile('index.html'); // -> without initial data
36 | }
37 | });
38 |
39 | function renderPage(appHtml, initialState) {
40 | return `
41 |
42 |
43 |
44 | My First React Router App
45 |
46 | ${appHtml}
47 |
48 |
51 | `
52 | }
53 |
54 | const PORT = process.env.PORT || 8080;
55 | app.listen(PORT, function () {
56 | console.log('Production Express server running at localhost:' + PORT)
57 | });
--------------------------------------------------------------------------------
/Chapter 04/4-browsersync/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "Header",
4 | "main": "./Header.js",
5 | "dependencies": {
6 | "bluebird": "3.5.0",
7 | "express": "4.15.4",
8 | "moment": "2.18.1",
9 | "react": "16.0.0",
10 | "react-dom": "16.0.0"
11 | },
12 | "devDependencies": {
13 | "autoprefixer": "^7.1.4",
14 | "babel-cli": "6.7.5",
15 | "babel-core": "6.26.0",
16 | "babel-eslint": "8.0.0",
17 | "babel-loader": "7.1.2",
18 | "babel-plugin-transform-runtime": "6.7.5",
19 | "babel-preset-env": "1.6.0",
20 | "babel-preset-react": "6.5.0",
21 | "babel-preset-stage-0": "6.5.0",
22 | "css-loader": "0.28.5",
23 | "del": "3.0.0",
24 | "eslint": "4.6.1",
25 | "eslint-config-airbnb": "15.1.0",
26 | "eslint-plugin-react": "7.3.0",
27 | "extend": "3.0.0",
28 | "file-loader": "0.11.2",
29 | "gaze": "1.1.2",
30 | "ncp": "2.0.0",
31 | "node-style-loader": "0.0.1-alpha",
32 | "postcss-loader": "^2.0.6",
33 | "precss": "^2.0.0",
34 | "style-loader": "0.18.2",
35 | "url-loader": "0.5.9",
36 | "webpack": "3.5.6",
37 | "webpack-dev-middleware": "2.0.4"
38 | },
39 | "eslintConfig": {
40 | "parser": "babel-eslint",
41 | "extends": "airbnb",
42 | "rules": {
43 | "comma-dangle": 0,
44 | "id-length": [
45 | 2,
46 | {
47 | "exceptions": [
48 | "i",
49 | "_",
50 | "x",
51 | "s"
52 | ]
53 | }
54 | ]
55 | }
56 | },
57 | "scripts": {
58 | "lint": "eslint components core data routes test tools",
59 | "build": "babel-node tools/run build",
60 | "serve": "node build/server.js"
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "react-chapter",
4 | "eslintConfig": {
5 | "parser": "babel-eslint",
6 | "extends": "airbnb",
7 | "rules": {
8 | "comma-dangle": 0,
9 | "id-length": [
10 | 2,
11 | {
12 | "exceptions": [
13 | "i",
14 | "_",
15 | "x",
16 | "s"
17 | ]
18 | }
19 | ]
20 | }
21 | },
22 | "dependencies": {
23 | "bluebird": "3.5.0",
24 | "express": "4.15.4",
25 | "moment": "2.18.1",
26 | "node-fetch": "1.7.2",
27 | "react": "16.0.0",
28 | "react-dom": "16.0.0"
29 | },
30 | "devDependencies": {
31 | "autoprefixer": "7.1.4",
32 | "babel-cli": "6.7.5",
33 | "babel-core": "6.26.0",
34 | "babel-eslint": "8.0.0",
35 | "babel-loader": "7.1.2",
36 | "babel-plugin-transform-runtime": "6.7.5",
37 | "babel-preset-env": "1.6.0",
38 | "babel-preset-react": "6.5.0",
39 | "babel-preset-stage-0": "6.5.0",
40 | "css-loader": "0.28.5",
41 | "del": "3.0.0",
42 | "eslint": "4.6.1",
43 | "eslint-config-airbnb": "15.1.0",
44 | "eslint-plugin-react": "7.3.0",
45 | "extend": "3.0.0",
46 | "file-loader": "0.11.2",
47 | "gaze": "1.1.2",
48 | "ncp": "2.0.0",
49 | "node-style-loader": "0.0.1-alpha",
50 | "postcss-import": "10.0.0",
51 | "postcss-loader": "2.0.6",
52 | "precss": "2.0.0",
53 | "style-loader": "0.18.2",
54 | "url-loader": "0.5.9",
55 | "webpack-dev-middleware": "2.0.4",
56 | "webpack": "3.5.6"
57 | },
58 | "scripts": {
59 | "lint": "eslint components core data routes test tools",
60 | "build": "babel-node tools/run build",
61 | "serve": "node build/server.js"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Chapter 05/5-react-server/routes/Test/Test.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 PropTypes from 'prop-types';
8 | import fetch from '../../core/fetch';
9 | import CurrentTime from '../../components/CurrentTime';
10 | import LikeButton from '../../components/LikeButton';
11 | import Layout from '../../components/Layout';
12 |
13 | const path = '/test';
14 | const action = () => ;
15 |
16 | class Test extends Component {
17 |
18 | static contextTypes = {
19 | page: PropTypes.shape({
20 | title: PropTypes.string
21 | }),
22 | user: PropTypes.shape({
23 | name: PropTypes.string.isRequired
24 | }),
25 | };
26 |
27 | state = { data: 'loading...' };
28 |
29 | componentDidMount2() {
30 | fetch('/api/test').then(x => x.json()).then(data => this.setState({ data }));
31 | }
32 | async componentWillMount() {
33 | try {
34 | const response = await fetch('/api/test');
35 | const data = await response.text();
36 | console.log('>>> data:', data);
37 | this.setState({ data });
38 | } catch (err) {
39 | console.error(err);
40 | this.setState({ data: 'Error: ' + err.message });
41 | }
42 | }
43 |
44 | render() {
45 | const { page, user } = this.context;
46 | page.title = 'Test Page';
47 |
48 | return (
49 |
50 |
{page.title}
51 |
52 |
53 |
Welcome, {user ? user.name : 'Guest'}!
54 |
55 |
Server response: {this.state.data}
56 |
57 | );
58 | }
59 | }
60 |
61 | export default { path, action };
62 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Isomorphic JavaScript Web Development
2 | This is the code repository for [Isomorphic JavaScript Web Development](https://www.packtpub.com/web-development/isomorphic-javascript-web-development?utm_source=github&utm_medium=repository&utm_campaign=9781785889769), published by [Packt](https://www.packtpub.com/). It contains all the supporting project files necessary to work through the book from start to finish.
3 | ## About the Book
4 | The latest trend in web development, Isomorphic JavaScript, allows developers to overcome some of the shortcomings of single-page applications by running the same code on the server as well as on the client. Leading this trend is React, which, when coupled with Node, allows developers to build JavaScript apps that are much faster and more SEO-friendly than single-page applications.
5 | ### Instructions and Navigations
6 | All of the codes are organized as per the chapters, each folder has the codes related to that chapter or appendix.
7 | For example: Isomorphic-JavaScript-Web-Development/Chapter 04/4-browsersync/components/App.js
8 |
9 | The code will look like the following:
10 | ```
11 | constructor(props) {
12 | super(props);
13 | this.state = { time: null };
14 | }
15 | ```
16 |
17 | ## Related Products
18 |
19 |
20 | * [Mastering MEAN Web Development: Expert Full Stack JavaScript [Video]](https://www.packtpub.com/web-development/mastering-mean-web-development-expert-full-stack-javascript-video?utm_source=github&utm_medium=repository&utm_campaign=9781785882159)
21 |
22 |
23 | * [Isomorphic Go](https://www.packtpub.com/web-development/isomorphic-go?utm_source=github&utm_medium=repository&utm_campaign=9781788394185)
24 |
25 |
26 | * [JavaScript by Example](https://www.packtpub.com/web-development/javascript-example?utm_source=github&utm_medium=repository&utm_campaign=9781788293969)
27 |
28 |
--------------------------------------------------------------------------------
/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 04/4-browsersync/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: Working with Browsersync and Hot Module Replacement**
13 | Chapter 5: Configuring Server-side Rendering
14 | Chapter 6: Creating an API Backend with GraphQL
15 | Chapter 7: Fetching Data with Relay
16 | Chapter 8: Implementing Routing and Navigation
17 | Chapter 9: Authentication and authorization
18 | Chapter 10: 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 06/6-graphql/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: Working with Browsersync and Hot Module Replacement
13 | > **Chapter 5: Rendering React components on the server**
14 | Chapter 6: Creating an API Backend with GraphQL
15 | Chapter 7: Fetching Data with Relay
16 | Chapter 8: Implementing Routing and Navigation
17 | Chapter 9: Authentication and authorization
18 | Chapter 10: 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 05/5-react-server/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: Working with Browsersync and Hot Module Replacement
13 | > **Chapter 5: Rendering React components on the server**
14 | Chapter 6: Creating an API Backend with GraphQL
15 | Chapter 7: Fetching Data with Relay
16 | Chapter 8: Implementing Routing and Navigation
17 | Chapter 9: Authentication and authorization
18 | Chapter 10: 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 06/6-graphql/server.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Learning Isomorphic Web Application Development
3 | * Copyright © 2016 Konstantin Tarkus, Packt Publishing
4 | */
5 |
6 | import 'babel-core/register';
7 | import path from 'path';
8 | import express from 'express';
9 | import graphql from 'express-graphql';
10 | import React from 'react';
11 | import ReactDOM from 'react-dom/server';
12 | import models from './data/models';
13 | import schema from './data/schema';
14 | import Router from './core/Router';
15 | import Html from './components/Html/Html';
16 |
17 | const app = express();
18 | const port = process.env.PORT || 3000;
19 |
20 | app.use(express.static(path.join(__dirname, 'public')));
21 |
22 | app.use((req, res, next) => {
23 | if (typeof req.query.admin !== 'undefined') {
24 | req.user = { id: 1 }; // eslint-disable-line no-param-reassign
25 | } else {
26 | req.user = null; // eslint-disable-line no-param-reassign
27 | }
28 | next();
29 | });
30 |
31 | app.use('/graphql', graphql({
32 | schema,
33 | rootValue: { user: { id: 1 } },
34 | pretty: process.env.NODE_ENV !== 'production',
35 | graphiql: true
36 | }));
37 |
38 | app.get('*', (req, res) => {
39 | const state = { user: req.user };
40 | const [component, page] = Router.match(req, state);
41 | const body = ReactDOM.renderToString(component);
42 | const html = ReactDOM.renderToStaticMarkup(
43 |
49 | );
50 | res.status(page.status).send(`\n${html}`);
51 | });
52 |
53 | /* eslint-disable no-console */
54 | models.sync({ force: process.env.NODE_ENV !== 'production' })
55 | .catch(err => console.error(err.stack))
56 | .then(() => {
57 | app.listen(port, () => console.log(
58 | `Node.js server is listening at http://localhost:${port}/`
59 | ));
60 | });
61 | /* eslint-enable no-console */
62 |
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/src/tests/PlainTest.js:
--------------------------------------------------------------------------------
1 | import TestUtils from 'react-dom/test-utils';
2 | import { Route, Link, MemoryRouter } from 'react-router-dom'
3 | import About from '../components/About'
4 | import chai, {expect} from 'chai';
5 | import chaiJquery from 'chai-jquery';
6 | import {JSDOM} from 'jsdom';
7 | import jquery from 'jquery';
8 |
9 | import {Provider} from 'react-redux'
10 | import {createStore} from 'redux'
11 | import reducers from './../reducers';
12 |
13 | import React from 'react';
14 | import ReactDOM from 'react-dom';
15 |
16 |
17 | function setupTests() {
18 | const dom = new JSDOM('');
19 | global.window = dom.window;
20 | global.document = dom.window.document;
21 | const $ = jquery(global.window);
22 | // Set up chai-jquery
23 | chaiJquery(chai, chai.util, $);
24 |
25 | return $;
26 | }
27 |
28 | require('fbjs/lib/ExecutionEnvironment').canUseDOM = true;
29 |
30 | suite('test suite', function () {
31 |
32 | const $ = setupTests();
33 |
34 | test('simple dom test', function () {
35 | const component = TestUtils.renderIntoDocument(
36 |
37 | );
38 | const renderedComponent = ReactDOM.findDOMNode(component);
39 | expect(renderedComponent.querySelector('.about-msg').textContent).to.equal('Hello');
40 | });
41 |
42 | test('simple test', function () {
43 | const $node = $(ReactDOM.findDOMNode(TestUtils.renderIntoDocument(
44 |
45 | )));
46 | expect($node.find('.about-msg')).to.have.text('Hello');
47 | });
48 |
49 | test('test router', function () {
50 | const $node = $(ReactDOM.findDOMNode(TestUtils.renderIntoDocument(
51 |
52 |
53 |
54 |
55 |
56 | )));
57 |
58 | TestUtils.Simulate.click($node.find('.about-btn')[0], {
59 | button: 0
60 | });
61 |
62 | expect($node.find('.about-msg').text()).to.equal('World');
63 | });
64 |
65 |
66 |
67 | });
--------------------------------------------------------------------------------
/Chapter 06/6-graphql/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "eslintConfig": {
4 | "parser": "babel-eslint",
5 | "extends": "airbnb",
6 | "rules": {
7 | "comma-dangle": 0,
8 | "id-length": [
9 | 2,
10 | {
11 | "exceptions": [
12 | "i",
13 | "_",
14 | "x",
15 | "s"
16 | ]
17 | }
18 | ]
19 | }
20 | },
21 | "dependencies": {
22 | "babel-polyfill": "6.26.0",
23 | "babel-runtime": "6.26.0",
24 | "bluebird": "3.5.0",
25 | "express": "4.15.4",
26 | "express-graphql": "0.6.11",
27 | "faker": "4.1.0",
28 | "graphiql": "0.11.3",
29 | "graphql": "0.11.3",
30 | "moment": "2.18.1",
31 | "node-fetch": "1.5.1",
32 | "react": "16.0.0",
33 | "react-dom": "16.0.0",
34 | "sequelize": "4.8.3",
35 | "sqlite3": "3.1.11",
36 | "whatwg-fetch": "2.0.3"
37 | },
38 | "devDependencies": {
39 | "babel-cli": "6.7.5",
40 | "babel-core": "6.26.0",
41 | "babel-eslint": "8.0.0",
42 | "babel-loader": "7.1.2",
43 | "babel-plugin-transform-runtime": "6.7.5",
44 | "babel-preset-env": "1.6.0",
45 | "babel-preset-react": "6.5.0",
46 | "babel-preset-stage-0": "6.5.0",
47 | "browser-sync": "2.12.3",
48 | "css-loader": "0.28.7",
49 | "del": "3.0.0",
50 | "eslint": "4.6.1",
51 | "eslint-config-airbnb": "15.1.0",
52 | "eslint-plugin-import": "2.7.0",
53 | "eslint-plugin-jsx-a11y": "6.0.2",
54 | "eslint-plugin-react": "7.3.0",
55 | "extend": "3.0.0",
56 | "file-loader": "0.11.2",
57 | "gaze": "1.0.0",
58 | "ncp": "2.0.0",
59 | "postcss": "6.0.11",
60 | "postcss-import": "10.0.0",
61 | "postcss-loader": "2.0.6",
62 | "precss": "2.0.0",
63 | "style-loader": "0.18.2",
64 | "url-loader": "0.5.7",
65 | "webpack": "3.5.6",
66 | "webpack-dev-middleware": "2.0.4",
67 | "webpack-hot-middleware": "2.10.0"
68 | },
69 | "scripts": {
70 | "lint": "eslint components core data routes test tools client.js server.js",
71 | "build": "babel-node tools/run build",
72 | "serve": "node build/server.js"
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Chapter 02/2-react/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 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 04/4-browsersync/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 06/6-graphql/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 05/5-react-server/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 07/7-routing/serverWithInitialData.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import express from 'express'
3 | // we'll use this to render our app to an html string
4 | import { renderToString } from 'react-dom/server'
5 | // and these to match the url to routes and then render
6 | import { StaticRouter } from 'react-router'
7 | import Root from './modules/Root'
8 |
9 | import path from 'path';
10 | import { matchRoutes } from 'react-router-config'
11 | import routes from './routesConfig'
12 | import 'source-map-support/register';
13 |
14 | const app = express();
15 |
16 | // serve our static stuff like index.css
17 | app.use(express.static(path.join(__dirname, 'public')));
18 |
19 | const loadBranchData = (location) => {
20 | const branch = matchRoutes(routes, location);
21 |
22 | const promises = branch.map(({ route, match }) => {
23 | return route.loadData
24 | ? route.loadData(match)
25 | : Promise.resolve(null)
26 | });
27 |
28 | return Promise.all(promises)
29 | };
30 |
31 | app.get('*', (req, res) => {
32 |
33 | loadBranchData(req.url).then((initialData) => {
34 | const context = {};
35 | const html = renderToString(
36 |
39 |
40 |
41 |
42 |
43 | );
44 |
45 | if (context.url) {
46 | // Somewhere a `` was rendered
47 | res.redirect(302, context.url);
48 | } else {
49 | res.set('content-type', 'text/html');
50 | console.log(initialData);
51 | res.send(renderPage(html, initialData));
52 | //res.sendFile('index.html'); // -> without initial data
53 | }
54 | });
55 |
56 | });
57 |
58 | function renderPage(appHtml, initialState) {
59 | return `
60 |
61 |
62 |
63 | My First React Router App
64 |
65 | ${appHtml}
66 |
70 |
71 | `
72 | }
73 |
74 | const PORT = process.env.PORT || 8080;
75 | app.listen(PORT, function () {
76 | console.log('Production Express server running at localhost:' + PORT)
77 | });
--------------------------------------------------------------------------------
/Chapter 08/8-auth/serverWithInitialData.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import express from 'express'
3 | // we'll use this to render our app to an html string
4 | import {renderToString} from 'react-dom/server'
5 | // and these to match the url to routes and then render
6 | import {StaticRouter} from 'react-router'
7 | import Root from './src/components/Root'
8 |
9 | import path from 'path';
10 | import {matchRoutes} from 'react-router-config'
11 | import routes from './routesConfig'
12 | import {Provider} from 'react-redux'
13 | import { createStore } from 'redux';
14 | import reducers from './src/reducers';
15 |
16 | const app = express();
17 |
18 | // serve our static stuff like index.css
19 | app.use(express.static(path.join(__dirname, 'public')));
20 |
21 | const loadBranchData = (location) => {
22 | const branch = matchRoutes(routes, location);
23 |
24 | const promises = branch.map(({route, match}) => {
25 | return route.loadData
26 | ? route.loadData(match)
27 | : Promise.resolve(null)
28 | });
29 |
30 | return Promise.all(promises)
31 | };
32 |
33 | app.get('*', (req, res) => {
34 |
35 | loadBranchData(req.url).then((initialData) => {
36 | const context = {};
37 |
38 | initialData = { auth: { authenticated : false}};
39 |
40 | const store = createStore(reducers, initialData);
41 |
42 | const html = renderToString(
43 |
44 |
47 |
48 |
49 |
50 | );
51 |
52 | if (context.url) {
53 | // Somewhere a `` was rendered
54 | console.log(`REDIRECTED! to ${context.url}`);
55 | res.redirect(302, context.url);
56 | } else {
57 | res.set('content-type', 'text/html');
58 | console.log("initial data from server");
59 | console.log(initialData);
60 | res.send(renderPage(html, initialData));
61 | //res.sendFile('index.html'); // -> without initial data
62 | }
63 | });
64 |
65 | });
66 |
67 | function renderPage(appHtml, initialState) {
68 | return `
69 |
70 |
71 |
72 | My First React Router App
73 |
74 | ${appHtml}
75 |
79 |
80 | `
81 | }
82 |
83 | const PORT = process.env.PORT || 8080;
84 | app.listen(PORT, function () {
85 | console.log('Production Express server running at localhost:' + PORT)
86 | });
--------------------------------------------------------------------------------
/Chapter 09/B05226_09_Code/serverWithInitialData.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import express from 'express'
3 | // we'll use this to render our app to an html string
4 | import {renderToString} from 'react-dom/server'
5 | // and these to match the url to routes and then render
6 | import {StaticRouter} from 'react-router'
7 | import Root from './src/components/Root'
8 |
9 | import path from 'path';
10 | import {matchRoutes} from 'react-router-config'
11 | import routes from './routesConfig'
12 | import {Provider} from 'react-redux'
13 | import { createStore } from 'redux';
14 | import reducers from './src/reducers';
15 |
16 | const app = express();
17 |
18 | // serve our static stuff like index.css
19 | app.use(express.static(path.join(__dirname, 'public')));
20 |
21 | const loadBranchData = (location) => {
22 | const branch = matchRoutes(routes, location);
23 |
24 | const promises = branch.map(({route, match}) => {
25 | return route.loadData
26 | ? route.loadData(match)
27 | : Promise.resolve(null)
28 | });
29 |
30 | return Promise.all(promises)
31 | };
32 |
33 | app.get('*', (req, res) => {
34 |
35 | loadBranchData(req.url).then((initialData) => {
36 | const context = {};
37 |
38 | initialData = { auth: { authenticated : false}};
39 |
40 | const store = createStore(reducers, initialData);
41 |
42 | const html = renderToString(
43 |
44 |
47 |
48 |
49 |
50 | );
51 |
52 | if (context.url) {
53 | // Somewhere a `` was rendered
54 | console.log(`REDIRECTED! to ${context.url}`);
55 | res.redirect(302, context.url);
56 | } else {
57 | res.set('content-type', 'text/html');
58 | console.log("initial data from server");
59 | console.log(initialData);
60 | res.send(renderPage(html, initialData));
61 | //res.sendFile('index.html'); // -> without initial data
62 | }
63 | });
64 |
65 | });
66 |
67 | function renderPage(appHtml, initialState) {
68 | return `
69 |
70 |
71 |
72 | My First React Router App
73 |
74 | ${appHtml}
75 |
79 |
80 | `
81 | }
82 |
83 | const PORT = process.env.PORT || 8080;
84 | app.listen(PORT, function () {
85 | console.log('Production Express server running at localhost:' + PORT)
86 | });
--------------------------------------------------------------------------------