like to understand is it possible to use the server provided by Nextjs?

bybosslee
Shopify Partner
1 0 0

Hi all

 

I'm new to shopify development (also pretty new to react & Nextjs) like to understand is it possible to use the default server provided by Nextjs?

For example, not using Koa - as the custom server

The reason I am asking this is because NextJs seems to have the basic stuff available with Api routers and data fetching capability

or this is just not possible because of the libraries available 

and in the case if someone likes to try using NextJs basic server function, they have to rewrite everything?

Thank you

0 Likes

You could! I tried but managing Shopify auth with nextjs custom express server gave a lot of unpredictable issues! I shifted back to Shopify Koa. 

Your custom server.js would look something like this 

 

const dotenv = require('dotenv')
dotenv.config()
const Koa = require('koa')
const next = require('next')
const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth')
const { verifyRequest } = require('@shopify/koa-shopify-auth')
const session = require('koa-session')
const { default: graphQLProxy } = require('@shopify/koa-shopify-graphql-proxy')
const { ApiVersion } = require('@shopify/koa-shopify-graphql-proxy')
const Router = require('koa-router')
const { receiveWebhook, registerWebhook } = require('@shopify/koa-shopify-webhooks')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()


const {
    SHOPIFY_API_SECRET_KEY,
    SHOPIFY_API_KEY,
} = process.env

app.prepare().then(() => {
    const server = new Koa()
    const router = new Router()
    server.use(session({ sameSite: 'none', secure: true }, server))
    server.keys = [SHOPIFY_API_SECRET_KEY]

    server.use(
        createShopifyAuth({
            apiKey: SHOPIFY_API_KEY,
            secret: SHOPIFY_API_SECRET_KEY,
            scopes: ['read_script_tags', 'write_script_tags'],
            accessMode: "offline",
            async afterAuth(ctx) {
                const { shop, accessToken } = ctx.session
                ctx.cookies.set("shopOrigin", shop, {
                    httpOnly: false,
                    secure: true,
                    sameSite: 'none'
                })
                try{

                    //create the shopify user in the backend and store the access token

                }catch (e) {
                    console.debug(`Failed afterAuth : ${e}`)
                }

                ctx.redirect('/')
            }
        })
    )

    server.use(graphQLProxy({ version: ApiVersion.July20 }))
    router.get('*', verifyRequest(), async (ctx) => {
        await handle(ctx.req, ctx.res)
        ctx.respond = false
        ctx.res.statusCode = 200
    })

    server.use(router.allowedMethods())
    server.use(router.routes())

    server.listen(port, () => {
        console.log(`> Ready on http://localhost:${port}`)
    })
})

 

Shopify's Koa Auth works like a charm without any difficulty to integrate! 

Here is an alternate with node and express auth -> 

 

const nonce = require('nonce')();
const apiKey = process.env.SHOPIFY_API_KEY;
const scopes = 'read_products';
const forwardingAddress = "https://botsa.ngrok.io"; // Replace this with your HTTPS Forwarding address

const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
const get = require('lodash/get');

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
const port = parseInt(process.env.PORT, 10) || 3000;

const handleShopifyRequest = (req, res, parsedUrl) =>{
    const { pathname, query } = parsedUrl;
    console.log('Path Name-> ', pathname);
    console.log('Query->' , query);
    const shop = get(query,'shop');
    if (shop) {
        const state = nonce();
        const redirectUri = forwardingAddress + '/shopify/callback';
        const installUrl = 'https://' + shop +
            '/admin/oauth/authorize?client_id=' + apiKey +
            '&scope=' + scopes +
            '&state=' + state +
            '&redirect_uri=' + redirectUri;

        res.cookie('state', state);
        res.redirect(installUrl);
    } else {
        app.render(req, res, '/verify', query);
        //return res.status(400).send('Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request');
    }
}

app.prepare().then(() => {
    createServer((req, res) => {
        // Be sure to pass `true` as the second argument to `url.parse`.
        // This tells it to parse the query portion of the URL.
        const parsedUrl = parse(req.url, true)
        const { pathname, query } = parsedUrl

        if (pathname === '/verify') {
            app.render(req, res, '/verify', query)
        } else if (pathname === '/dashboard') {
            app.render(req, res, '/dashboard', query)
        }else if(pathname === '/shopify'){
            handleShopifyRequest(req,res,parsedUrl);
        }
        else {
            handle(req, res, parsedUrl)
        }
    }).listen(port, (err) => {
        if (err) throw err
        console.log('> Ready on http://localhost:3000')
    })
})

 

Regards 

- Looking to Automate Support on FB Messenger? Install our Messenger Marketing & Support App
- Want to embed Instagram Stories on your store? Install our Instagram Stories & Highlights App
- Have more questions? Feel free to email me.
- My reply helped? Click Like to show me some love!
0 Likes