Local version of Prismic.io slow wait time to load

Hello @amarinofr

I am taking this over as Fares is off this week.

I haven't seen your code but looking at your code snippet I can suggest some solutions to optimize your metadata. You don't need to create a separate Custom Type for metadata. Add metadata field in the about Custom Type in a different tab. For example:

  1. Go to your Custom Type where you want to add the metadata.
  2. Click on the "+" sign next to the main tab and name it "SEO."
  3. Add the metadata fields to that tab.
  4. A Key Text field for the meta title( API ID: meta_title).
  5. A Key Text field for the meta description( API ID: meta_desc).

In that way, you don't need 2 calls in one route to get content. Only query the about page and template SEO/Meta fields in the head section of the about templating section.

I hope this optimizes your meta fields calls.

Thanks,
Priyanka

Thanks @Priyanka ! I feel it made no difference in the wait time, but it looks and feels way cleaner this way.

But the TTFB is still a bit slow, having wait times between 200ms and 600ms. It's way better when I switched to CDN, but it's still very slow for what it should be. I've seen prismic websites with much much lower TTFB values and I'm wondering how they do it?

And since this is basically raw Javascript with Express shouldn't it be faster?

Hi @amarinofr
I will check with my team to see other optimizations can be done; I don't have more stuff to optimize other than what @Priyanka has proposed, but converting to one API call should have made a difference.

Nothing to add to what @Priyanka has mentioned, let's see if someone from the community has other suggestions.

1 Like

I am facing the same issue from the same course on awwards
I have changed my approach based on the discussion above, making only one specific fetch call based on the current page, but there's still an unusual delay

Here's my code:


require('dotenv').config();

const fetch = require('node-fetch');

const logger = require('morgan')
const express = require('express')
const errorHandler = require('errorhandler')
const bodyParser = require('body-parser')
const methodOverride = require('method-override')

const UAParser = require('ua-parser-js')

const app = express();
const path = require('path');
const port = process.env.PORT || 4000;

