From 6cf01c496d40ef134099eb394643e646e5e2ff82 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Sat, 21 Apr 2018 16:50:05 -0700 Subject: [PATCH] Upgrade Gatsbygram MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This proved fairly difficult — Gatsbygram's modal architecture is always a good canary in the coalmine for ensuring Gatsby's architecture is flexible. It ended up being quite elegant though: * Used to load the image metadata into the Modal component so it could loop through the images. * Exposed through the Gatsby package so that the layout could render the index page underneath the modal when it is showing * Use around the Index/Modal components so that the Index page component didn't need rendered to the DOM again * To detect if this was the initial render, I implemented onInitialClientRender and set a global on the window so that the post template component would know *not* to use the modal if the user went directly to a post page. --- examples/gatsbygram/.babelrc | 4 - examples/gatsbygram/gatsby-browser.js | 4 + examples/gatsbygram/gatsby-config.js | 6 + examples/gatsbygram/package.json | 35 +-- examples/gatsbygram/src/components/modal.js | 191 ++++++++-------- examples/gatsbygram/src/components/post.js | 1 + examples/gatsbygram/src/html.js | 79 ------- examples/gatsbygram/src/layouts/index.js | 112 ++++----- examples/gatsbygram/src/pages/about.js | 63 ++--- examples/gatsbygram/src/pages/index.js | 215 +++++++++--------- .../gatsbygram/src/templates/post-page.js | 18 +- examples/gatsbygram/src/utils/typography.js | 4 +- .../gatsby/cache-dir/component-renderer.js | 148 ------------ .../gatsby-browser-entry.js} | 22 +- packages/gatsby/cache-dir/json-store.js | 75 +++--- packages/gatsby/cache-dir/production-app.js | 8 +- packages/gatsby/cache-dir/root.js | 28 ++- packages/gatsby/cache-dir/socketIo.js | 52 +++-- packages/gatsby/package.json | 1 - packages/gatsby/src/utils/webpack.config.js | 3 + 20 files changed, 446 insertions(+), 623 deletions(-) delete mode 100644 examples/gatsbygram/.babelrc delete mode 100644 examples/gatsbygram/src/html.js delete mode 100644 packages/gatsby/cache-dir/component-renderer.js rename packages/gatsby/{src/browser.js => cache-dir/gatsby-browser-entry.js} (55%) diff --git a/examples/gatsbygram/.babelrc b/examples/gatsbygram/.babelrc deleted file mode 100644 index a8b9b8bbcd312..0000000000000 --- a/examples/gatsbygram/.babelrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "presets": ['react', 'es2015', 'stage-1'], - "plugins": ['add-module-exports'] -} diff --git a/examples/gatsbygram/gatsby-browser.js b/examples/gatsbygram/gatsby-browser.js index 6a5fd30a630c0..481872938425e 100644 --- a/examples/gatsbygram/gatsby-browser.js +++ b/examples/gatsbygram/gatsby-browser.js @@ -9,3 +9,7 @@ exports.shouldUpdateScroll = args => { return false } } + +exports.onInitialClientRender = () => { + window.___GATSBYGRAM_INITIAL_RENDER_COMPLETE = true +} diff --git a/examples/gatsbygram/gatsby-config.js b/examples/gatsbygram/gatsby-config.js index 796b0e3a16acc..a20d0a555ce32 100644 --- a/examples/gatsbygram/gatsby-config.js +++ b/examples/gatsbygram/gatsby-config.js @@ -67,5 +67,11 @@ module.exports = { trackingId: `UA-91652198-1`, }, }, + { + resolve: `gatsby-plugin-typography`, + options: { + pathToConfigModule: `src/utils/typography`, + }, + }, ], } diff --git a/examples/gatsbygram/package.json b/examples/gatsbygram/package.json index 5c1da0b7901c8..5e8a765deffc2 100644 --- a/examples/gatsbygram/package.json +++ b/examples/gatsbygram/package.json @@ -5,30 +5,35 @@ "version": "1.0.0", "author": "Kyle Mathews ", "dependencies": { - "gatsby": "latest", - "gatsby-image": "^1.0.5", - "gatsby-plugin-glamor": "^1.6.8", - "gatsby-plugin-google-analytics": "^1.0.8", - "gatsby-plugin-manifest": "^1.0.8", - "gatsby-plugin-offline": "^1.0.9", - "gatsby-plugin-sharp": "^1.6.8", - "gatsby-source-filesystem": "^1.5.2", - "gatsby-transformer-json": "^1.0.8", - "gatsby-transformer-sharp": "^1.6.8", + "core-js": "^2.5.5", + "gatsby": "canary", + "gatsby-image": "canary", + "gatsby-plugin-glamor": "canary", + "gatsby-plugin-google-analytics": "canary", + "gatsby-plugin-manifest": "canary", + "gatsby-plugin-offline": "canary", + "gatsby-plugin-sharp": "canary", + "gatsby-plugin-typography": "^2.1.0-alpha.e9c3027b", + "gatsby-source-filesystem": "canary", + "gatsby-transformer-json": "canary", + "gatsby-transformer-sharp": "canary", + "glamor": "^2.20.40", "instagram-screen-scrape": "^2.0.0", "lodash": "^4.16.4", "mkdirp": "^0.5.1", "mousetrap": "^1.6.0", - "progress": "^1.1.8", + "progress": "^2.0.0", "prop-types": "^15.5.8", + "react": "^16.3.2", + "react-dom": "^16.3.2", "react-gravatar": "^2.6.1", "react-icons": "^2.2.3", - "react-modal": "^1.7.6", - "react-typography": "^0.15.0", + "react-modal": "^3.4.2", + "react-typography": "^0.16.13", "request": "^2.79.0", "slug": "^0.9.1", - "typeface-space-mono": "^0.0.22", - "typography": "^0.15.0" + "typeface-space-mono": "0.0.54", + "typography": "^0.16.6" }, "keywords": [ "gatsby" diff --git a/examples/gatsbygram/src/components/modal.js b/examples/gatsbygram/src/components/modal.js index ad5d4adb0376a..0fff2ec92ca98 100644 --- a/examples/gatsbygram/src/components/modal.js +++ b/examples/gatsbygram/src/components/modal.js @@ -6,15 +6,16 @@ import Close from "react-icons/lib/md/close" import findIndex from "lodash/findIndex" import mousetrap from "mousetrap" import * as PropTypes from "prop-types" -import { navigateTo } from "gatsby" +import { navigateTo, StaticQuery } from "gatsby" import { rhythm } from "../utils/typography" +let posts + class GatsbyGramModal extends React.Component { static propTypes = { isOpen: PropTypes.bool, location: PropTypes.object.isRequired, - posts: PropTypes.array.isRequired, } componentDidMount() { @@ -32,7 +33,7 @@ class GatsbyGramModal extends React.Component { findCurrentIndex() { let index index = findIndex( - this.props.posts, + posts, post => post.id === this.props.location.pathname.split(`/`)[1] ) @@ -45,7 +46,6 @@ class GatsbyGramModal extends React.Component { } const currentIndex = this.findCurrentIndex() if (currentIndex || currentIndex === 0) { - const posts = this.props.posts let nextPost // Wrap around if at end. if (currentIndex + 1 === posts.length) { @@ -63,7 +63,6 @@ class GatsbyGramModal extends React.Component { } const currentIndex = this.findCurrentIndex() if (currentIndex || currentIndex === 0) { - const posts = this.props.posts let previousPost // Wrap around if at start. if (currentIndex === 0) { @@ -77,94 +76,106 @@ class GatsbyGramModal extends React.Component { render() { return ( - navigateTo(`/`)} - style={{ - overlay: { - position: `fixed`, - top: 0, - left: 0, - right: 0, - bottom: 0, - backgroundColor: `rgba(0, 0, 0, 0.75)`, - }, - content: { - position: `absolute`, - border: `none`, - background: `none`, - padding: 0, - top: 0, - bottom: 0, - right: 0, - left: 0, - overflow: `auto`, - WebkitOverflowScrolling: `touch`, - }, - }} - contentLabel="Modal" - > -
navigateTo(`/`)} - css={{ - display: `flex`, - position: `relative`, - height: `100vh`, - }} - > -
- this.previous(e)} - /> - {this.props.children({ - location: { pathname: this.props.location.pathname }, - })} - { + if (!posts) { + posts = data.allPostsJson.edges.map(e => e.node) + } + return ( + navigateTo(`/`)} + style={{ + overlay: { + position: `fixed`, + top: 0, + left: 0, + right: 0, + bottom: 0, + backgroundColor: `rgba(0, 0, 0, 0.75)`, + }, + content: { + position: `absolute`, + border: `none`, + background: `none`, + padding: 0, + top: 0, + bottom: 0, + right: 0, + left: 0, + overflow: `auto`, + WebkitOverflowScrolling: `touch`, + }, }} - onClick={e => this.next(e)} - /> -
- navigateTo(`/`)} - css={{ - cursor: `pointer`, - color: `rgba(255,255,255,0.8)`, - fontSize: `30px`, - position: `absolute`, - top: rhythm(1 / 4), - right: rhythm(1 / 4), - }} - /> -
-
+ contentLabel="Modal" + > +
navigateTo(`/`)} + css={{ + display: `flex`, + position: `relative`, + height: `100vh`, + }} + > +
+ this.previous(e)} + /> + {this.props.children} + this.next(e)} + /> +
+ navigateTo(`/`)} + css={{ + cursor: `pointer`, + color: `rgba(255,255,255,0.8)`, + fontSize: `30px`, + position: `absolute`, + top: rhythm(1 / 4), + right: rhythm(1 / 4), + }} + /> +
+ + ) + }} + /> ) } } export default GatsbyGramModal - -export const modalFragment = graphql` - fragment Modal_posts on PostsJson { - id - } -` diff --git a/examples/gatsbygram/src/components/post.js b/examples/gatsbygram/src/components/post.js index 680770f3c673c..d7f1d975e9b19 100644 --- a/examples/gatsbygram/src/components/post.js +++ b/examples/gatsbygram/src/components/post.js @@ -2,6 +2,7 @@ import * as PropTypes from "prop-types" import React from "react" import HeartIcon from "react-icons/lib/fa/heart" import { Link } from "gatsby" +import Img from "gatsby-image" import { rhythm, scale } from "../utils/typography" import presets from "../utils/presets" diff --git a/examples/gatsbygram/src/html.js b/examples/gatsbygram/src/html.js deleted file mode 100644 index 18005bc869e30..0000000000000 --- a/examples/gatsbygram/src/html.js +++ /dev/null @@ -1,79 +0,0 @@ -import React, { Component } from "react" -import { TypographyStyle } from "react-typography" -import logo from "!file-loader!../static/images/logo.png" -import * as PropTypes from "prop-types" -import typography from "./utils/typography" - -let stylesStr -if (process.env.NODE_ENV === `production`) { - try { - stylesStr = require(`!raw-loader!../public/styles.css`) - } catch (e) { - console.log(e) - } -} - -const propTypes = { - headComponents: PropTypes.node.isRequired, - body: PropTypes.node.isRequired, - postBodyComponents: PropTypes.node.isRequired, -} - -class Html extends Component { - render() { - let css - if (process.env.NODE_ENV === `production`) { - css = ( - - -
- {this.props.postBodyComponents} - - - ) - } -} - -Html.propTypes = propTypes - -module.exports = Html diff --git a/examples/gatsbygram/src/layouts/index.js b/examples/gatsbygram/src/layouts/index.js index fdb4811d6ba0b..7b6dfeb55d82a 100644 --- a/examples/gatsbygram/src/layouts/index.js +++ b/examples/gatsbygram/src/layouts/index.js @@ -1,78 +1,77 @@ import * as PropTypes from "prop-types" import React from "react" import CameraIcon from "react-icons/lib/fa/camera-retro" -import { Link } from "gatsby" +import { Link, PageRenderer } from "gatsby" // Load the css for the Space Mono font. import "typeface-space-mono" import { rhythm, scale } from "../utils/typography" import presets from "../utils/presets" -import Modal from "../components/modal" -class DefaultLayout extends React.Component { +let Modal +import("../components/modal").then(modal => { + Modal = modal.default +}) + +let windowWidth + +class Layout extends React.Component { static propTypes = { location: PropTypes.object.isRequired, - children: PropTypes.func, - } - static childContextTypes = { - setPosts: PropTypes.func, - } - getChildContext() { - return { - setPosts: posts => { - this.posts = posts - }, - } + isModal: PropTypes.bool, } componentDidMount() { // Create references to html/body elements - this.htmlElement = document.querySelector(`html`) - this.bodyElement = document.querySelector(`body`) - - // Cache the window width. - this.windowWidth = window.innerWidth + // this.htmlElement = document.querySelector(`html`) + // this.bodyElement = document.querySelector(`body`) + // // Cache the window width. + // windowWidth = window.innerWidth } componentWillReceiveProps(nextProps) { // if we're changing to a non-homepage page, put things in // a modal (unless we're on mobile). - if ( - nextProps.location.pathname !== `/` && - nextProps.location.pathname !== `/about/` && - this.windowWidth > 750 - ) { - // Freeze the background from scrolling. - this.htmlElement.style.overflow = `hidden` - this.bodyElement.style.overflow = `hidden` - - // Always set overflow-y to scroll so the scrollbar stays visible avoiding - // weird jumping. - this.htmlElement.style.overflowY = `scroll` - } else { - // Otherwise we're navigating back home so delete old home so the - // modal can be destroyed. - delete this.modalBackgroundChildren - this.htmlElement.style.overflow = `visible` - this.bodyElement.style.overflow = `visible` - - // Always set overflow-y to scroll so the scrollbar stays visible avoiding - // weird jumping. - this.htmlElement.style.overflowY = `scroll` - } + // if (windowWidth > 750) { + // // Freeze the background from scrolling. + // this.htmlElement.style.overflow = `hidden` + // this.bodyElement.style.overflow = `hidden` + // // Always set overflow-y to scroll so the scrollbar stays visible avoiding + // // weird jumping. + // this.htmlElement.style.overflowY = `scroll` + // } else { + // // Otherwise we're navigating back home so delete old home so the + // // modal can be destroyed. + // delete this.modalBackgroundChildren + // this.htmlElement.style.overflow = `visible` + // this.bodyElement.style.overflow = `visible` + // // Always set overflow-y to scroll so the scrollbar stays visible avoiding + // // weird jumping. + // this.htmlElement.style.overflowY = `scroll` + // } } render() { const { location } = this.props let isModal = false - if ( - this.props.location.pathname !== `/` && - this.props.location.pathname !== `/about/` && - this.windowWidth > 750 - ) { + if (!windowWidth && typeof window !== `undefined`) { + windowWidth = window.innerWidth + } + if (this.props.isModal && windowWidth > 750) { isModal = true } + if (isModal && Modal) { + return ( + + + + {this.props.children} + + + ) + } + return (
-
- {isModal - ? this.props.children({ - ...this.props, - location: { pathname: `/` }, - }) - : this.props.children()} -
- -
- {isModal && ( - - {this.props.children} - - )} -
+ {this.props.children}
) } } -export default DefaultLayout +export default Layout diff --git a/examples/gatsbygram/src/pages/about.js b/examples/gatsbygram/src/pages/about.js index 882e754d78351..39fd0bd519d92 100644 --- a/examples/gatsbygram/src/pages/about.js +++ b/examples/gatsbygram/src/pages/about.js @@ -1,39 +1,42 @@ import React from "react" import { rhythm } from "../utils/typography" +import Layout from "../layouts" class About extends React.Component { render() { return ( -
-

About Gatsbygram

-

- Gatsbygram is an example website built with the JavaScript web - framework - {` `} - - Gatsby - - . -

-

- The code for the site lives at{` `} - - https://github.com/gatsbyjs/gatsby/tree/master/examples/gatsbygram - -

-

- - Read a case study on how Gatsbygram was built - -

-
+ +
+

About Gatsbygram

+

+ Gatsbygram is an example website built with the JavaScript web + framework + {` `} + + Gatsby + + . +

+

+ The code for the site lives at{` `} + + https://github.com/gatsbyjs/gatsby/tree/master/examples/gatsbygram + +

+

+ + Read a case study on how Gatsbygram was built + +

+
+
) } } diff --git a/examples/gatsbygram/src/pages/index.js b/examples/gatsbygram/src/pages/index.js index 1020e3254f396..469317ca101e2 100644 --- a/examples/gatsbygram/src/pages/index.js +++ b/examples/gatsbygram/src/pages/index.js @@ -6,6 +6,7 @@ import { rhythm, scale } from "../utils/typography" import presets from "../utils/presets" import Avatar from "../components/Avatar" import Post from "../components/post" +import Layout from "../layouts" // This would normally be in a Redux store or some other global data store. if (typeof window !== `undefined`) { @@ -20,9 +21,6 @@ class Index extends React.Component { allPostsJson: PropTypes.object, }), } - static contextTypes = { - setPosts: PropTypes.func, - } constructor() { super() @@ -68,129 +66,129 @@ class Index extends React.Component { const posts = allPostsJson.edges.map(e => e.node) - this.context.setPosts(posts) - user = user.edges[0].node return ( -
- {/* user profile */} +
+ {/* user profile */}
- -
-
-

