Аполлон с работником службы в проекте Next.js

У меня есть прототип NextJS в прямом эфире на https://www.schandillia.com/blog. Отображаемые данные снимаются с установки Strapi по адресу https://dev.schandillia.com/graphql. У меня также есть вся кодовая база на Github по адресу https://github.com/amitschandillia/proost/web (внешний интерфейс).

Я использую клиент Apollo для взаимодействия с источником graphql. А также сервисный работник, настроенный для включения PWA.

Все работает нормально, за исключением того, что я не могу кэшировать результаты запроса в браузере. Сервисный работник может кэшировать все остальное, кроме результатов запросов Apollo. Есть ли способ, которым это может быть включено? Целью является:

  1. Чтобы можно было использовать какую-то предварительную выборку результатов запроса на сервере.
  2. Чтобы иметь возможность кэшировать результаты в браузере через сервисного работника.

Три файла, относящиеся к этой проблеме:

Настройка Apollo


// web/apollo/index.js

import { HttpLink } from 'apollo-link-http';
import { withData } from 'next-apollo';
import { InMemoryCache } from 'apollo-cache-inmemory';

// Set up cache.
const cache = new InMemoryCache();

// Configure Apollo.
const config = {
  link: new HttpLink({
    uri: 'https://dev.schandillia.com/graphql', // Server URL (must be absolute)
  }),
  cache,
};
export default withData(config);

Компонент запроса


// web/pages/PostsList.jsx

import ReactMarkdown from 'react-markdown';
import gql from 'graphql-tag';
import { graphql } from 'react-apollo';
import { Fragment } from 'react';
import Typography from '@material-ui/core/Typography';
import CircularProgress from '@material-ui/core/CircularProgress';

const renderers = {
  paragraph: props => <Typography variant="body1" gutterBottom {...props} />
};

const PostsList = ({ data: { error, posts } }) => {
  let res = '';
  if (error) res = (
    <Typography variant="subtitle2" gutterBottom>
      Error retrieving posts!
    </Typography>
  );
  if (posts && posts.length) {
    if (posts.length !== 0) {
      // Payload returned
      res = (
        <Fragment>
          {posts.map(post => (
            <div>
              <Typography variant="display1" gutterBottom>{post.title}</Typography>
              <Typography variant="subtitle1" gutterBottom>{post.secondaryTitle}</Typography>
              <Typography variant="subtitle2" gutterBottom>Post #{post._id}</Typography>
              <ReactMarkdown source={post.body} renderers={renderers} />
            </div>
          ))}
        </Fragment>
      );
    } else {
      res = (
      // No payload returned
        <Typography variant="subtitle2" gutterBottom>
          No posts Found
        </Typography>
      );
    }
  } else {
    res = (
    // Retrieving payload
      <CircularProgress />
    );
  }
  return res;
};

const query = gql`
  {
    posts {
      _id
      title
      secondaryTitle
      body
    }
  }
`;
// The 'graphql' wrapper executes a GraphQL query and makes the results
// available on the 'data' prop of the wrapped component (PostsList)
export default graphql(query, {
  props: ({ data }) => ({
    data,
  }),
})(PostsList);

Страница блога


// web/pages/blog.jsx

import React, { PureComponent, Fragment } from 'react';
import PropTypes from 'prop-types';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import { withStyles } from '@material-ui/core/styles';
import Head from 'next/head';
import Link from 'next/link';
import withRoot from '../lib/withRoot';
import PostsList from '../components/PostsList';

const styles = theme => ({
  root: {
    textAlign: 'center',
    paddingTop: theme.spacing.unit * 20,
  },
  paragraph: {
    fontFamily: 'Raleway',
  },
});

class Blog extends PureComponent {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/serviceWorker.js'); }
  }

  render() {
    const { classes } = this.props;
    const title = 'Blog | Project Proost';
    const description = 'This is the blog page';
    return (
      <Fragment>
        <Head>
          <title>{ title }</title>
          <meta name="description" content={description} key="description" />
        </Head>
        <div className={classes.root}>
          <Typography variant="display1" gutterBottom>
            Material-UI
          </Typography>
          <Typography gutterBottom>
            <Link href="/about">
              <a>Go to the about page</a>
            </Link>
          </Typography>
          <Typography gutterBottom>
            <Link href="/blog">
              <a>View posts</a>
            </Link>
          </Typography>
          <Button variant="raised" color="primary">
            Super Secret Password
          </Button>
          <Button variant="raised" color="secondary">
            Super Secret Password
          </Button>
        </div>
        <PostsList />
      </Fragment>
    );
  }
}

Blog.propTypes = {
  classes: PropTypes.shape({
    root: PropTypes.string,
  }).isRequired,
};

// Posts.propTypes = {
//   classes: PropTypes.object.isRequired,
// };

export default withRoot(withStyles(styles)(Blog));

Работник службы, о котором идет речь, выглядит следующим образом (отредактировано для краткости):

// web/offline/serviceWorker.js

const CACHE_NAME = '1b23369032b1541e45cb8e3d94206923';
const URLS_TO_CACHE = [
  '/',
  '/about',
  '/blog',
  '/index',
  'apple-touch-icon.png',
  'browserconfig.xml',
  'favicon-16x16.png',
  'favicon-194x194.png',
  'favicon-32x32.png',
  'favicon.ico',
  'manifest.json',
];

// Call install event
self.addEventListener('install', (e) => {
  e.waitUntil(
    caches
      .open(CACHE_NAME)
      .then(cache => cache.addAll(URLS_TO_CACHE))
      .then(() => self.skipWaiting())
  );
});

// Call activate event
self.addEventListener('activate', (e) => {
  // remove unwanted caches
  e.waitUntil(
    caches.keys().then((cacheNames) => {
      Promise.all(
        cacheNames.map((cache) => {
          if (cache !== CACHE_NAME) {
            return caches.delete(cache);
}
        })
      );
})
  );
});

// Call fetch event
self.addEventListener('fetch', (e) => {
  e.respondWith(
    fetch(e.request).catch(() => caches.match(e.request))
  );
});

Пожалуйста, порекомендуйте!

0 ответов

Другие вопросы по тегам