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