- {user.username} -

-

- {posts.length} posts - 192k followers -

-
-
- {/* posts */} - {chunk(posts.slice(0, this.state.postsToShow), 3).map((chunk, i) => ( -
- {chunk.map(node => ( - this.setState({ activePost: post })} - /> - ))} + +
+
+

+ {user.username} +

+

+ {posts.length} posts + 192k followers +

+
- ))} - {!this.state.showingMore && ( - ( +
+ {chunk.map(node => ( + this.setState({ activePost: post })} + /> + ))} +
+ ))} + {!this.state.showingMore && ( +
{ - this.setState({ - postsToShow: this.state.postsToShow + 12, - showingMore: true, - }) - }} - > - Load More - - )} - + padding: rhythm(1 / 2), + width: `calc(100vw - ${rhythm(1)})`, + marginLeft: rhythm(0.5), + marginRight: rhythm(0.5), + marginBottom: rhythm(0.5), + marginTop: rhythm(0.5), + [presets.Tablet]: { + borderRadius: `100%`, + margin: `0 auto`, + marginBottom: rhythm(1.5), + marginTop: rhythm(1.5), + padding: rhythm(1), + height: rhythm(5), + width: rhythm(5), + lineHeight: rhythm(3), + textAlign: `center`, + }, + }} + onClick={() => { + this.setState({ + postsToShow: this.state.postsToShow + 12, + showingMore: true, + }) + }} + > + Load More + + )} + + ) } } @@ -215,7 +213,6 @@ export const pageQuery = graphql` weeksAgo: time(difference: "weeks") ...Post_details ...PostDetail_details - ...Modal_posts } } } diff --git a/examples/gatsbygram/src/templates/post-page.js b/examples/gatsbygram/src/templates/post-page.js index a5e5cbf018c53..877e23af51b60 100644 --- a/examples/gatsbygram/src/templates/post-page.js +++ b/examples/gatsbygram/src/templates/post-page.js @@ -1,6 +1,7 @@ import * as PropTypes from "prop-types" import React from "react" import PostDetail from "../components/post-detail" +import Layout from "../layouts" class PostTemplate extends React.Component { static propTypes = { @@ -9,10 +10,21 @@ class PostTemplate extends React.Component { }), } render() { + let isModal = false + // We don't want to show the modal if a user navigates + // directly to a post so if this code is running on Gatsby's + // initial render then we don't show the modal, otherwise we + // do. + if ( + typeof window !== `undefined` && + window.___GATSBYGRAM_INITIAL_RENDER_COMPLETE + ) { + isModal = true + } return ( - // PostDetail is used for this detail page and - // also in the modal. - + + + ) } } diff --git a/examples/gatsbygram/src/utils/typography.js b/examples/gatsbygram/src/utils/typography.js index ec09236449fee..05aa60be00d7d 100644 --- a/examples/gatsbygram/src/utils/typography.js +++ b/examples/gatsbygram/src/utils/typography.js @@ -36,4 +36,6 @@ if (process.env.NODE_ENV !== `production`) { typography.injectStyles() } -module.exports = typography +export default typography +export const scale = typography.scale +export const rhythm = typography.rhythm diff --git a/packages/gatsby/cache-dir/component-renderer.js b/packages/gatsby/cache-dir/component-renderer.js deleted file mode 100644 index 2ac12f08f62e7..0000000000000 --- a/packages/gatsby/cache-dir/component-renderer.js +++ /dev/null @@ -1,148 +0,0 @@ -import React, { createElement } from "react" -import PropTypes from "prop-types" -import loader, { publicLoader } from "./loader" -import emitter from "./emitter" -import { apiRunner } from "./api-runner-browser" -import shallowCompare from "shallow-compare" - -// Pass pathname in as prop. -// component will try fetching resources. If they exist, -// will just render, else will render null. -class ComponentRenderer extends React.Component { - constructor(props) { - super() - let location = props.location - - // Set the pathname for 404 pages. - if (!loader.getPage(location.pathname)) { - location = Object.assign({}, location, { - pathname: `/404.html`, - }) - } - - this.state = { - location, - pageResources: loader.getResourcesForPathname(location.pathname), - } - } - - componentWillReceiveProps(nextProps) { - // During development, always pass a component's JSON through so graphql - // updates go through. - if (process.env.NODE_ENV !== `production`) { - if ( - nextProps && - nextProps.pageResources && - nextProps.pageResources.json - ) { - this.setState({ pageResources: nextProps.pageResources }) - } - } - if (this.state.location.pathname !== nextProps.location.pathname) { - const pageResources = loader.getResourcesForPathname( - nextProps.location.pathname - ) - if (!pageResources) { - let location = nextProps.location - - // Set the pathname for 404 pages. - if (!loader.getPage(location.pathname)) { - location = Object.assign({}, location, { - pathname: `/404.html`, - }) - } - - // Page resources won't be set in cases where the browser back button - // or forward button is pushed as we can't wait as normal for resources - // to load before changing the page. - loader.getResourcesForPathname(location.pathname, pageResources => { - this.setState({ - location, - pageResources, - }) - }) - } else { - this.setState({ - location: nextProps.location, - pageResources, - }) - } - } - } - - componentDidMount() { - // Listen to events so when our page gets updated, we can transition. - // This is only useful on delayed transitions as the page will get rendered - // without the necessary page resources and then re-render once those come in. - emitter.on(`onPostLoadPageResources`, e => { - if ( - loader.getPage(this.state.location.pathname) && - e.page.path === loader.getPage(this.state.location.pathname).path - ) { - this.setState({ pageResources: e.pageResources }) - } - }) - } - - shouldComponentUpdate(nextProps, nextState) { - // 404 - if (!nextState.pageResources) { - return true - } - // Check if the component or json have changed. - if (!this.state.pageResources && nextState.pageResources) { - return true - } - if ( - this.state.pageResources.component !== nextState.pageResources.component - ) { - return true - } - - if (this.state.pageResources.json !== nextState.pageResources.json) { - return true - } - - // Check if location has changed on a page using internal routing - // via matchPath configuration. - if ( - this.state.location.key !== nextState.location.key && - nextState.pageResources.page && - (nextState.pageResources.page.matchPath || - nextState.pageResources.page.path) - ) { - return true - } - - return shallowCompare(this, nextProps, nextState) - } - - render() { - const pluginResponses = apiRunner(`replaceComponentRenderer`, { - props: { ...this.props, pageResources: this.state.pageResources }, - loader: publicLoader, - }) - const replacementComponent = pluginResponses[0] - // If page. - if (this.props.isPage) { - if (this.state.pageResources) { - return ( - replacementComponent || - createElement(this.state.pageResources.component, { - ...this.props, - ...this.state.pageResources.json, - }) - ) - } - } else { - return null - } - } -} - -ComponentRenderer.propTypes = { - isPage: PropTypes.bool, - location: PropTypes.object, -} - -export default ComponentRenderer diff --git a/packages/gatsby/src/browser.js b/packages/gatsby/cache-dir/gatsby-browser-entry.js similarity index 55% rename from packages/gatsby/src/browser.js rename to packages/gatsby/cache-dir/gatsby-browser-entry.js index cc98b2d1f860d..1bee9b2191ffd 100644 --- a/packages/gatsby/src/browser.js +++ b/packages/gatsby/cache-dir/gatsby-browser-entry.js @@ -1,5 +1,18 @@ import React from "react" import Link, { withPrefix, navigateTo } from "gatsby-link" +import pages from "./pages.json" +import loader from "./loader" +import JSONStore from "./json-store" + +const PageRenderer = ({ location }) => { + const pageResources = loader.getResourcesForPathname(location.pathname) + const isPage = !!(pageResources && pageResources.component) + return React.createElement(JSONStore, { + pages, + location, + pageResources, + }) +} const StaticQueryContext = React.createContext({}) @@ -21,4 +34,11 @@ const StaticQuery = props => ( ) -export { Link, withPrefix, navigateTo, StaticQueryContext, StaticQuery } +export { + Link, + withPrefix, + navigateTo, + StaticQueryContext, + StaticQuery, + PageRenderer, +} diff --git a/packages/gatsby/cache-dir/json-store.js b/packages/gatsby/cache-dir/json-store.js index b96351e1e00f4..5117b5709863a 100644 --- a/packages/gatsby/cache-dir/json-store.js +++ b/packages/gatsby/cache-dir/json-store.js @@ -3,18 +3,12 @@ import { Route } from "react-router-dom" import omit from "lodash/omit" import get from "lodash/get" -import ComponentRenderer from "./component-renderer" +import PageRenderer from "./page-renderer" import syncRequires from "./sync-requires" import { StaticQueryContext } from "gatsby" import socketIo, { getStaticQueryData, getPageQueryData } from "./socketIo" -const getPathFromProps = props => { - if (props.isPage) { - return get(props.pageResources, `page.path`) - } else { - return `/dev-404-page/` - } -} +const getPathFromProps = props => get(props.pageResources, `page.path`) class JSONStore extends React.Component { constructor(props) { @@ -24,24 +18,32 @@ class JSONStore extends React.Component { pageQueryData: getPageQueryData(), path: null, } - this.socket = socketIo() + if (process.env.NODE_ENV !== `production`) { + this.socket = socketIo() + } } handleMittEvent = (type, event) => { - this.setState({ - staticQueryData: getStaticQueryData(), - pageQueryData: getPageQueryData(), - }) + if (process.env.NODE_ENV !== `production`) { + this.setState({ + staticQueryData: getStaticQueryData(), + pageQueryData: getPageQueryData(), + }) + } } componentDidMount() { - this.registerPath(getPathFromProps(this.props)) - ___emitter.on("*", this.handleMittEvent) + if (process.env.NODE_ENV !== `production`) { + this.registerPath(getPathFromProps(this.props)) + ___emitter.on("*", this.handleMittEvent) + } } componentWillUnmount() { - this.unregisterPath(this.state.path) - ___emitter.off("*", this.handleMittEvent) + if (process.env.NODE_ENV !== `production`) { + this.unregisterPath(this.state.path) + ___emitter.off("*", this.handleMittEvent) + } } componentWillReceiveProps(nextProps) { @@ -55,43 +57,32 @@ class JSONStore extends React.Component { } registerPath(path) { - this.setState({ path }) - this.socket.emit(`registerPath`, path) + if (process.env.NODE_ENV !== `production`) { + this.setState({ path }) + this.socket.emit(`registerPath`, path) + } } unregisterPath(path) { - this.setState({ path: null }) - this.socket.emit(`unregisterPath`, path) + if (process.env.NODE_ENV !== `production`) { + this.setState({ path: null }) + this.socket.emit(`unregisterPath`, path) + } } render() { - const { isPage, pages, pageResources } = this.props + const { pages, pageResources } = this.props const data = this.state.pageQueryData[this.state.path] const propsWithoutPages = omit(this.props, `pages`) if (!data) { return
} - if (isPage) { - return ( - - - - ) - } else { - const dev404Page = pages.find(p => /^\/dev-404-page/.test(p.path)) - return createElement(Route, { - key: `404-page`, - component: props => - createElement( - syncRequires.components[dev404Page.componentChunkName], - { - ...propsWithoutPages, - ...data, - } - ), - }) - } + return ( + + + + ) } } diff --git a/packages/gatsby/cache-dir/production-app.js b/packages/gatsby/cache-dir/production-app.js index 28cdc941b7f14..c5d29fdfb5ad5 100644 --- a/packages/gatsby/cache-dir/production-app.js +++ b/packages/gatsby/cache-dir/production-app.js @@ -11,7 +11,7 @@ import emitter from "./emitter" window.___emitter = emitter import pages from "./pages.json" import redirects from "./redirects.json" -import ComponentRenderer from "./component-renderer" +import PageRenderer from "./page-renderer" import asyncRequires from "./async-requires" import loader from "./loader" loader.addPagesArray(pages) @@ -150,8 +150,6 @@ apiRunnerAsync(`onClientEntry`).then(() => { const AltRouter = apiRunner(`replaceRouterComponent`, { history })[0] - const ComponentRendererWithRouter = withRouter(ComponentRenderer) - loader.getResourcesForPathname(window.location.pathname, () => { let pathPrefix = `/` if (__PREFIX_PATHS__) { @@ -173,12 +171,12 @@ apiRunnerAsync(`onClientEntry`).then(() => { attachToHistory(routeProps.history) if (loader.getPage(routeProps.location.pathname)) { - return createElement(ComponentRenderer, { + return createElement(PageRenderer, { isPage: true, ...routeProps, }) } else { - return createElement(ComponentRenderer, { + return createElement(PageRenderer, { isPage: true, location: { pathname: `/404.html` }, }) diff --git a/packages/gatsby/cache-dir/root.js b/packages/gatsby/cache-dir/root.js index 9a287e0409572..28d97a4d227e4 100644 --- a/packages/gatsby/cache-dir/root.js +++ b/packages/gatsby/cache-dir/root.js @@ -6,7 +6,7 @@ import { apiRunner } from "./api-runner-browser" import syncRequires from "./sync-requires" import pages from "./pages.json" import redirects from "./redirects.json" -import ComponentRenderer from "./component-renderer" +import PageRenderer from "./page-renderer" import loader from "./loader" import { hot } from "react-hot-loader" import JSONStore from "./json-store" @@ -141,12 +141,26 @@ const Root = () => const { pathname } = routeProps.location const pageResources = loader.getResourcesForPathname(pathname) const isPage = !!(pageResources && pageResources.component) - return createElement(JSONStore, { - isPage, - pages, - ...routeProps, - pageResources, - }) + if (isPage) { + return createElement(JSONStore, { + pages, + ...routeProps, + pageResources, + }) + } else { + const dev404Page = pages.find(p => /^\/dev-404-page/.test(p.path)) + return createElement(Route, { + key: `404-page`, + component: props => + createElement( + syncRequires.components[dev404Page.componentChunkName], + { + ...propsWithoutPages, + ...data, + } + ), + }) + } }, }) ) diff --git a/packages/gatsby/cache-dir/socketIo.js b/packages/gatsby/cache-dir/socketIo.js index b14ae436cf693..8f0008ba25842 100644 --- a/packages/gatsby/cache-dir/socketIo.js +++ b/packages/gatsby/cache-dir/socketIo.js @@ -9,32 +9,36 @@ export const getPageQueryData = () => pageQueryData export const getIsInitialized = () => isInitialized export default function socketIo() { - if (!socket) { - // Try to initialize web socket if we didn't do it already - try { - socket = io() - socket.on(`message`, msg => { - console.log(`====message received`, msg) - if (msg.type === `staticQueryResult`) { - staticQueryData = { - ...staticQueryData, - [msg.payload.id]: msg.payload.result, + if (process.env.NODE_ENV !== `production`) { + if (!socket) { + // Try to initialize web socket if we didn't do it already + try { + socket = io() + socket.on(`message`, msg => { + console.log(`====message received`, msg) + if (msg.type === `staticQueryResult`) { + staticQueryData = { + ...staticQueryData, + [msg.payload.id]: msg.payload.result, + } } - } - if (msg.type === `pageQueryResult`) { - pageQueryData = { - ...pageQueryData, - [msg.payload.id ? msg.payload.id : msg.payload.path]: msg.payload - .result, + if (msg.type === `pageQueryResult`) { + pageQueryData = { + ...pageQueryData, + [msg.payload.id ? msg.payload.id : msg.payload.path]: msg.payload + .result, + } } - } - if (msg.type && msg.payload) { - ___emitter.emit(msg.type, msg.payload) - } - }) - } catch (err) { - console.error(`Could not connect to socket.io on dev server.`) + if (msg.type && msg.payload) { + ___emitter.emit(msg.type, msg.payload) + } + }) + } catch (err) { + console.error(`Could not connect to socket.io on dev server.`) + } } + return socket + } else { + return null } - return socket } diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index cb7c0d3f3024a..6269fecb58317 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -6,7 +6,6 @@ "bin": { "gatsby": "./dist/bin/gatsby.js" }, - "browser": "dist/browser.js", "bugs": { "url": "https://github.com/gatsbyjs/gatsby/issues" }, diff --git a/packages/gatsby/src/utils/webpack.config.js b/packages/gatsby/src/utils/webpack.config.js index 93428f82ce218..dbff1cbe21d01 100644 --- a/packages/gatsby/src/utils/webpack.config.js +++ b/packages/gatsby/src/utils/webpack.config.js @@ -346,6 +346,9 @@ module.exports = async ( directoryPath(path.join(`src`, `node_modules`)), directoryPath(`node_modules`), ], + alias: { + gatsby$: directoryPath(path.join(`.cache`, `gatsby-browser-entry.js`)), + }, } }