简体   繁体   中英

I'm Trying to Inject An NPM package As A Plugin on A Next.js App to Avoid A "Module not found: Can't resolve 'child_process'" Error

I have experience developing nuxt apps but I am new to next.js apps. On the next.js app that I am trying to make, I'm having trouble getting 'google-auth-library' to work in a component . This is my code for the component in question:

components/Middle.tsx

import React from 'react';
import { Button } from 'react-bootstrap';
import { GoogleAuth } from 'google-auth-library';

const url = "https://us-central1-gtwitone.cloudfunctions.net/<functionname>";
const keyFilename = "/path/to/my/key.json";
//const functionsClient = CloudFunctionsServiceClient.v1.CloudFunctionsServiceClient;

class Middle extends React.Component {
    async main() {
      const auth = new GoogleAuth({keyFilename: keyFilename})

      //Create your client with an Identity token.
      const client = await auth.getIdTokenClient(url);
      const res = await client.request({url});
      console.log(res.data);
  }

    render() {
      return (
        <div className="col-md-12 text-center">
            <Button variant='primary' onClick={this.main}>
                Click me
            </Button>
        </div>
      );
    }
  }

export default Middle;

I know that the code in main() works in a regular node app. I made a node app where I put that function in an index.js file and ran it with node index.js and it ran perfectly. The problem is when I run this app with yarn dev I get a blank browser page and this in my terminal:

<myusername>@<mycomputername> <myappname> % yarn dev
yarn run v1.22.17
$ next dev
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
wait  - compiling...
event - compiled client and server successfully in 214 ms (124 modules)
wait  - compiling / (client and server)...
wait  - compiling...
error - ./node_modules/google-auth-library/build/src/auth/googleauth.js:17:0
Module not found: Can't resolve 'child_process'

Import trace for requested module:
./node_modules/google-auth-library/build/src/index.js
./components/Middle.tsx
./pages/index.tsx

https://nextjs.org/docs/messages/module-not-found
Native Node.js APIs are not supported in the Edge Runtime. Found `child_process` imported.

Could not find files for / in .next/build-manifest.json
Could not find files for / in .next/build-manifest.json
^C
<myusername>@<mycomputername> <myappname> % 

I believe that this error is due to a problem with server side rendering. I wrote a nuxt app where I had a similar issue, with a package called 'unity-webgl'. I fixed the problem by injecting it into the app via a plugins folder. I made this file:

plugins/plug-unity-webgl.client.js

import UnityWebgl from "unity-webgl";

export default ({ _ }, inject) => {
  const Unity = new UnityWebgl({
    loaderUrl: "/Build/tetris.loader.js",
    dataUrl: "/Build/tetris.data",
    frameworkUrl: "/Build/tetris.framework.js",
    codeUrl: "/Build/tetris.wasm",
  });
  inject("webgl", Unity);
};

I also needed to declare this in nuxt.config.js

import colors from 'vuetify/es5/util/colors'

export default {
  // Set server port
  server: {
    port: 8080
  },
  /*
  ** Nuxt rendering mode
  ** See https://nuxtjs.org/api/configuration-mode
  */
  mode: 'universal',

  // Target: https://go.nuxtjs.dev/config-target
  target: 'static',

  // Global page headers: https://go.nuxtjs.dev/config-head
  head: {
    titleTemplate: '%s - appFrontend',
    title: 'appFrontend',
    htmlAttrs: {
      lang: 'en'
    },
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: '' },
      { name: 'format-detection', content: 'telephone=no' }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },

  // Global CSS: https://go.nuxtjs.dev/config-css
  css: [
  ],

  // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
  plugins: [
    '~/plugins/persistState.js',
    '~/plugins/axios.js',
    '~/plugins/plug-unity-webgl.client.js'
  ],

  // Auto import components: https://go.nuxtjs.dev/config-components
  components: true,

  // Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
  buildModules: [
    // https://go.nuxtjs.dev/vuetify
    '@nuxtjs/vuetify'
  ],

  // Modules: https://go.nuxtjs.dev/config-modules
  modules: [
    // https://go.nuxtjs.dev/axios
    '@nuxtjs/axios'
  ],

  // Axios module configuration: https://go.nuxtjs.dev/config-axios
  axios: {
    // Workaround to avoid enforcing hard-coded localhost:3000: https://github.com/nuxt-community/axios-module/issues/308
    browserBaseURL: process.env.API_URL
  },

  // Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify
  vuetify: {
    customVariables: ['~/assets/variables.scss'],
    theme: {
      dark: true,
      themes: {
        dark: {
          primary: colors.blue.darken2,
          accent: colors.grey.darken3,
          secondary: colors.amber.darken3,
          info: colors.teal.lighten1,
          warning: colors.amber.base,
          error: colors.deepOrange.accent4,
          success: colors.green.accent3
        }
      }
    }
  },

  // Build Configuration: https://go.nuxtjs.dev/config-build
  build: {
  }
}

Note the plugins arrary. So how would I do something similar with this next.js app I'm working on? The next.config.js file looks way different than the nuxt.config.js file did:

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
}

module.exports = nextConfig

Can you inject plugins to get them to run client side only with a next.js app? How would I do this?

Update:
Here is my Github repo of the code. The focus of this question is components/Middle.ts https://github.com/ChristianOConnor/call-to-cloud-exp

They key is that you have to put the GoogleAuth api call in the pages/api route. This is an example of how to call a Google Cloud Function. Btw, I made the basic template for the example with the command npx create-next-app@latest call-to-cloud-exp --typescript

pages/api/google.ts

// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from "next"
import { GoogleAuth } from "google-auth-library"

export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
    const url = process.env.FUNCTION_URL as string

    //Example with the key file, not recommended on GCP environment.
    const auth = new GoogleAuth({ keyFilename: process.env.KEYSTORE_PATH })

    //Create your client with an Identity token.
    const client = await auth.getIdTokenClient(url)
    const result = await client.request({ url })
    console.log(result.data)
    res.json({ data: result.data })
}

components/Middle.tsx

import React from "react"
import { Button } from "react-bootstrap"

class Middle extends React.Component {
  handleClick() {
        console.log("this is:", this)
    }
  
  // this talks with /pages/api/google
  async imCallingAnAPI() {
    const result = await fetch("/api/google")
    console.log({ result })
  }

  render() {
    return (
      <div className="col-md-12 text-center">
        <Button variant="primary" onClick={this.imCallingAnAPI}>
          Click me
        </Button>
      </div>
    )
  }
}

export default Middle

pages/index.tsx

import type { NextPage } from 'next'
import Header from '../components/Header';
import Footer from '../components/Footer';
import Middle from '../components/Middle';

const Home: NextPage = () => {
  return (
    <><main className='d-flex flex-column min-vh-100'>
      <Header />
      <br></br>
      <br></br>
      <Middle />
      </main>
      <footer>
        <Footer />
      </footer>
    </>
  )
}

export default Home

Try importing the package dynamically. This could happen because of nextjs SSR. Call your component wherever you're using this npm package dynamically as shown in the docs below.

const DynamicComponent = dynamic(() => import('../components/hello'))

Refer from the doc:- https://nextjs.org/docs/advanced-features/dynamic-import

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM