Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESM with Webpack not running #88

Open
nzedler opened this issue Sep 10, 2024 · 1 comment
Open

ESM with Webpack not running #88

nzedler opened this issue Sep 10, 2024 · 1 comment

Comments

@nzedler
Copy link

nzedler commented Sep 10, 2024

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?

@nzedler
Copy link
Author

nzedler commented Sep 10, 2024

The ziti.js else-statement can NEVER work in environments with Webpack, see the official answer mapbox/node-pre-gyp#308 (comment) to the question if node-pre-gyp can support Webpack.

It seems to me that we have to modify the if-statement to allow Webpack environments (or somehow fulfill the if-statement when running import ziti from '@openziti/ziti-sdk-nodejs', but I have no clue how)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant