-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Preview feature? #22
Comments
Did you figure it out? |
No. I haven't used gatsby-source-prismic, and won't unless I hear that the preview is possible. |
Hey @tremby, sorry for the late reply. From what I can tell, I don't see how Prismic's preview system can work with Gatsby's build system. If you have an idea of how this could work, please feel free to post some ideas in here. Prismic sends a preview token via HTTP that should be used as the ref when fetching the document data. This assumes a server exists that can retrieve that token, make a request to Prismic to fetch the document, and render the page using that document. Since Gatsby gathers all document data at build time, it does not have a way to grab the document preview. As an alternative, it would be possible to create a custom page in Gatsby that retrieves the ref in the URL query and makes the appropriate Prismic API calls to render the page. In other words, the page would not be static and would require making network calls directly to Prismic to fill in content areas. Ideally Prismic would allow querying for documents at the "Draft" level through the API without needing to receive the correct ref to do so. I.e. if we could request a preview ref on demand, creating a separate "staging" build of your site would be possible. This is similar to what Contentful does with its |
I'm aware of how Prismic's preview feature works -- I've used it front-end with the Prismic Javascript SDK and back-end with the PHP SDK in the past.
Yes, this is the sort of thing I had in mind. I imagine the Gatsby site handling the preview signal from Prismic and rendering the page all client-side. I don't know what sort of challenges this might entail -- perhaps none of the logic to turn a Prismic API response into data the Gatsby pages can render isn't bundled to the client side, for example. But this is what I'm asking about.
This isn't really valuable to me. The way I use Prismic (and the way I believe my clients use it) is to prepare changes and hit the "preview" button from the Prismic UI to view the preview, or to stage a bunch of changes as a release then hit the "preview" button to preview the entire release. Both ways use pass the ref to the website the normal "preview" way, and don't require a different endpoint to be set up. |
I am not 100% clear on how the preview feature works, so please correct me if anything I say is wrong. I see two ways this could be done: Provide a guide for a separate "Preview"/Drafts buildGatsby only pulls data at build time, so the only way to render the preview document data is to trigger a new build with that ref. This would require a server that can listen to the request from Prismic, grab the ref, and provide that ref to the source plugin via This should require minimal changes to the source plugin, but more documentation on how to set it up. Create a "dynamic" endpoint to display preview data using existing templatesSince Prismic will send a request to
If you changed the reference to I think this method gets pretty messy and makes your site highly dependent on a single service, but the benefit of having a live preview is nice. Any thoughts on either approach? |
The former probably isn't valuable to me, unless there was a really easy-to-deploy script for this I could put on AWS Lambda or something -- I wouldn't want to run a server -- and as long as it would be very fast to run. The latter approach seems more valuable and is more like what I had in mind, but it sounds like you have some reservations, and yes, it does look like it'd make building the site more complicated. |
This is also functionality I'm looking for. There's actually a somewhat comprehensive guide for doing preview buttons on a Prismic site here: https://prismic.io/docs/reactjs/beyond-the-api/in-website-preview Maybe we could do some kind of reverse engineering, to trigger preview builds? I'm experimenting with this plugin, along with netlify, which allows custom deployment contexts. I'm imagining something like this:
This might be a cumbersome work around, but you eliminate the need to update a state with your new data. I'll look in to this tomorrow, and report on any findings :) |
I've run into this issue as well. When you get Prismic previews working the way they're intended, it's really awesome for everyone (editors, approvers, devs, etc). I've done it either all on the front-end with a create-react-app SPA, and on the back-end as well. It's not too challenging in those environments because your code already knows how to talk to the API, so it just needs to do it with an extra ref parameter (and maybe disable some caching for the current session). The challenge for getting it to work with Gatsby is that you're being fed data from the GraphQL store and not directly requesting it from the API - so it's frozen in the state it was at during the last build. This is what makes it a static site and not just an SPA. Right now it seems like @angeloashmore is right. You either need to write separate logic to fetch the data for previews (this isn't really a great solution, too much duplicated code) or you need to rebuild the site static for each new preview ref (this might be possible with something like deploy previews on Netlify, but it's slow because Gastby needs to fetch & process all the data and render all the pages before the preview is available.) I don't think either solution is really all that great frankly. You either more than double your work for fetching prismic data (plus, add a bunch more opportunities for bugs to show up), or you make editors wait a few minutes before they can preview any changes (while simultaneously making your staging/continuous integration setups more complicated). This isn't really a unique problem to Gatsby - it's an issue with previews for static site generators in general (the fact that Gastby serves the logic and data separately makes it seem like it's closer than other static site generators... but it's really not because so much processing needs to happen to the data to enable the GraphQL stuff). Prismic also makes the problem more obvious than something like Contentful because they have such a dynamic preview system. The question I guess is: how can we improve on this situation. The Prismic team seems like they'd be willing to do work to support a solution if we could come up with one. Similarly, there has been some talk about preview functionality over in the Gatsby repository: If we look at other repositories for guidance we get some potential steps. Contentful basically uses a simplified preview model that serves all draft changes with a single preview key. Prismic could provide something similar by giving us an access key to pull content in from master+all releases (this is actually a complicated problem because releases can have conflicting changes - particularly if you're using experiments). That would let you set up a single preview environment, but you lose per-environment and per-document previews - which are a really nice features of Prismic. It also doesn't solve the problem of making editors wait a few minutes before the preview is ready to view (but at least they might not need to ask for it before the build kicks off?). The other thing Contentful provides is a sync API, which essentially lets to you diff the local data you have against server's copy, so you can pull down only what's changed since your last sync. This combined with some of the work that's been happening on the Gatsby side to enable new data to be loaded while running in develop mode might help improve the problem with preview speed - you don't need to re-build the javascript/css/image assets and you can only pull what's changed when re-building the data, so that should speed things up significantly. Of course that still requires a completely different hosting architecture for your preview environment (one that keeps the service running) but at least you don't have to write a bunch of new code. It seems like the ideal solution would be if Gatsby provided some kind of support for this kind of thing more directly. Perhaps some way for data at run time to be fetched directly from the appropriate APIs (potentially requiring those APIs to support GraphQL? or for the source plugins to support the translation from GraphQL queries into efficient API calls and reformat the responses) rather than needing the pre-processed static versions of the data that are built from a full content download. This would let you load a static placeholder "/preview" route that then switches to loading the preview data in dynamically and redirecting you to the final route client-side. This seems like a lot of work though and I wouldn't know where to start. It also gets rid of the benefits of being able to cache the page data you usually need at CDN edges, so it probably would need to be an option. Does anyone have better ideas? |
Also very keen for a preview feature, but (as @AdamPflug summed up well) I don't think it's worth doing until Gatsby has some way to refresh data without a full rebuild. That way you could run a dev/staging server and have Prismic call a webhook on save to refresh the data and do a partial rebuild to view previews. Not ideal, since it'd mean keeping a warm server running, but it'd just be for internal editors, and better than alternatives. Doing a full build of a site of any real size to preview every change isn't feasible IMO, and writing your own data layer sounds like an engineering headache that doesn't make sense in terms of effort/reward. Second issue linked above seems to be the one to follow for Gatsby refreshing data. |
Check out the I wonder if this could help at all. The endpoint is only available when using the built-in dev server, so I wonder how feasible it is to have it constantly running as a preview server. |
I think that's the best compromise - running the dev server as a staging env for previews. Not ideal, but it'd only be for internal editors, so better than nothing IMO. |
I came across this example site from Prismic that handles previews using the pre-v1 version of the source plugin: https://github.com/levimykel/gatsby-website/blob/87f21ddde60958b13893b41cc4aa41ea877d7141/src/templates/page.js
This works well because the API response from the preview token mirrors the data schema of the pre-v1 plugin. v1 changes the schema to add some additional processing, so it is not a 1-to-1 mapping anymore. But, we could still use the above method by running the API response through the same transformers the source plugin uses. We would just need to export/import the There are still some things to think about, like how does it handle different content types, and how would it map directly to the same accessors as through |
@angeloashmore yeah that's basically what I was suggesting above as the best we can do for now. I'd be awesome if support for something like that was built into gatsby, so source plugins could support both build time and run-time queries (not just useful for previews, but also for things like advanced filtering), and it would also probably play nicer with pages that need data from multiple sources. That way we could avoid writing duplicate query logic to handle those two cases. In the meantime, it sounds like the Prismic team is getting close to launching a beta of native GraphQL support for their API, which may help reduce some of the overhead of maintaining two copies of your query logic somewhat. |
Right now I have a sloppier solution that takes advantage of our Netlify account to only load preview pages in a password-protected version of our site. However, I'm handling data mapping to a common structure by having two different functions that get called depending on the source. |
@simplesessions how did you handle getting your previewed content out of the API at build time? I love deploying to Netlify but haven't figured out a good solution for previewing prismic stuff there because of the per-release refs that change all the time. Also, how are you triggering new builds? I thought he web-hooks were only for publish/archive events In other newsThe first stage of Prismic's native GraphQL support is in beta: With this in mind, I had a thought: would it be possible to write a higher order component that wraps page components to fetch the preview content for them dynamically when you have a preview cookie set? It would need to:
If we can extract all the complexities of having 2 code paths into a single HOC, then as long as that's solid it eliminates a lot of the drawbacks discussed above, and it probably doesn't require any additional support from the Gatsby core team to implement. To me this feels like an interesting approach, but I could be missing something (or it may end up being very difficult to implement in practice). I see the API something like this (the key is basically just he last line): import React from "react";
import prismicPreview from `gatsby-source-prismic`;
let ProductListPage= ({ data }) => {
const products = data.PrismicProductQuery.allPrismicProduct.edges;
return (
<div>
{products.map(({product}) =>
<div>
<h1>{product.data.name}</h1>
<div dangerouslySetInnerHTML={{ __html: product.data.description.html }} />
</div>
)}
</div>
);
};
export const query = graphql`
query PrismicProductQuery {
allPrismicProduct {
edges {
node {
id
data {
name
price
description {
html
}
}
}
}
}
}
`;
export default prismicPreview(ProductListPage, query); We'd still need to solve the problem of what to do with 404s (for net new pages as an example), but if feels like a step in the right direction? |
@AdamPflug Sorry, I somehow missed that you replied to this! I just used it in a hacky way by taking advantage of Netlify and deploying an instance of the site that's password-protected, includes a template that loads and parses the data, and exposes the API key. It works quickly and effectively, and am hesitant to lean towards any other options that trigger full on builds since it'll make the preview process for the content guys we work with kind of a slog. So yeah - for now, I'm exposing the access token and simply doing a fetch and parsing all the info :) |
Hey @simplesessions can you share your config/hack with the access token exposed for previews. Or are you saying that you are skipping the gatsby-source-prismic plugin all together? |
Stage 2 of native graphQL coming soon: https://www.youtube.com/watch?v=W-QWGw7Zb1c |
@birkir In my case I'm skipping gatsby-source-prismic altogether and just straight up using PrismicDOM. I avoid any sort of recompiling and the load time is super quick. Right now, I have it just straight up loading behind a password-protected Netlify instance, but looking to incorporate some lambda function to load everything. |
Thanks @simplesessions Here is my solution: withPrismicPreview.tsximport React from 'react';
import traverse from 'traverse';
import { get, isArray } from 'lodash';
import Prismic from 'prismic-javascript';
export function withPrismicPreview(Component) {
return class WrappedComponent extends React.Component {
state = {
data: this.props.data,
}
componentDidMount() {
this.setup();
}
async setup() {
const url = new URL(window.location.toString());
const data = { ...this.props.data };
const previewFlag = url.searchParams.get('preview');
if (previewFlag) {
// Get all prismicId's (unique)
const prismicIds = traverse(data).reduce(function(acc, x) {
if (this.key === 'prismicId' && acc.indexOf(this.parent.node.prismicId) === -1) {
acc.push(this.parent.node.prismicId);
}
return acc;
}, []);
// Warn possible missing prismicId's
if (prismicIds.length === 0) {
// tslint:disable-next-line no-console
console.warn('Preview did not find any `prismicId` keys in your graphql schema. '
+ 'Please add them to allow proper mapping.');
}
const api = await Prismic.getApi(`https://${process.env.GATSBY_PRISMIC_ENDPOINT}.cdn.prismic.io/api/v2`);
const previews = await Promise.all(prismicIds.map((prismicId) => api.getByID(prismicId)));
// Update the object with a match from preview (if available)
const updateWithPreview = (obj) => {
const preview = previews.find((p) => p.id === obj.prismicId);
return traverse(obj).map(function(x) {
if (this.key === 'dataString') {
this.update(JSON.stringify(preview.data));
}
if (this.key === 'raw' && isArray(x)) {
const paths = this.path.slice(0);
paths.pop();
this.update(get(preview, paths.join('.')), true);
}
if (this.isLeaf) {
const previewValue = get(preview, this.path.join('.'));
if (previewValue) {
this.update(previewValue);
}
}
});
};
// Traverse all objects that have `prismicId` in them
traverse(data).forEach(function(x) {
if (get(x, 'prismicId')) {
this.update(updateWithPreview(x));
}
});
// Set newly mapped data
this.setState({ data });
}
}
public render() {
const { data, ...passProps } = this.props;
return <Component data={this.state.data} {...passProps} />;
}
};
} pages/preview.jsximport React from 'react';
import Prismic from 'prismic-javascript';
import linkResolver from 'utils/linkResolver';
export default class PreviewPage extends React.Component {
componentDidMount() {
const url = new URL(window.location as any);
const token = url.searchParams.get('token');
if (token) {
Prismic.getApi(`https://${process.env.GATSBY_PRISMIC_ENDPOINT}.cdn.prismic.io/api/v2`)
.then((api) =>
api.previewSession(token, linkResolver, '/')
.then((pathname: string) => {
const now = new Date();
now.setHours(now.getHours() + 1);
document.cookie = `${Prismic.previewCookie}=${token}; expires=${now.toUTCString()}; path=/`;
url.searchParams.append('preview', 'true');
url.pathname = pathname;
window.location = url;
}),
);
}
}
render() {
return null;
}
} Usageimport React from 'react';
import { RichText } from 'prismic-reactjs';
import { withPrismicPreview } from 'utils/withPrismicPreview';
@withPrismicPreview
export default class HomePage extends React.PureComponent {
render() {
const content = JSON.parse(this.props.data.prismicPage.dataString);
return <h1>{RichText.asText(content.title)}</h1>;
// or using raw
return <h1>{RichText.asText(this.props.data.prismicPage.data.title.raw)}</h1>;
}
}
export const query = graphql`
prismicPage {
id
prismicId # necessery for previews
dataString
data {
title {
raw {
text
type
}
}
}
}
` (I removed typescript type annotations so pardon me if there is anything missing from the code snippets) |
Hello! It's Gabe from Prismic. We are currently working on another implementation of post {
mytitle:title
mysummary:summary
} We decided that in order for Prismic previews to work with Gatsby, users need a slightly more structured workflow, and plugin developers need to have access to requests in the browser APIs. Our proposed solution is a plugin ( The plugin works by surrounding every page in an This is an example of how import { extendApolloLink } from 'gatsby-apollo'
exports.onClientEntry = () => {
extendApolloLink(link => new ApolloLink(async (operation, forward) => {
if (condition) return forward(operation)
return liveQuery(operation)
})).concat(link)
} A typical developer's workflow:A page for loading the list of posts using the const Posts = () => (
<Query query={postsQuery}>
// Loading would be `true` while a live preview is loading,
// and the `Posts` template can handle it however it chooses.
{({ data, loading, error }) => data.prismic.allBlogPosts.map(post =>
<div>{ post.title }</div>
)}
</Query>
)
// `gql`, not `graphql`
const postsQuery = gql`{
prismic {
allBlogPosts {
title
summary
}
}
}`
export default Posts A page for loading a single post using the const Post = ({ data, loading, error }) => (
<div>{ data.prismic.blogPost.title }</div>
)
// This query need not be in this file. It can be decoupled for re-use.
// Normally Gatsby would need it here to connect this query to the props.
// Queries with variables (i.e. $uid) now must be compiled explicity.
const blogPostQuery = gql`
query BlogPost($lang: String, $uid: String) {
prismic {
blogPost(uid: $uid, lang: $lang) {
title
summary
}
}
}
`
// `graphql` HOC
export default graphql(blogPostQuery)(Post) In the browser, the plugin automatically adds the Queries with variable definitions no longer compiled via // Compile the `BlogPost` query with these 3 variations
compileQueryVariations({
query: 'BlogPost',
variations: [
{ lang: 'en-us', uid: 'post-1' },
{ lang: 'fr-fr', uid: 'post-1' },
{ lang: 'en-us', uid: 'post-2' },
],
})
// We create ONLY ONE PAGE to render any blog post.
// In production, infer the `lang` and `uid` variables from the URL.
createPage({
template: './src/components/Post.js',
matchPath: '/posts/:lang/:uid',
})
We could generate the graphql(`{
prismic {
allBlogPosts {
lang
uid
}
}
}`).map(result => result.data.prismic.allBlogPosts) This system allows queries to be decoupled from pages. The configuration for this plugin is one line: // In gatsby-config.js
{ resolve: 'gatsby-apollo' } I am planning to implement |
Yes, the points you mentioned are pain points but can be solved with restrictions and extra work. a) To overcome unpublished documents, that Gatsby would have to generate on build time, we can just have placeholder pages that can render the specific document type dynamically (/_preview/blog, /_preview/custom-type), through a custom linkResolver for preview. b) Not having a single source of truth is a very bad problem. For things like filtering and paging (where we don't want to create static pages for each possible scenario), we have to have two sources of truth. Same for preview, but renaming the fields that have prismicId as a child is fine, but other deeply nested fields will fail the mapping. That being said, the solution you proposed is a great addition to the Gatsby ecosystem and will enable a single source of truth for all source plugins that support the system. The only issue is exposing of secrets and stuff needed to fetch the data on the client. But there is no way to overcome that problem with Gatsby. Thanks Gabe. |
@birkir Thank you for your feedback. The "secrets needed to fetch the data" problem seems solvable in the case of Prismic previews. For normal fetching, data is retreived from the static file server. If a live query is required (for a blog post keyword search perhaps), you would have to change your Prismic settings to allow anyone access to the Master Ref. For preview fetching, prismic.js (or the gatsby plugin) will communicate with your repository "example.prismic.io" and will automatically authenticate your request for preview content if you are currently logged into that repository. No secrets spilled :) To perhaps clarify to people how our unpublished preview would work: When you navigate to And for pagination and filtering:
We would not want to use |
@krabbypattified Glad to see official support for Gatsby! Re: the Apollo method, it sounds like every page would be rendered client-side. Would the method you describe above be implemented in addition to statically rendering pages? |
@angeloashmore I am not 100% sure what you mean, but I will try my best to answer. I'll assume by "rendered client-side" you mean being able to dynamically respond to the URL and render live data. And by "statically rendering pages" you mean the normal Gatsby process where we fetch from the JSON files or inline the results of queries. To answer your question, the plugin doesn't interfere with anything. It simply adds a querying method ( Perhaps the example I provided was confusing? The example shows how you can create a page that will render your createPage({
template: './src/components/Post.js',
matchPath: '/posts/:lang/:uid',
}) And the Here is an example of another workflow for a list of posts (you could use the // In ./src/pages/posts.js
const Posts = () => (
<Query query={postsQuery}>
{({ data, loading, error }) => data.prismic.allBlogPosts.map(post =>
<div>{ prismic.allBlogPosts.map(p => <div>{p.title}</div>) }</div>
)}
</Query>
)
const postsQuery = gql`{
prismic {
allBlogPosts {
title
summary
}
}
}`
export default Posts I hope that answered your question, but please let me know if not. |
@krabbypattified I think the question is: do we get a fully pre-rendered HTML version of the page for the initial page load of This seems like a bummer because that pre-rendered HTML you usually get is one of Gatbsy's key advantages (optimized time to first contentful paint). By requiring 2 HTTP requests in series before you can even begin to generate the HTML client side and then query for all the required resources you really slow down that first page load. I agree with @birkir that there's probably another way to work around the "unpublished documents" problem (perhaps having some code on the 404 page that, when in preview mode, does a react-router redirect to the correct route, but this time renders client-side in live query mode). |
Haven't been following this too closely, but just wanted to quickly chime in to agree with @AdamPflug – anything that works against Gatsby's buildtime rendering of all pages would be a dealbreaker for most I imagine. That's really one of the key selling points of Gatsby over a more conventional React/SPA setup. |
Wanted to share my experience with prismic previews for the past couple of weeks. Limitations and constraintsMy idea is based around piggybacking onto existing graphql query responses and patching them. We have to add Field aliasingBecause of the implementation, we need to know the field's name to match them correctly. So it's fine to alias documents, but not fields within documents. # Good
blog: prismicBlog {
prismicId
data {
title
}
}
# Bad
prismicBlog {
prismicId
data {
title: heading
}
} gatsby-imageWhen using image sharper, include the actual Prismic image url and make sure the UI can fallback to that one if no localFile was found. myimage {
url # this one
localFile {
childImageSharp {
fixed(width:100, height:100) {
...GatsbyImageSharpFixed
}
}
}
} {myimage.localFile ? <Img fixed={myimage.localFile} /> : <img src={myimage.url} />} Because previews happen dynamically, gatsby hasn't processed the updated image with image-sharper, so the solution is to remove the localFile property and rely on the actual image url. Unpublished documentsI solved this problem by finding another published document of the same type, resolve its page and then swap the document id with the previewing document id. This only happens when the previewable document isn't already published So the only case when this fails is when no published type of the document exists. And guess what, Gatsby also crashes when this is the case, so not really an issue with my solution per se. so tldr;
If anyone has anything to add, let me know. I'll be creating an npm package with the updated solution and would to like to know more edge cases to support. |
@birkir I ended up tackling the image and aliasing in a slightly different way: |
@Dean177 Ok, that's a good idea. I just didn't bother to research if that was consistent, thanks for letting me know, will add! |
@AdamPflug Thank you for clarifying, you are absolutely right. That was my mistake to overlook pre-rendering HTML. The method I described (Apollo) is different than Gatsby's. It would require the website to have JavaScript enabled, and it would have to make 2 HTTP requests before the first meaningful paint. That is, unless Gatby's HTML pre-renderer is smart enough to compile a React component that uses Apollo queries. That would be so cool. That being said, pre-rendering HTML for each URL is only a great idea while the URL is the single, deterministic factor in the first meaningful paint. If there are other factors at play such as cookies, local storage, API requests, etc., this solution quickly falls apart. At best, the browser renders a flash of inaccurate content. On the surface, Gatsby's solution seems great. But to achieve this improved performance, Gatsby pulls a few hacks. It implements two routing systems: the static file server and the Reach router. The file server doubles as an HTML pre-renderer. These hacks are excusable for a website that fits the 100% static architecture, or "works without JavaScript," if you will. As soon as people begin to ask for features that aren't very static (live data, dynamic routes, preview content, etc.), the 100% static architecture falls apart. Any plugin designed to work around this design limitation is more or less a hack on top of a hack. On the other hand, we have systems like NextJS and Netlify that do not sacrifice architecture for performance. They do not force the model to fit the concept of a "works without JavaScript" file server. Plugins built on top of these systems are not hacks. In fact, there is no Prismic plugin required for these systems. Simply add Improving performance almost always adds complexity. Developers have to decide where that complexity makes sense. In the case of Gatsby, this complexity hurts me dearly. Perhaps I should also mention the elephant in the room - that an API request to Prismic is pretty darn fast. Since the requests are deterministic, they are permanently cached at our servers, our CDN, and your browser. (If you want to avoid the extra request to get the correct ref, you can keep the ref in local storage, or even hardcode it.) That means requests are as fast as (or faster than) requesting a file via GitHub Pages, Netlify, or some other file server. I want to help you all as best as I can. If
where should I focus my efforts instead? What is the best solution? What is the complexity of the Is the
solution comprehensive enough? I sincerely appreciate all of your contributions to this conversation, so please let me know if I have not addressed anything. I am only one person, so I may not have time to explore every idea myself. Your help is always appreciated. Gabe |
@krabbypattified It feels like you are making a lot of assumptions about the use cases that gatsby meets.
Having the url be the single deterministic factor for the first meaningful paint is not a severe restriction. Take a look at some of the sites from the showcase: https://www.gatsbyjs.org/showcase/ Marketing sites, blogs, landing pages. Those pages can still have content content that relies on cookies, localstorage or api requests, they can have placeholders or spinners whilst dynamic content is resolved.
There is a perfectly serviceible way to add completely dynamic content to gatsby apps:
I am perfectly ok with complexity living in the frameworks and plugins that I use.
It doesn't matter that your api is as fast as github pages. Its a request that each individual client doesn't need to make. One of the valuable parts of gatsby is that this requests happens once on our CI server. Its one fewer component in the live pipeline, a reduction in complexity, one less thing that can be slow or fail completely.
Initially, try to understand why people chose gatsby over the similar frameworks and why they are happy with those tradeoffs. Calling them hacks is not productive, people clearly get a lot of value from Gatsby. |
To clarify, I assumed this work was targeting the development server. After |
Seeing the example projects, I agree with you here:
I also agree with you here:
And I confess I may have confused "100% static" with Gatsby's implementation of it. Static is very powerful if done right. I trust it is the best solution for you and many others. Additionally, Gatsby is a great tool. However, I stand by my critique of Gatsby. It has the potential to become tremendously more valuable to developers. I call specific features "hacks," but perhaps I should elaborate on that. What I mean is that they add unneccessary restrictions and complexity to their framework by having, for example, a query mechanism that is not properly designed (described in my post above). Gatsby sees the problem, and v3 is attempting to solve it. For the moment, we do not have a v3. But Gatsby offers Node APIs and Browser APIs that make it possible to add features without having to submit a pull request. For example:
Thank you for the example projects. I saw them. The tradeoffs make sense. But I think calling Gatsby out on bad design is a necessary step for progress to be made (unless you were only criticizing my word choice). @Dean177 Thank you for your reply. From your other comment above, it seems you lean toward the |
@joseph-cloudthing Yes, all would be static after the build. He is referring to something like Jenkins. |
@krabbypattified thanks for your considered response, I admit I was partly critisizing the word choice. In this case I think I do lean towards the prismicId solution. Honestly Apollo with HTML pre-rendering sounds fantastic, but it does come with some drawbacks. One of the features gatsby provides is its transformer plugins, particularly image sharp to facilitate build-time image resizing and dynamic cropping which wouldn't be possible with the Apollo + Prerender (??). |
@Dean177 Interesting point about image sharp. The tricky part is making a live Prismic query with an embedded image sharp query. I have an idea, but I am not 100% sure about it.
If the image sharp is run in the browser, it would make the request a bit slower. But since queries are compiled at build time, this would only affect a live (Preview) query. |
Leaving image rendering with sharp for just a sec, what's really working well for me is the "sloppier" solution I mentioned earlier, which involves loading PrismicDOM and just having it render relevant parts. Like mentioned earlier in the thread, the Prismic API is pretty fast, so the content replacement is super fast. In my case, especially in my case where I'm using it for long-form articles. What really helps is that the data that the GraphQL queries output is super close in shape to the data that PrismicDOM outputs, though there are some small differences that could be worked out. My ideal solution would be to basically have a small script that's hosted on Prismic that basically just verifies that the URL params hint or indicate that the page that I'm rendering is a preview. It can then contact Prismic and, if I'm logged in, load up PrismicDOM remotely, grab the preview data, and replace the content. Perhaps the pages that are previewable are armed with some callback that PrismicDOM or whatever library expects so that all it does is pass the new content into it, then it's up to us to tell it how to render. I do something similar where I pass in either the GraphQL data or PrismicDOM data to a In this solution, I'm looking to avoid loading any other Prismic-related libs explicitly so it's not bundled with the site while enabling previews to still load and maintain the static HTML nature. Any thoughts on something like that? |
@simplesessions I believe with dynamic I'm leaning toward @simplesessions's solution to previewing, with the caveat of somehow overcoming the need to run a separate preview instance with custom code. This allows statically rendering all known pages, but falling back to a dynamic/client-side renderer for new/unknown pages. As @simplesessions mentions, this requires modifying or supplementing the |
I have created a gatsby plugin to track this feature in a separate package. https://github.com/birkir/gatsby-plugin-prismic-preview |
New plugin that will help to get us live previews for more GraphQL powered CMS's https://github.com/birkir/gatsby-source-graphql-universal |
Closing this out as https://github.com/angeloashmore/gatsby-source-prismic/blob/v3-beta/docs/previews-guide.md |
Is there any way to get Prismic's in-situ preview feature working with a (deployed) Gatsby site?
The text was updated successfully, but these errors were encountered: