Search code examples
node.jsazurewebpackazure-blob-storageterser

Webpack @azure/storage-blob node-fetch AbortSignal issue


I am facing one particular issue often talked about at various places the link I will share later. The problem is related to the webpack bundling. My nodeJS application uses @azure/storage-blob library to fetch the data while it works perfectly fine when not bundled but as soon as I bundle the application using webpack the app starts to throw the following error:

Stack Trace: TypeError: Expected signal to be an instanceof AbortSignal at new Request (webpack://ECPNodeAPI/./node_modules/node-fetch/lib/index.mjs?:1229:10) at eval (webpack://ECPNodeAPI/./node_modules/node-fetch/lib/index.mjs?:1416:19) at new Promise () at fetch (webpack://ECPNodeAPI/./node_modules/node-fetch/lib/index.mjs?:1414:9) at NodeFetchHttpClient2.eval (webpack://ECPNodeAPI/./node_modules/@azure/core-http/es/src/nodeFetchHttpClient.js?:69:74) at step (webpack://ECPNodeAPI/./node_modules/@azure/core-http/node_modules/tslib/tslib.es6.js?:195:19) at Object.eval [as next] (webpack://ECPNodeAPI/./node_modules/@azure/core-http/node_modules/tslib/tslib.es6.js?:142:14) at eval (webpack://ECPNodeAPI/./node_modules/@azure/core-http/node_modules/tslib/tslib.es6.js?:128:67) at new Promise () at __awaiter (webpack://ECPNodeAPI/./node_modules/@azure/core-http/node_modules/tslib/tslib.es6.js?:110:10)

The issue is mentioned in node-fetch issues: https://github.com/node-fetch/node-fetch/issues/784. While the latest version claims to have this issue fixed. But @azure/storage-blob is using the old version of node-fetch.

Solutions that I have tried but no luck.

Does anyone else have any other workaround for the same?


Solution

  • I was able to come over with this problem using Terser Plugin. Here is the webpack.config.js file that might help you fix the issue.

    import path from 'path';
    import TerserPlugin from 'terser-webpack-plugin';
    import nodeExternals from 'webpack-node-externals';
    
    const __dirname = path.dirname('.');
    
    const isProd = true; // process.env.NODE_ENV === 'production';
    
    export default {
      mode: isProd ? 'production' : 'development',
      target: 'node',
      externals: [nodeExternals()],
      entry: './index.mjs',
      resolve: {
        extensions: ['.js', '.ts'],
      },
      output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'api.bundle.js',
        clean: true,
      },
      optimization: {
        minimize: false,
        minimizer: [
          new TerserPlugin({
            terserOptions: {
              keep_fnames: /AbortSignal/,
              sourceMap: true,
            },
          }),
        ],
      },
      module: {
        rules: [{
            test: /\.html$/,
            use: 'raw-loader'
          },
          {
            test: /\.js$/,
            loader: 'esbuild-loader',
            options: {
              //    loader: 'jsx',  // Remove this if you're not using JSX
              target: 'es2018', // Syntax to compile to (see options below for possible values)
            },
          },
          {
            test: /\.tsx?$/,
            loader: 'esbuild-loader',
            options: {
              loader: 'ts', // Or 'ts' if you don't need tsx
              target: 'es2015',
            },
          },
        ],
      },
    };