Webpack bundle of my lambda function has require statements (doesn't actually bundle)

Viewed 574

So this is a pretty weird one. I am using Webpack to bundle (and build) some lambda functions written in TypeScript, but the lambdas fail to run because Webpack outputs 'bundles' that aren't actually bundled. They still include 'require' statements for locally defined TypeScript modules/helpers.

I'm sure I'm missing something stupid, but I'd certainly appreciate an assist!

tsconfig

{
  "compilerOptions": {
    "module": "commonjs",
    "allowJs": true,
    "noEmit": false,
    "esModuleInterop": true,
    "noImplicitAny": false,
    "strictNullChecks": false,
    "isolatedModules": false,
    "resolveJsonModule": true,
  },
  "exclude": [],
  "include": [
    "src/lambda"
  ],
  "ts-node": {
    "compilerOptions": {
      "module": "commonjs"
    }
  }
}

webpack.config.ts

import * as webpack from 'webpack';
import * as path from 'path';
import nodeExternals from 'webpack-node-externals';

const handler = (percentage: number, message: string) => {
  // eslint-disable-next-line no-console
  console.log(`${(percentage * 100).toFixed()}% ${message}`);
};

module.exports = {
  entry: {
    api: ['./src/lambda/api.ts']
  },
  node: {
    fs: 'empty',
  },
  resolve: {
    extensions: ['.js', '.ts', '.tsx', '.scss'],
  },
  output: {
    libraryTarget: 'commonjs',
    path: path.resolve('./build/'),
    filename: '[name].js',
  },
  target: 'node',
  externals: [nodeExternals()],
  module: {
    noParse: /node_modules/,
    rules: [
      {
        test: [/\.ts$/, /\.tsx$/],
        exclude: /(node_modules)/,
        use: [
          {
            loader: 'ts-loader',
            options: {
              configFile: 'tsconfig.lambda.json',
            },
          },
        ],
      },
    ],
  },
  plugins: [new webpack.ProgressPlugin(handler)],
};

api.ts

import { helper } from './api/helper';

export const handler = (event, context, callback) => {
  callback(null, {
    statusCode: 400,
    body: helper(),
  });
};

api/helper.ts

export const helper = () => {
  return 'Hello World';
};


webpack output

!function(e,r){for(var t in r)e[t]=r[t]}(exports,function(e){var r={};function t(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}return t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:n})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,r){if(1&r&&(e=t(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(t.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var o in e)t.d(n,o,function(r){return e[r]}.bind(null,o));return n},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.p="",t(t.s=0)}([function(e,r,t){e.exports=t(1)},function(e,r){"use strict";r.__esModule=!0,r.handler=void 0;var t=require("./api/helper");r.handler=function(e,r,n){n(null,{statusCode:400,body:t.helper()})}}]));

Note the require("./api/helper") towards the end of the function. Why isn't it pulled in?? Why is there a require statement in the 'bundled' output? Shouldn't the helper function be included in the bundle?

Thanks!

2 Answers

The problem here is the following line:

module: {
    noParse: /node_modules/, // < --- this guy breaks everything
    rules: [
      {
        test: [/\.ts$/, /\.tsx$/],
        exclude: /(node_modules)/,
        use: [
          {
            loader: 'ts-loader',
            options: {
              configFile: 'tsconfig.lambda.json',
            },
          },
        ],
      },
    ],
  },

remove noParse and everything will work as expected, exclude: /(node_modules)/ is enough.

UPD: thb I don't know why exactly noParse causes such webpack behaviour in your app. Here is the place where noParse handled.

A bunch of internal packages can be scoped but:

var _packageName = require('package-name');

gets spit out in the compiled versions when it should really be require('@scope/package-name') by looking at the package.json name field.

On Webpack 4.17 and below, this error occurs for scoped applications. It should be installed into @scope/package-name module or it cannot be read to build(bundle).

Related