Unable to run lambda in docker image - node.js

I currently have an AWS Lambda that I've been working on that I would like to build and run from a docker image. I'm using the aws-lambda-node:16 image as my base image. But I can't seem to get the docker image to properly pick up the handler from my javascript file to run the lambda.
I have tested the lambda's execution outside the docker image with lambda-local and the lambda runs fine in my local environment. It just seems that something is up with the docker container.
My Dockerfile:
FROM amazon/aws-lambda-nodejs:16
COPY dist/blacklist-ips/app.js ${LAMBDA_TASK_ROOT}
COPY package.json pnpm-lock.yaml ${LAMBDA_TASK_ROOT}/
RUN npm i -g pnpm && pnpm install --production
CMD [ "app.handle" ]
My Webpack config:
import { resolve } from 'path';
import { default as webpack } from 'webpack';
import TerserPlugin from 'terser-webpack-plugin';
const config = (env: any, argv: any): webpack.Configuration => {
return {
mode: env.production ? 'production' : 'development',
entry: {
'blacklist-ips': resolve(__dirname, 'src', 'blacklist-ips', 'blacklist-ips.ts')
},
output: {
path: resolve(__dirname, 'dist'),
filename: '[name]/app.js',
libraryTarget: 'commonjs2'
},
devtool: false,
target: 'node',
externals: [
'#aws-sdk/client-cloudwatch-logs',
'#aws-sdk/client-wafv2',
'luxon',
'tslib'
],
resolve: {
extensions: [ '.ts', '.js', '.json' ]
},
module: {
rules: [
{
test: /.ts$/,
loader: 'ts-loader'
}
]
},
optimization: {
minimize: env.production,
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
mangle: false
}
})
]
}
}
}
export default config;
My handler function is being properly exported in the webpack bundle:
const handler = async () => {
...lambda logic
};
exports.handler = handler;
I'm stumped as to why it's not working correctly with the Docker container...

Your CMD is app.handle while your function name is handler. You should change the CMD to be app.handler.

Related

importing react-virtuoso throws error "You may need an appropriate loader to handle this file type."

My project works fine but after installing and importing react-virtuoso it throws error.
ERROR in ./~/react-virtuoso/dist/index.mjs
Module parse failed: C:\Users\Rocky\Documents\betterdash\node_modules\react-virtuoso\dist\index.mjs Unexpected token (364:22)
You may need an appropriate loader to handle this file type.
| }
| const Component = forwardRef((propsWithChildren, ref) => {
| const { children, ...props } = propsWithChildren;
| const [system2] = useState(() => {
| return tap(init(systemSpec), (system22) => applyPropsToSystem(system22, props));
# ./src/components/order-viewer.jsx 13:21-46
# ./src/main.js
# multi whatwg-fetch ./src/main.js
Here is my webpack.config.js
const path = require("path");
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: ["whatwg-fetch", "./src/main.js"],
output: {
path: path.join(__dirname, "dist"),
filename: "bundle.js",
publicPath: "/",
},
module: {
loaders: [
{
test: /.jsx?$/,
loader: "babel-loader",
include: path.join(__dirname, "src"),
exclude: /node_modules/,
query: {
presets: ["es2015", "react", "flow"],
plugins: ["transform-flow-strip-types"],
},
},
{
test: /\.s?css$/,
loaders: ExtractTextPlugin.extract({
use: ["css-loader", "sass-loader"],
fallback: "style-loader",
}),
},
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new ExtractTextPlugin({
filename: "style.css",
allChunks: true,
disable: process.env.NODE_ENV === "development",
}),
],
devtool: "source-map",
};
I tried deleting node_modules then run npm install but it doesn't solve the problem. If I remove the part of code that imports the react-virtuoso the error also gone.
import { Virtuoso } from "react-virtuoso";
I had the same problem with Jest and I noticed they have renamed the index.js file to index.cjs from version 4.0.0 to version 4.0. I would assume you have to do something similar with Webpack.
transform: {
'^.+\\.(cjs|js|jsx)$': [
'babel-jest',
{ configFile: './babel.config.js' }
]
},
If you install V4.0.0 it will work if that is the same issue.

Webpack Config to build sdk for both Node and Browser

Can someone help me in figuring out what should be the webpack sdk config to build sdk for both web and browser?
My current config looks like this
const path = require('path');
let baseConfig = {
mode: 'production',
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'sdk/js-sdk.js',
libraryTarget: 'umd',
library: 'jsSdk',
globalObject: 'this'
},
resolve: {
extensions: [ ".ts", ".js"]
},
externals: {
"request-promise-native": "request-promise-native",
"request": "request"
},
module: {
rules: [
{ test: /\.ts$/, use: 'ts-loader' }
]
}
}
module.exports = baseConfig
Which I am building using following command
"pn-dev-build": "rm -rf dist && npm version patch && webpack --mode=development && npm publish --registry http://localhost:4873",
And then if I install it in my vue-nuxt project it gives following error
fs in ./node_modules/request/lib/har.js friendly-errors 09:06:34
net in ./node_modules/forever-agent/index.js, ./node_modules/tough-cookie/lib/cookie.js and 1 other
friendly-errors 09:06:34
tls in ./node_modules/forever-agent/index.js, ./node_modules/tunnel-agent/index.js
Can someone help me in solving the above error?
Multiple entry point approach is not the best idea here because you are bundling for two different targets(node and browser) with same config
Better would be to export a array with two configuration something like this ( and in this approch you can use multiple entry point to split your browser bundle and other stuff to make your website performant )
in webpack.config.js ( use this file as Webpack config )
const webpackBrowserConfig = require("./webpack.config.browser.js");
const webpackServerConfig = require("./webpack.config.server.js");
module.exports = [webpackServerConfig, webpackBrowserConfig];
in webpack.config.browser.js
module.exports = {
target: 'web',
mode: 'production',
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
// your browser related config
},
resolve: {
extensions: [ ".ts", ".js"]
},
externals: {
"request-promise-native": "request-promise-native",
"request": "request"
},
module: {
rules: [
{ test: /\.ts$/, use: 'ts-loader' }
]
}
}
and in webpack.config.server.js
module.exports = {
target: 'node',
mode: 'production',
entry: './src/serverIndex.ts',
output: {
path: path.resolve(__dirname, 'dist')
// your server related config
},
resolve: {
extensions: [ ".ts", ".js"]
},
externals: {
"request-promise-native": "request-promise-native",
"request": "request"
},
module: {
rules: [
{ test: /\.ts$/, use: 'ts-loader' }
]
}
}
you can also create this in same file and reduce some duplication ( whichever works for you ) I showed this approach with two different file for clarity
create a file as an entry point for the server, and another for the browser.
let baseConfig = {
mode: 'production',
entry: ['browser.ts','server.ts'],
...
}
browser.ts contains all browser-specific logic, and server.ts contains all server-specific logis.

Select correct environment.ts in webpack

Inside my webpack.config.js, I am returning the correct webpack config file based on passed env:
module.exports = (env) => {
return require(`./webpack.${env}.js`)
};
Inside my webpack.prod.js:
module.exports = {
entry: './src/app.ts',
target: 'node',
module: {
rules: [{test: /.tsx?$/, use: 'ts-loader'}]
},
mode: 'production',
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'app.js',
}
};
Then I have inside /src/environments, two environment files:
environment.ts
environment.prod.ts
In any of my other services, I refer to environment as:
import {environment} from '../environments/environment';
Actually I got this idea from angular-cli. And I would like to also use this in node.js. My question is how do I specify in the webpack to rename environment.prod.ts and use that when building for production?
In node environment specific context is toggled with variable NODE_ENV
So this is what I did and it works as I expected. First I install file-replace-loader, then I modified the webpack as follows:
const {resolve} = require('path');
...
module: {
rules: [{
test: /.tsx?$/,
use: 'ts-loader'
},{
test: /environment\.ts?$/,
loader: 'file-replace-loader',
options: {
condition: true,
replacement: resolve('./src/environments/environment.prod.ts'),
async: true
}
}
]
...
I set the condition to true since I am modifying the webpack.prod.js.

Publish multiple Vuejs components in one project to npm using webpack

Im trying to publish a project to npm that contains two or more Vue components so i can import, register and use both components like this:
import Component1 from 'npm-package'
import Component2 from 'npm-package'
this is my webpack file:
const webpack = require('webpack');
const merge = require('webpack-merge');
const path = require('path');
var config = {
output: {
path: path.resolve(__dirname + '/dist/'),
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
include: __dirname,
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue'
},
{
test: /\.css$/,
loader: 'style!less!css'
}
]
},
externals: {
moment: 'moment'
},
plugins: [
new webpack.optimize.UglifyJsPlugin( {
minimize : true,
sourceMap : false,
mangle: true,
compress: {
warnings: false
}
} )
]
};
module.exports = [
merge(config, {
entry: path.resolve(__dirname + '/src/plugin.js'),
output: {
filename: 'vue-project.min.js',
libraryTarget: 'window',
library: 'VueProject',
}
}),
merge(config, {
entry: path.resolve(__dirname + '/src/index.js'),
output: {
filename: 'vue-project.js',
libraryTarget: 'umd',
library: 'vue-project',
umdNamedDefine: true
},
resolve: {
extensions: ['', '.js', '.vue'],
alias: {
'src': path.resolve(__dirname, '../src'),
'components': path.resolve(__dirname, '../src/components')
}
}
})
];
and this is the index.js file i'm using as the entry point for the build process
import Component1 from './components/folder1/Component1.vue'
import Component1 from './components/folder2/Component2.vue'
export default {
components: {
Component1,
Component2
}
}
The build process using npm run build works fine and i can publish the project to npm and install it using npm install. Importing and using it works fine to, but when i run my project i get the error:
failed to mount component: template or render function not defined.
All other posts o found regarding this error did not solve my problem, as none of them tried to export multiple components.
Both components work completely as intended when im publishing them in two different projects.
What am i missing here? Thanks in advance!
You don't need to export using the components property, you simply need to do:
export {
Component1,
Component2
}
You would then do:
import {Component1} from 'npm-package';
import {Component2} from 'npm-package';
or
import {Component1, Component2} from 'npm-package';
see: https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export

