Replies: 5 comments
-
can you share the code? I had some issues at first with Next.js 14, but got it working. Ensure that you are explicitly using the "use client"; where appropriate. |
Beta Was this translation helpful? Give feedback.
-
@jpieters You can check the issue/example of the code in this repo: https://github.com/tembra/human-nextjs-14 There I tried many ways to load Human, each one in a specific intuitive named route, and they all fail.
Notice that even on Even if NextJS is pre-rendering client components/pages on the server for the initial page load, it does not makes sense that this function is being executed. Said that I think that If you can share how you got it working it will be awesome. I'm really out of ideas. |
Beta Was this translation helpful? Give feedback.
-
After digging deeper on webpack configuration I managed to get it working using this /** @type {import('next').NextConfig} */
const nextConfig = {
webpack: (config, { webpack, isServer }) => {
if (isServer) {
config.plugins.push(
new webpack.IgnorePlugin({
checkResource(resource) {
if (resource === '@vladmandic/human') {
// ignore human package on server
return true
}
return false
},
})
// or a shorter (but not too explicit) version
// new webpack.IgnorePlugin({ resourceRegExp: /^@vladmandic\/human$/ })
)
}
return config
}
}
export default nextConfig With this configuration all my examples of the shared code work. However I obviously got the error below during page compiling. So this is not the correct approach. $ npm run dev
> [email protected] dev
> next dev
▲ Next.js 14.1.0
- Local: http://localhost:3000
✓ Ready in 6s
○ Compiling / ...
✓ Compiled / in 8.4s (477 modules)
⨯ Error: Cannot find module '@vladmandic/human'
at webpackMissingModule (./app/page.tsx:7:50)
at eval (./app/page.tsx:7:142)
at (ssr)/./app/page.tsx (.../human-nextjs-14/.next/server/app/page.js:162:1)
at __webpack_require__ (.../human-nextjs-14/.next/server/webpack-runtime.js:33:42)
at JSON.parse (<anonymous>)
✓ Compiled in 243ms (230 modules) I also still want to know WHY the module is being imported/resolved by webpack on server rendering if it is lazy loaded inside a callback. Anyone has any thoughts/explanations or am I missing something in my code? |
Beta Was this translation helpful? Give feedback.
-
since this is not an issue with |
Beta Was this translation helpful? Give feedback.
-
Solution for nextjs 14 app router client side browser as "use client" component.
I encountered the same issue with the error Cause : Solution : Example Implementation override componentDidMount() { // make sure this will be ignored in build process
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
// Assign img element after component is mounted
this.img = document.getElementById(this.props.imgId) as (HTMLImageElement | undefined);
// Load Human model dynamically
import('@vladmandic/human').then((H: any) => {
this.human = new H.default(config) as Human;
console.log('human version:', this.human.version, '| tfjs version:', this.human.tf.version['tfjs-core']);
console.log('platform:', this.human.env.platform, '| agent:', this.human.env.agent);
console.log('loading models...');
this.human.load().then(() => {
this.setState({ ready: true });
console.log('ready...');
});
});
}
} Key Points
Full Component ExampleBelow is the complete component that processes an 'use client'
import { Component } from "react";
import type { Human, Config } from '@vladmandic/human';
const config: Partial<Config> = {
debug: true,
modelBasePath: '/models/models', // reference to my local models base path
face: { enabled: true },
};
interface Props { imgId: string };
interface State { ready: boolean };
class RunHuman extends Component<Props, State> {
human: Human | undefined = undefined;
img: HTMLImageElement | undefined = undefined;
setFaceResult: React.Dispatch<React.SetStateAction<Human[] | null>> | undefined;
constructor(props: Props) {
super(props);
this.state = { ready: false };
}
override componentDidMount() { // make sure this will be ingored in build process
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
// Assign img element after component is mounted
this.img = document.getElementById(this.props.imgId) as (HTMLImageElement | undefined);
// Load Human model dynamically
import('@vladmandic/human').then((H: any) => {
this.human = new H.default(config) as Human;
console.log('human version:', this.human.version, '| tfjs version:', this.human.tf.version['tfjs-core']);
console.log('platform:', this.human.env.platform, '| agent:', this.human.env.agent);
console.log('loading models...');
this.human.load().then(() => {
this.setState({ ready: true });
console.log('ready...');
});
});
}
}
// Event handler for detection
detect = async () => {
if (!this.human || !this.img) return;
// Run detection on the image
await this.human.detect(this.img, { face: { detector: { maxDetected: 20 } } });
// console.log detected faces and their embeddings
const faces = this.human.result.face;
console.log("total face detected: ",faces.length);
faces.forEach((face, i) => {
console.table({
face: i+1,
gender: face.gender,
score: face.score,
embedding_length: face.embedding?.length
})
});
console.log('Detection complete');
};
override render() {
return (
<div>
<button className="p-2 mb-11 bg-black text-white border-red-400 border-2" onClick={this.detect} disabled={!this.state.ready}>
Detect Faces
</button>
</div>
);
}
}
export default RunHuman; This approach should help others facing the same issue when using TensorFlow.js models in client-side Next.js applications. |
Beta Was this translation helpful? Give feedback.
-
Issue Description
When importing Human on a NextJS 14 project, the framework tries to import the node bundle instead of ESM for browsers, despite adding
'use client'
on top of the page file.Since node bundle requires a tfjs backend, the error below comes in:
I know that this is not an issue within the Human package at all and it's about NextJS SSR. However I guess you may help me to achieve the desired solution.
I already tried to load Human within a separated dynamic loaded component with
dynamic(() => import('@/components/Human'), { ssr: false })
, but it also did not work.I also tried to import it inside a
useEffect
of theHuman
component created as you did in your class constructor in NextJS demo, but it also did not work.I also tried to import Human explicitly from
@vladmandic/human/dist/human.esm
but it did not found the path.Everything works fine if I use Vite instead of NextJS to create my project.
Steps to Reproduce
npx create-next-app app-name
and choose all default configs.npm i
app/page.tsx
to add'use client'
on top the file and add import to Humanimport { Human } from '@vladmandic/human
.npm run dev
Expected Behavior
NextJS identify that I'm using a client component on that page and load ESM bundle of Human package instead of node bundle.
Environment
js
,esm
,esm-nobundle
)? esmDiagnostics
Additional
package.json
Beta Was this translation helpful? Give feedback.
All reactions