0

I'm not sure what I'm doing wrong, and the documentation is pretty spotty and nobody on Prismic's Community board is very responsive. I'm hoping somebody can help me here:

I'm trying to use slicezone for nextjs, and I'm following along with the documentation and I'm 'missing a loader' for slicezone.

The error:

./node_modules/next-slicezone/index.js
Module parse failed: Unexpected token (6:2)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| 
| const PageInfo = ({ title, description }) => (
>   <div
|     style={{
|       height: '80vh',

My page:

import { client } from '../../../prismic-configuration'
import Prismic from '@prismicio/client'
import { SliceZone } from 'next-slicezone'
import { useGetStaticProps, useGetStaticPaths} from 'next-slicezone/hooks'
import resolver from '../../../sm-resolver'

const CategoryProduct = ({slices}) => {
  return(
    <div>

    </div>
  )
}

export async function getStaticProps(props) {
  const { params: { uid, category }} = props
  console.log(uid, category)
  const products = await client.query([
    Prismic.Predicates.at('', 'product'),
  ])
  const prods = {
    props: {
      products
    }
  }

  return prods
}

export async function getStaticPaths() {
  const results = {
    paths: [
      {
        params: {
          uid: 'handmade-film-transitions',
          category: 'transitions'
        }
      }
    ], fallback: false
  }
  return results
}

I should note that when I remove next-slicezone and just leave the prismic query, everything works just fine. I've looked at my configuration files, and everything seems to be in order.

Here's the sm-resolver.js that it auto-installed for me (which I think may be the culprit). Not sure where to go:

module.exports = {
  apiEndpoint: 'https://edit-elements.cdn.prismic.io/api/v2',
  repoName: "edit-elements",
  linkResolver: function(doc) {
      if (doc.isBroken) {
          return '/404';
      }
      if (doc.type === 'home') {
          return '/';
      }
      if (doc.type === 'page') {
          return '/page/' + doc.uid
      }
      if (doc.type === 'shop') {
          return `/shop/${doc.uid}`
      }
      return '/'
  }
}

I'm sure I'm doing something wrong because the docs are pretty nebulous (especially having to integrate with an already-setup repo), so any help would be greatly appreciated. :)

Joel Hager
  • 2,990
  • 3
  • 15
  • 44
  • Have you tried using [`next-transpile-modules`](https://www.npmjs.com/package/next-transpile-modules) to transpile `next-slicezone`? – juliomalves May 30 '21 at 18:12
  • I didn't know that was even a thing, and the documentation doesn't say anything about its need – Joel Hager May 30 '21 at 18:34
  • If I recall correctly, SliceZone is when config the Prismic content to allow a given content model to have multiple slices. It seems like you don't have it setup correctly base on the API call `https://edit-elements.cdn.prismic.io/api/v2` – Archer11 Jun 08 '21 at 20:54
  • It is set up correctly, because the slices are coming through. It was adding next-transpile-modules. I'm talking with the maintainer of next-slicezone about fixing the bug. I'm not sure if I can answer my own question yet. – Joel Hager Jun 08 '21 at 21:13

1 Answers1

0

The issue was the version (as I and others) have set up doesn't work out of the box. You have to use next-transpile-modules (in its current state). sm-resolver is just for link-building (from Prismic support).

Here is the solution:

next.config.js:

const withPlugins = require('next-compose-plugins')
const withSvgr = require('next-svgr')
const withTM = require('next-transpile-modules')(['next-slicezone'])

module.exports = withPlugins([
  withTM,
  withSvgr],
  {
    future: 
    {
      webpack5: true
    },
    modules: true,
  },
)

package.json:

{
  "name": "edit-elements",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "storybook": "start-storybook -p 8888",
    "build-storybook": "build-storybook",
    "slicemachine": "start-slicemachine --port 9999"
  },
  "dependencies": {
    "@emotion/react": "^11.4.0",
    "@emotion/styled": "^11.3.0",
    "@material-ui/core": "^5.0.0-alpha.31",
    "@material-ui/icons": "^4.11.2",
    "@material-ui/lab": "^4.0.0-alpha.58",
    "@prismicio/client": "^4.0.0",
    "@storybook/react": "^6.2.9",
    "clsx": "^1.1.1",
    "essential-slices": "^1.0.4",
    "firebase": "^8.2.1",
    "firebase-admin": "^9.4.2",
    "firebaseui": "^4.7.1",
    "framer-motion": "^3.1.1",
    "jose": "^3.12.3",
    "next": "^10.2.1",
    "next-compose-plugins": "^2.2.1",
    "next-slicezone": "0.1.0-alpha.0",
    "next-svgr": "^0.0.2",
    "next-transpile-modules": "^6.4.1",
    "prismic-dom": "^2.2.5",
    "prismic-reactjs": "^1.3.3",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "react-paypal-button-v2": "^2.6.3",
    "react-player": "^2.9.0",
    "react-resize-detector": "^6.7.2",
    "sass": "^1.32.4",
    "slice-machine-ui": "^0.0.46",
    "storybook": "^6.2.9",
    "styled-components": "^5.2.1",
    "theme-ui": "^0.7.3"
  },
  "devDependencies": {
    "babel-plugin-react-require": "^3.1.3"
  }
}

An example of a working dynamic page [category]/[uid]:

import { client } from '../../../prismic-configuration'
import Prismic from '@prismicio/client'
import { Divider, Grid, Typography, makeStyles } from '@material-ui/core'
import SliceZone from 'next-slicezone'
import { useGetStaticPaths, useGetStaticProps } from 'next-slicezone/hooks'
import SliceResolver from '../../../sm-resolver'
import AddToCartButton from '../../../components/AddToCartButton'
import { SignJWT } from 'jose/jwt/sign'
import { useEffect, useRef, useState } from 'react'

const theme = makeStyles({
  'section': {
    margin: '3rem auto'
  },
  outer: {
    padding: '1rem .5rem'
  },
  container: {
    margin: 'auto',
  },
  slim: {
    margin: 'auto',
    maxWidth: '1200px',
  },
  productImg: {
    width: '100%',
    height: 'auto',
    maxWidth: '500px'
  },
  productTitle: {
    marginTop: '3rem'
  },
  justifyText: {
    textAlign: 'justify'
  },
  wideDivide: {
    margin: '3em auto'
  },
  strike: {
    textDecoration: 'line-through',
    fontSize: '1.5rem',
    color: '#999999'
  }
})

const CategoryProduct = (props) => {
  const [ currentProduct, setCurrentProduct ] = useState(null)

  useEffect(() => {
    const { product } = props
    console.log('useEffect props', product)
    setCurrentProduct(prevState => product)
    console.log('loaded product', currentProduct)
  }, [currentProduct])

  const product = props.product
  const slices = product.data.body
  const { featured_image, price, on_sale, sale_price, title, short_description } = product.data
  const styles = theme()
  return(
    <Grid container direction="column" mt={6} className={styles.outer}>
      <Grid container style={{marginBottom: '6rem'}} className={styles.slim} justifyContent="center">
        <Grid item xs={4} md={6}>
          <img className={styles.productImg} src={featured_image.medium.url} />
        </Grid>
        <Grid item xs={8} md={6} sx={{textAlign: 'right'}}>
          <Typography className={styles.productTitle} variant="h1">{title[0].text}</Typography>
          <Typography mb={2} variant="h4">{on_sale && sale_price ? <div><span className={styles.strike}>${price}</span>&nbsp;${sale_price}</div> : `$${price}`}</Typography>
          <AddToCartButton product={product} />
          <Divider className={styles.wideDivide} />
          <Typography className={styles.justifyText}>{short_description[0].text}</Typography>
        </Grid>
      </Grid>
      <Grid container direction="column" className={[styles.slices, styles.slim].join(' ')}>
        <SliceZone resolver={SliceResolver} slices={slices} />
      </Grid>
    </Grid>
  )
}

export const getStaticProps = async ({params}) => {
  const product = await client.getByUID('product', params.uid)
  const { price, sale_price } = product.data
  // Where we return the specific product's data
  return {
    props: {
      product
    }
  }
}

export const getStaticPaths = useGetStaticPaths({
  client: client,
  type: 'product',
  formatPath: (doc) => {
    // Where we return paths for /category/uid for static pages
    return {
      params: {
        category: doc.data.category.uid,
        uid: doc.uid 
      }
    }
  }
})
export default CategoryProduct
Joel Hager
  • 2,990
  • 3
  • 15
  • 44