我正在尝试将 NPM 包作为插件注入 Next.js 应用程序以避免 "Module not found: Can't resolve 'child_process'" 错误
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
我有开发 nuxt 应用程序的经验,但我是 next.js 应用程序的新手。在我尝试制作的 next.js 应用程序中,我无法让 'google-auth-library' 在 component
中工作。这是我对有问题的 component
的代码:
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;
我知道 main() 中的代码适用于常规节点应用程序。我做了一个节点应用程序,我把那个函数放在一个 index.js
文件中,运行 它与 node index.js
和它 运行 完美。问题是当我 运行 这个带有 yarn dev
的应用程序时,我得到一个空白的浏览器页面,并且在我的终端中是这样的:
<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> %
我认为此错误是由于服务器端呈现问题引起的。我写了一个 nuxt 应用程序,我有一个类似的问题,有一个名为 'unity-webgl' 的包。我通过 plugins
文件夹将其注入应用程序来解决问题。我做了这个文件:
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);
};
我还需要在 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: {
}
}
注意 plugins
数组。那么我该如何对我正在开发的 next.js 应用程序做类似的事情呢? next.config.js
文件看起来与 nuxt.config.js 文件有很大不同:
next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}
module.exports = nextConfig
您能否仅使用 next.js 应用程序注入插件,让它们进入 运行 客户端?我该怎么做?
更新:
这是我的 Github 代码库。本题重点是components/Middle.tshttps://github.com/ChristianOConnor/call-to-cloud-exp
尝试动态导入包。这可能是因为 nextjs SSR。
在您使用此 npm 包的任何地方动态调用您的组件,如下面的文档所示。
const DynamicComponent = dynamic(() => import('../components/hello'))
参考文档:-
https://nextjs.org/docs/advanced-features/dynamic-import
关键是您必须将 GoogleAuth
api 调用放在 pages/api
路由中。这是一个如何调用 Google 云函数的示例。顺便说一句,我使用命令 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
我有开发 nuxt 应用程序的经验,但我是 next.js 应用程序的新手。在我尝试制作的 next.js 应用程序中,我无法让 'google-auth-library' 在 component
中工作。这是我对有问题的 component
的代码:
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;
我知道 main() 中的代码适用于常规节点应用程序。我做了一个节点应用程序,我把那个函数放在一个 index.js
文件中,运行 它与 node index.js
和它 运行 完美。问题是当我 运行 这个带有 yarn dev
的应用程序时,我得到一个空白的浏览器页面,并且在我的终端中是这样的:
<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> %
我认为此错误是由于服务器端呈现问题引起的。我写了一个 nuxt 应用程序,我有一个类似的问题,有一个名为 'unity-webgl' 的包。我通过 plugins
文件夹将其注入应用程序来解决问题。我做了这个文件:
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);
};
我还需要在 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: {
}
}
注意 plugins
数组。那么我该如何对我正在开发的 next.js 应用程序做类似的事情呢? next.config.js
文件看起来与 nuxt.config.js 文件有很大不同:
next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}
module.exports = nextConfig
您能否仅使用 next.js 应用程序注入插件,让它们进入 运行 客户端?我该怎么做?
更新:
这是我的 Github 代码库。本题重点是components/Middle.tshttps://github.com/ChristianOConnor/call-to-cloud-exp
尝试动态导入包。这可能是因为 nextjs SSR。 在您使用此 npm 包的任何地方动态调用您的组件,如下面的文档所示。
const DynamicComponent = dynamic(() => import('../components/hello'))
参考文档:- https://nextjs.org/docs/advanced-features/dynamic-import
关键是您必须将 GoogleAuth
api 调用放在 pages/api
路由中。这是一个如何调用 Google 云函数的示例。顺便说一句,我使用命令 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