ziti-sdk-nodejs
ziti-sdk-nodejs copied to clipboard
ESM with Webpack not running
Hi together,
we're having trouble getting ziti-sdk-nodejs working without modifying the ziti-sdk-nodejs library code under Nextjs (React). We built and call the following test function using the ESM-client-side example code server-side:
'use server';
import ziti from '@openziti/ziti-sdk-nodejs';
export async function TestZiti() {
// Somehow provide path to identity file, e.g. via env var
const zitiIdentityFile = process.env.ZITI_IDENTITY_FILE ?? './test_identity.json';
// Authenticate ourselves onto the Ziti network
await ziti.init(zitiIdentityFile).catch((err) => { /* probably exit */ });
const on_resp_data = (obj) => {
console.log(`response is: ${obj.body.toString('utf8')}`);
};
// Perform an HTTP GET request to a dark OpenZiti web service
ziti.httpRequest(
'myDarkWebService', // OpenZiti Service name or HTTP origin part of the URL
undefined, // schemeHostPort parm is mutually-exclusive with serviceName parm
'GET',
'/', // path part of the URL including query params
['Accept: application/json'], // headers
undefined, // optional on_req cb
undefined, // optional on_req_data cb
on_resp_data // optional on_resp_data cb
);
}
In order to get it working, we needed to add the dependency node-loader
and the following Webpack config in the next.config.js
. What we did is copying the ziti_sdk_nodejs.node
-file to the build directory to make it available (since Nextjs performs build optimization). Additionally we hat to define the node-loader, that is able to load the binary:
webpack: (config, { isServer, nextRuntime }) => {
if (isServer && nextRuntime === "nodejs") {
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
config.plugins.push(
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, 'node_modules/@openziti/ziti-sdk-nodejs/build/Release/ziti_sdk_nodejs.node'),
to: path.resolve(__dirname, '.next/server/vendor-chunks//_next/ziti_sdk_nodejs.node'),
},
],
})
);
config.externals = [
...config.externals,
"_http_server"
];
config.module.rules.push({
test: /\.node$/,
loader: "node-loader",
options: {
name: "ziti_sdk_nodejs.node",
},
});
}
return config;
}
Running this example, we get the following error message:
⨯ ./node_modules/.pnpm/@[email protected]/node_modules/@mapbox/node-pre-gyp/lib/util/nw-pre-gyp/index.html
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> <!doctype html>
| <html>
| <head>
Import trace for requested module:
./node_modules/.pnpm/@[email protected]/node_modules/@mapbox/node-pre-gyp/lib/util/nw-pre-gyp/index.html
./node_modules/.pnpm/@[email protected]/node_modules/@mapbox/node-pre-gyp/lib/ sync ^\.\/.*$
./node_modules/.pnpm/@[email protected]/node_modules/@mapbox/node-pre-gyp/lib/node-pre-gyp.js
./node_modules/.pnpm/@[email protected]/node_modules/@openziti/ziti-sdk-nodejs/lib/ziti.js
./src/app/test.tsx
./src/app/page.tsx
This is because in @openziti/ziti-sdk-nodejs/lib/ziti.js
line 32 to 44, always the else
-statement is used. typeof require.context == 'function'
is never true, because require
is undefined:
if (typeof require.context == 'function') {
importAll( require.context("../build/", true, /\.node$/) );
} else {
const binary = require('@mapbox/node-pre-gyp');
const path = require('path')
const binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')), {debug: false});
binding = require(binding_path);
}
However, if we modify the if-statement to always true, require.context("../build/", true, /\.node$/)
works and loads the binary despite typeof require.context == 'function'
being false. This works flawlessly. 🎉
// if (typeof require.context == 'function') {
if (true) {
importAll( require.context("../build/", true, /\.node$/) );
} else {
const binary = require('@mapbox/node-pre-gyp');
const path = require('path')
const binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')), {debug: false});
binding = require(binding_path);
}
We don't want to modify the package source in production. Are there any possibilities to get it running without modifying the package source?