├── .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  2Fx @ATTRxx -------------------------------------------------------------------------------- /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 |
14 | 17 | 18 |
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 |
14 | 17 | 18 |
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 |
14 | 17 | 18 |
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 |
14 | 18 | 19 |
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 |
{hero}
14 |
15 | {children} 16 |
17 |
18 | © Company Name 19 |
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 |
12 |
13 | My App 14 | { 15 | !children && 16 |
17 | } 18 |
19 | Username 20 | 21 |
22 |
23 | {children} 24 |
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 |
12 |
13 | My App 14 | { 15 | !children && 16 |
17 | } 18 |
19 | Username 20 | 21 |
22 |
23 | {children} 24 |
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 |
12 |
13 | My App 14 | { 15 | !children && 16 |
17 | } 18 |
19 | Username 20 | 21 |
22 |
23 | {children} 24 |
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 |
12 |
13 | My App 14 | { 15 | !children && 16 |
17 | } 18 |
19 | Username 20 | 21 |
22 |
23 | {children} 24 |
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 |
23 | 24 | Tools 25 | 26 | 27 | Books 28 | 29 | ... 30 |
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 | 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 |
    28 | / {' '} 29 | {' '} 30 | 31 |
    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 |
    28 | / {' '} 29 | {' '} 30 | 31 |
    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 |
    28 | / {' '} 29 | {' '} 30 | 31 |
    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(); 39 | res.status(page.status).send('\n' + html); 40 | }); 41 | 42 | server.listen(port, () => console.log( 43 | `Node.js server is listening at http://localhost:${port}/` 44 | )); 45 | -------------------------------------------------------------------------------- /Chapter 09/B05226_09_Code/src/tests/tests_helper.js: -------------------------------------------------------------------------------- 1 | import {JSDOM} from 'jsdom'; 2 | import jquery from 'jquery'; 3 | import TestUtils from 'react-dom/test-utils'; // ES6 4 | import ReactDOM from 'react-dom'; 5 | import chai, {expect} from 'chai'; 6 | import React from 'react'; 7 | import {Provider} from 'react-redux'; 8 | import {createStore} from 'redux'; 9 | import chaiJquery from 'chai-jquery'; 10 | 11 | // Set up testing environment to run like a browser in the command line 12 | const dom = new JSDOM(''); 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 | ![book](https://dl.dropboxusercontent.com/u/16006521/learning-isomorphic-web-application-development.png) 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 | ![book](https://dl.dropboxusercontent.com/u/16006521/learning-isomorphic-web-application-development.png) 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 | ![book](https://dl.dropboxusercontent.com/u/16006521/learning-isomorphic-web-application-development.png) 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 | ![book](https://dl.dropboxusercontent.com/u/16006521/learning-isomorphic-web-application-development.png) 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 | ![book](https://dl.dropboxusercontent.com/u/16006521/learning-isomorphic-web-application-development.png) 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 | }); --------------------------------------------------------------------------------