Search code examples
node.jswebpacklambdabundler

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


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!


Solution

  • 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.