With the `node-addon` I don't get any errors but the React Page doesn't show up
raphael10-collab opened this issue · comments
Following the indications found here: https://medium.com/jspoint/a-simple-guide-to-load-c-c-code-into-node-js-javascript-applications-3fcccf54fd32 and here https://github.com/nodejs/node-addon-examples/tree/main/1_hello_world/node-addon-api
I'm trying to understand how to effectively use node-addon-api for later include within electron C++ module.
In a simple react-typescript-webpack app I've put this:
package.json
:
{
"name": "greet",
"version": "0.0.1",
"license": "UNLICENSED",
"scripts": {
"start": "webpack serve --open",
"build": "webpack --mode production"
},
"dependencies": {
"node-addon-api": "^6.0.0",
"node-gyp": "^9.3.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@babel/core": "^7.20.12",
"@babel/plugin-transform-runtime": "^7.19.6",
"@babel/preset-env": "^7.20.2",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
"@babel/runtime": "^7.20.13",
"@types/fork-ts-checker-webpack-plugin": "^0.4.5",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.10",
"@types/webpack": "^5.28.0",
"@types/webpack-dev-server": "^4.7.2",
"@typescript-eslint/eslint-plugin": "^5.51.0",
"@typescript-eslint/parser": "^5.51.0",
"babel-loader": "^9.1.2",
"eslint": "^8.34.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"fork-ts-checker-webpack-plugin": "^7.3.0",
"node-loader": "^2.0.0",
"ts-node": "^10.9.1",
"typescript": "^4.9.5",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1"
},
"resolutions": {
"@types/webpack": "^4.4.11"
}
}
webpack.config.js
:
const webpack = require("webpack")
const webpackDevServer = require("webpack-dev-server")
const path = require("path")
const Configuration = require("webpack")
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin")
// https://webpack.js.org/loaders/node-loader/
const config: typeof Configuration = {
entry: "./src/index.tsx",
target: "node",
node: {
__dirname: false,
},
module: {
rules: [
{
test: /\.node$/,
use: 'node-loader',
},
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript",
],
},
},
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
mode: 'development',
output: {
path: path.resolve(__dirname, "build"),
filename: "bundle.js",
},
devServer: {
static: path.join(__dirname, "build"),
compress: true,
port: 4000,
},
plugins: [
new ForkTsCheckerWebpackPlugin({
async: false,
}),
],
};
export default config;
tsconfig.json
:
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"esModuleInterop": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": ["src"]
}
binding.gyp
:
{
"targets": [
{
"target_name": "greet",
"cflags!": [ "-fno-exceptions" ],
"cflags_cc!": [ "-fno-exceptions" ],
"sources": [
"./src/greeting.cpp",
"./src/index.cpp"
],
"include_dirs": [
"<!@(node -p \"require('node-addon-api').include\")"
],
'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
}
],
'cflags!': [ '-fno-exceptions' ],
'cflags_cc!': [ '-fno-exceptions' ],
'conditions': [
["OS=='win'", {
"defines": [
"_HAS_EXCEPTIONS=1"
],
"msvs_settings": {
"VCCLCompilerTool": {
"ExceptionHandling": 1
},
},
}],
["OS=='mac'", {
'xcode_settings': {
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
'CLANG_CXX_LIBRARY': 'libc++',
'MACOSX_DEPLOYMENT_TARGET': '10.7',
},
}],
]
}
In ./src/
folder:
greeting.h
:
#include <string>
std::string helloUser( std::string name );
greeting.cpp
:
#include
#include
#include "greeting.h"
std::string helloUser( std::string name) {
return "Hello " + name + " !";
}
int main() {
std::string HelloUserString = helloUser("Bob");
std::cout << HelloUserString << std::endl;
return 0;
}
Compiling and testing the .cpp
file:
raphy@raohy:~/native-greet-module/src$ g++ -std=c++20 greeting.cpp -o greeting
raphy@raohy:~/native-greet-module/src$ ./greeting
Hello Bob !
index.cpp
:
#include <napi.h>
#include <string>
// https://github.com/nodejs/node-addon-examples/blob/main/1_hello_world/node-addon-api/hello.cc
// native C++ function that is assigned to "greetHello" property on "exports" object
Napi::String greetHello(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// call "helloUser" function from "greeting.cpp" file
// WARNING: We are passing hardcoded "MIKE" value for now
std::string result = helloUser( "MIKE" );
// return new "Nap::String" value
return Napi::String::New(env, result);
}
// callback method when module is registered with Node.js
Napi::Object Init(Napi::Env env, Napi::Object exports) {
// set a key on "exports" object
exports.Set(
Napi::String::New(env, "greetHello"), // property name => "greetHello"
Napi::Function::New(env, greetHello) // property value => "greetHello" function
);
// return "exports" object (always)
return exports;
}
// register "greet" module which calls "Init" method
NODE_API_MODULE(greet, Init)
I executed node-gyp configure
:
raphy@raohy:~/native-greet-module$ node-gyp configure
gyp info it worked if it ends with ok
gyp info using node-gyp@9.3.0
gyp info using node@18.12.1 | linux | x64
gyp info find Python using Python version 3.10.6 found at "/usr/bin/python3"
gyp info spawn /usr/bin/python3
gyp info spawn args [
gyp info spawn args '/home/raphy/.nvm/versions/node/v18.12.1/lib/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args 'binding.gyp',
gyp info spawn args '-f',
gyp info spawn args 'make',
gyp info spawn args '-I',
gyp info spawn args '/home/raphy/native-greet-module/build/config.gypi',
gyp info spawn args '-I',
gyp info spawn args '/home/raphy/.nvm/versions/node/v18.12.1/lib/node_modules/node-gyp/addon.gypi',
gyp info spawn args '-I',
gyp info spawn args '/home/raphy/.cache/node-gyp/18.12.1/include/node/common.gypi',
gyp info spawn args '-Dlibrary=shared_library',
gyp info spawn args '-Dvisibility=default',
gyp info spawn args '-Dnode_root_dir=/home/raphy/.cache/node-gyp/18.12.1',
gyp info spawn args '-Dnode_gyp_dir=/home/raphy/.nvm/versions/node/v18.12.1/lib/node_modules/node-gyp',
gyp info spawn args '-Dnode_lib_file=/home/raphy/.cache/node-gyp/18.12.1/<(target_arch)/node.lib',
gyp info spawn args '-Dmodule_root_dir=/home/raphy/native-greet-module',
gyp info spawn args '-Dnode_engine=v8',
gyp info spawn args '--depth=.',
gyp info spawn args '--no-parallel',
gyp info spawn args '--generator-output',
gyp info spawn args 'build',
gyp info spawn args '-Goutput_dir=.'
gyp info spawn args ]
gyp info ok
raphy@raohy:~/native-greet-module$
And then node-gyp build
:
raphy@raohy:~/native-greet-module$ node-gyp build
gyp info it worked if it ends with ok
gyp info using node-gyp@9.3.0
gyp info using node@18.12.1 | linux | x64
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
make: Entering directory '/home/raphy/native-greet-module/build'
CXX(target) Release/obj.target/greet/src/greeting.o
CXX(target) Release/obj.target/greet/src/index.o
SOLINK_MODULE(target) Release/obj.target/greet.node
COPY Release/greet.node
make: Leaving directory '/home/raphy/native-greet-module/build'
gyp info ok
raphy@raohy:~/native-greet-module$
In ./src/
folder` :
index.tsx
:
import React from "react";
import ReactDOM from "react-dom";
const greetModule = require('../build/Release/greet.node')
const App = () => (
<h1>My React and TypeScript App!</h1>
);
ReactDOM.render(
<App />,
document.getElementById("root")
);
Starting the react app
I get no errors:
raphy@raohy:~/native-greet-module$ yarn start
yarn run v1.22.19
$ webpack serve --open
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:4000/
<i> [webpack-dev-server] On Your Network (IPv4): http://192.168.1.7:4000/
<i> [webpack-dev-server] On Your Network (IPv6): http://[fe80::f2e3:be71:cd02:bb1d]:4000/
<i> [webpack-dev-server] Content not from webpack is served from '/home/raphy/native-greet-module/build' directory
<i> [webpack-dev-middleware] wait until bundle finished: /
asset bundle.js 1.16 MiB [emitted] (name: main)
asset 5951ea98b41e9eadb7f0d975f38f4ae6.node 60.8 KiB [emitted] (auxiliary name: main)
runtime modules 23.7 KiB 11 modules
built modules 1.09 MiB [built]
modules by path ./node_modules/ 1.09 MiB
modules by path ./node_modules/webpack/hot/*.js 4.59 KiB 4 modules
modules by path ./node_modules/react/ 85.7 KiB 2 modules
modules by path ./node_modules/react-dom/ 1000 KiB 2 modules
modules by path ./node_modules/scheduler/ 17.3 KiB
./node_modules/scheduler/index.js 198 bytes [built] [code generated]
./node_modules/scheduler/cjs/scheduler.development.js 17.1 KiB [built] [code generated]
./src/index.tsx 331 bytes [built] [code generated]
./build/Release/greet.node 199 bytes [built] [code generated]
external "events" 42 bytes [built] [code generated]
external "path" 42 bytes [optional] [built] [code generated]
webpack 5.75.0 compiled successfully in 1766 ms
But I get this output, instead of the expected header message My React and TypeScript App!
:
You can find the code in this Repo
: https://github.com/raphael10-collab/native-greet-module
What's wrong with my settings? And how to make this simple React-Typescript-Webpack with node-addon
showing the react page
?
This issue is stale because it has been open many days with no activity. It will be closed soon unless the stale label is removed or a comment is made.
Hi @raphael10-collab ,
From the looks of it though, you don't have an index.html
file to be served to use your transpiled index.js. However, this is an issue with webpack and/or react, not node-addon-api. I would reach out there if you are having issues.