NextJS, использующий кэш памяти в dev, не работает

#typescript #caching #next.js

Вопрос:

Я хочу создать простой статический сайт блога, и когда я экспортирую свои страницы, все происходит хорошо и быстро.

Но в режиме разработки мое создание сообщений происходит медленно, и я хочу кэшировать их, чтобы это было сделано только один раз. Это делается в post.ts файле, и мой кэш есть const posts: Post[] = [] .

Я ожидаю , что после ввода yarn dev post.ts файл будет загружен один раз, и я смогу заполнить и повторно использовать свой кэшированный массив записей, но, как ни странно, этот модуль ts загружается много раз.

 import fs from 'fs'
import path from 'path'
// ...
​
console.log('????? reloading page')
const posts: Post[] = []  // cached posts, hope to generate once
let postsGenerated = false
​
export async function getSortedPostsData(): Promise<Post[]> {
  // Get file names under /posts
  const pendings: Promise<any>[] = []
  if (postsGenerated) {
    console.log('      Using cache ')
    return sortPostsByDate(posts)
  } else {
    console.log('==== Calculating all')
    postsGenerated = true
  }
  let i = 0
  traverseDir('content/blog', (path) => {
    if (path.includes('.md')) { ... })
  }
      
  await Promise.all(pendings)
  return sortPostsByDate(posts)
}

 

В результате иногда используется кэш, иногда нет. Даже при перезагрузке одной и той же страницы кэш не всегда вызывается. Почему? И как это улучшить ?

введите описание изображения здесь

Комментарии:

1. Не могли бы вы привести минимальный воспроизводимый пример для дальнейшей отладки этого поведения?

Ответ №1:

Вероятно, именно так работает быстрое обновление. Вы не можете быть уверены, что сервер не перезагрузит .ts файл после запуска разработки. Не уверен, насколько это улучшит, но вы можете попробовать использовать файл в качестве кэша вместо пустой константы, чтобы сохранять проанализированные данные при перезагрузке.

 const devPostsCache = 'devPostsCache.json';
export async function getSortedPostsData(): Promise<Post[]> {
  // Get file names under /posts
  const pendings: Promise<any>[] = []
  const postGenerated = fs.existsSync(devPostsCache);
  if (postsGenerated) {
    const posts = JSON.parse(fs.readFileSync(devPostsCache));
    return sortPostsByDate(posts)
  } else {
    console.log('==== Calculating all')
    postsGenerated = true
  }
  let i = 0
  traverseDir('content/blog', (path) => {
    if (path.includes('.md')) { ... })
  }
  
  // not sure what pending promises exactly do
  // I'll assume you get an array of post
  const parsedPosts = await Promise.all(pendings);
  fs.writeFileSync(devPostsCache, JSON.stringify(parsedPosts));
  return sortPostsByDate(posts)
}
 

и удаляйте его каждый раз, когда вы начинаете разработку со predev скрипта

   "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "predev": "rm devPostsCache.json"
  },
 

Обновить

Другой подход, который я нашел, чтобы избежать слишком частой перекомпиляции кода, — это изменение конфигурации onDemandEntries.

 module.exports = {
  onDemandEntries: {
    // period (in ms) where the server will keep pages in the buffer
    maxInactiveAge: 360 * 1000,
    // number of pages that should be kept simultaneously without being disposed
    pagesBufferLength: 10,
  },
}
 

По умолчанию используется 60 * 1000 значение maxInactiveAge и 2 для длины буфера страниц.

Я также попытался изменить некоторые конфигурации webpack, но это не сработало, потому что nextjs перекомпилирует все это по запросу.

Комментарии:

1. На консоли появляется быстрое обновление, и я подумал, что это может быть причиной. Однако это не кажется полностью последовательным. Файл кажется намного проще, чем я думал сначала. Это немного грустно, так как это не нужно для производства.

Ответ №2:

Возможно, я ошибаюсь, но это звучит как пример использования, когда динамический маршрут, getStaticPaths и getStaticProps могут работать для вас.

getStaticPaths проверит существующие файлы и проложит для них маршруты, а getStaticProps при необходимости получит нужную запись. При экспорте все они извлекаются и генерируются.

https://nextjs.org/docs/advanced-features/static-html-export

https://nextjs.org/docs/basic-features/data-fetching#getstaticpaths-static-generation

Комментарии:

1. Я действительно им пользуюсь

2. Если вы используете его, то вы должны иметь возможность генерировать сообщение на основе маршрута только по требованию, а не все сразу? Или вы уже это делаете, и даже это медленно генерируется при открытии страницы публикации?