app.use(logger('dev'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
app.use(methodOverride())
app.use(errorHandler())

const d = new Date();

const Prismic = require('@prismicio/client');
const PrismicDOM = require('prismic-dom')
const PrismicH = require('@prismicio/helpers');

const initApi = (req) => {
  return Prismic.createClient(process.env.PRISMIC_ENDPOINT, {
    accessToken: process.env.PRISMIC_ACCESS_TOKEN,
    req,
    fetch,
  });
};

const HandleLinkResolver = (doc) => {

  if (doc.type === 'about'){
    return `/about`
  }
  if (doc.type === 'projects'){
    return `/projects`
  }
  if (doc.type === 'project_details'){
    return `/project/${doc.slug}`
  }

  return '/';
};

app.use((req, res, next) => {

  const ua = UAParser(req.headers['user-agent'])

  res.locals.isDesktop = ua.device.type === undefined
  res.locals.isPhone = ua.device.type === 'mobile'
  res.locals.isTablet = ua.device.type === 'tablet'

  app.locals.currYear = d.getFullYear();

  res.locals.Link = HandleLinkResolver

  res.locals.PrismicH = PrismicH;

  res.locals.PrismicDOM = PrismicDOM
  next();
});

app.use(express.static(path.join(__dirname, 'public')));

app.set('view engine', 'pug');
app.set('views', path.join(__dirname, 'views'));
app.locals.basedir = app.get('views');

const assets = [];

const handleRequest = async (apiFor, api) => {

  if(apiFor === 'home'){
    const home = await api.getSingle('home')

    home.data.project_list.forEach((item) => {
      assets.push(item.project_image.url);
    });

    return{
      assets,
      home
    }

  }
  if(apiFor === 'about'){
    const about = await api.getSingle('about')

    return{
      assets,
      about
    }

  }
  if(apiFor === 'projects'){
    const projects = await api.getSingle('projects')

    projects.data.project.forEach((item) => {
      assets.push(item.project_image.url);
    });

    return{
      assets,
      projects
    }

  }

  return {
  
  };
};

app.get('/', async (req, res) => {
  const api = await initApi(req);
  const defaults = await handleRequest('home',api);

  res.render('pages/home', {
    ...defaults,
  });
});

app.get('/about', async (req, res) => {
  const api = await initApi(req);
  const defaults = await handleRequest('about',api);

  res.render('pages/about', {
    ...defaults,
  });
});

app.get('/projects', async (req, res) => {
  const api = await initApi(req);
  const defaults = await handleRequest('projects',api);

  res.render('pages/projects', {
    ...defaults,
  });
});

app.get('/project/:uid', async (req, res) => {
  const api = await initApi(req);
  const defaults = await handleRequest(api);

  const project = await api.getByUID('project_details', req.params.uid, {
    fetchLinks: 'project.title',
  });
  res.render('pages/detail', {
    ...defaults,
    project,
  });
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});

Hello @neelansh448

Welcome to the Prismic community, and thanks for reaching out to us.

You should use the latest prismic packages versions like @prismicio/client, @prismicio/helpers and where you don't need prismic-dom. Also, create a client function where you don't need req params.
I will suggest you change the setup and follow the article: Set up Prismic with Express - Documentation - Prismic

Give this a try and let me know if you need anything else.

Thanks,
Priyanka

Yes, this actually helps a lot and mine got a lot faster!

Thanks, @amarinofr for letting us know. It helps others.

It doesn't seems to work for me. load time is still slow.

Am I implementing this the correct way ?

/* eslint-disable no-undef */
/* eslint-disable no-unused-vars */
require('dotenv').config();

const fetch = require('node-fetch');

const logger = require('morgan')
const express = require('express')
const errorHandler = require('errorhandler')
const bodyParser = require('body-parser')
const methodOverride = require('method-override')

const UAParser = require('ua-parser-js')

const app = express();
const path = require('path');
const port = process.env.PORT || 4000;

app.use(logger('dev'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
app.use(methodOverride())
app.use(errorHandler())

const d = new Date();

const Prismic = require('@prismicio/client');
const PrismicH = require('@prismicio/helpers');

const client = Prismic.createClient(process.env.PRISMIC_ENDPOINT, {
  fetch,
  accessToken: process.env.PRISMIC_ACCESS_TOKEN
})

const HandleLinkResolver = (doc) => {

  if (doc.type === 'about'){
    return `/about`
  }
  if (doc.type === 'projects'){
    return `/projects`
  }
  if (doc.type === 'project_details'){
    return `/project/${doc.slug}`
  }

  return '/';
};

app.use((req, res, next) => {

  const ua = UAParser(req.headers['user-agent'])

  res.locals.isDesktop = ua.device.type === undefined
  res.locals.isPhone = ua.device.type === 'mobile'
  res.locals.isTablet = ua.device.type === 'tablet'

  res.locals.currYear = d.getFullYear();

  res.locals.Link = HandleLinkResolver

  res.locals.PrismicH = PrismicH;

  next();
});

app.use(express.static(path.join(__dirname, 'public')));

app.set('view engine', 'pug');
app.set('views', path.join(__dirname, 'views'));
app.locals.basedir = app.get('views');

const assets = [];

app.get('/', async (req, res) => {

  const home = await client.getSingle('home')

  home.data.project_list.forEach((item) => {
    assets.push(item.project_image.url);
  });

  res.render('pages/home', {
    home,
    assets,
  });
});

app.get('/about', async (req, res) => {

  const about = await client.getSingle('about')

  res.render('pages/about', {
    about,
    assets,
  });
});

app.get('/projects', async (req, res) => {

  const projects = await client.getSingle('projects')

  projects.data.project.forEach((item) => {
    assets.push(item.project_image.url);
  });

  res.render('pages/projects', {
    // ...defaults,
    projects,
    assets,
  });
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});

Screenshot 2023-02-23 at 8.20.39 PM

Hello @neelansh448

Evreything looks good to me. One thing I would change is to use import method instead require method. Loading is synchronous(step by step) for require on the other hand import can be asynchronous(without waiting for previous import) so it can perform a little better than require

Give this a try.

Thanks,
Priyanka

I am really confused right now!

I am using webpack and it says

cannot use import statement outside a module webpack

Is there an example file / boilerplate for such a case ?

Thanks! Appreciate it!

You can use "type": "module" on the package.json config file to use imports I think.

Hello @neelansh448

Thanks @amarinofr for your response.

To use import syntax, Add "type": "module" to the package.json file. It's decribed in our Set up article:

Here is a starter in express.js: GitHub - prismicio/nodejs-blog

Thanks,
Priyanka

This requires a me to make alot of changes to my project structure.

But did this solution really worked for you in reducing the load time ?

I'm actually using require instead of import. What made the real difference is what @Priyanka mentioned early.

Ah I see! that solution didn't work for me though!

Hello @neelansh448, I am not sure about the root cause of the slow time. I can try to run your project on my locale if you share the github repo or project source code with me. You can send me via private message.

Thanks,
Priyanka