Build is successful in Jenkins but AWS-Codebuild is giving plugin error

I have a project which is building successfully on Jenkins but when I try to build using AWS Codebuild it gives a plugin error. The project is basically a NodeJS and ReactJS project. We do not want to move to Jenkins as we are serverless and installing jenkins requires one EC2 instance. We do not want to maintain any server. I have tried below environments for AWS codebuild:
aws/codebuild/ubuntu-base:14.04
aws/codebuild/nodejs:6.3.1
aws/codebuild/nodejs:7.0.0
aws/codebuild/nodejs:4.4.7
The first four commands of my buildspec.yml is executed only when I use aws/codebuild/ubuntu-base:14.04 codebuild environment. Otherwise only last three commands are part of my buildspec.yml
Below is my buildspec.yml
version: 0.1
phases:
build:
commands:
- sudo apt-get update
- curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
- sudo apt-get install -y nodejs
- sudo apt-get install -y build-essential
- npm install
- npm run dev
- aws s3 cp --recursive dist/ s3://$AWS_BUCKET_NAME/ --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers
Below is my error logs in AWS codebuild during npm run
ERROR in
Child html-webpack-plugin for "index.html":
+ 3 hidden modules
Also, I get following warning during npm install in Codebuild but I do not get the this warning in Jenkins
npm WARN deprecated babel-plugin-react-hot#1.0.4: This plugin is no longer maintained. Please use babel-plugin-react-transform with react-transform-hot-reload instead.
Below is my webpack.config.js
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var FlowStatusWebpackPlugin = require('flow-status-webpack-plugin');
module.exports = {
entry: [
'./src/app/index.js'
],
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js'
},
module: {
loaders: [
{
test: /\.json$/,
loader: 'json'
},
{
test: /\.js$/,
exclude: /(node_modules|test)/,
loaders: ["babel-loader"]
},
{
test: /\.(css|scss)$/,
loaders: ['style', 'css', 'sass-loader']
},
{
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
loader: 'url-loader',
options: {
limit: 100000,
name: 'assets/[hash].[ext]'
}
},
{
test: /\.styl$/,
loader: 'style-loader!css-loader!postcss-loader!stylus-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: __dirname + '/src/app/index.html',
filename: 'index.html',
inject: 'body'
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new webpack.DefinePlugin({
"process.env": {
'NODE_ENV': JSON.stringify('dev')
}
}),
new FlowStatusWebpackPlugin({
failOnError: true
})
],
devtool: 'source-map',
node: {
tls: "empty",
fs: "empty"
},
resolve: {
root: path.resolve(__dirname),
alias: {
'~': 'src',
},
extensions: ['', '.js', '.jsx']
},
};
new HtmlWebpackPlugin({
template: __dirname + '/src/app/index.html',
filename: 'index.js',
inject: 'body'
})
filename option is supposed to be a javascript file? i.e: filename: index.js

Resources