Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

All environment variables are missing #274

Closed
zamirdan opened this issue Nov 14, 2017 · 18 comments
Closed

All environment variables are missing #274

zamirdan opened this issue Nov 14, 2017 · 18 comments

Comments

@zamirdan
Copy link

zamirdan commented Nov 14, 2017

This is a Bug Report

Description

All environment variables are missing.
I have built very simple project with only one function:
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
body: JSON.stringify({
message: process.env.MY_VAR,
input: event,
}),
};

callback(null, response);
};

I have added to the yml file under provider this lines
environment:
MY_VAR: abc

when I run it without the plugin it works, but after I'm installing the plugin it doesn't.

Similar or dependent issue(s):

@HyperBrain
Copy link
Member

Hi @zamirdan , thanks for raising the issue.

This is very strange. The plugin does not do anything with the environment variables and that should be handled completely by Serverless. Are the variables missing when you deploy the function, or only if you run the code locally? And which tool do you use to run them?

Can you post the complete serverless.yml, and the webpack config?

@zamirdan
Copy link
Author

zamirdan commented Nov 14, 2017

Thank you for the quick reply.
I am missing the environment variables in both situations (local and deploy).
I use "sls invoke function/local" to run my tests.

yml file:

service: testEnv

provider:
  name: aws
  runtime: nodejs6.10
  versionFunctions: false
  region: us-east-1
  environment:
    MY_VAR: abc

package:
  individually: true

functions:
  testEnv:
    handler: functions/testEnv.hendler

plugins:
  - serverless-webpack

@HyperBrain
Copy link
Member

Can you try the same with one of the provided examples, preferrably https://github.com/serverless-heaven/serverless-webpack/tree/master/examples/serverless-offline or https://github.com/serverless-heaven/serverless-webpack/blob/master/examples/babel-dynamically-entries?
Just add an environment definition to the serverless.yml and print it in one of the functions? It looks to me that something with your function configuration is wrong, but it would be better to start from a known working example to find out, what exactly is wrong.

@zamirdan
Copy link
Author

zamirdan commented Nov 14, 2017

Hi,
Thank you, I have found the problem.
It was in the webpack.config.js file...
target: 'node' was missing.
I could pack deploy and invoke all functions without it, but it a must for environment variables.
Thanks

Note... I read the documentation again and it's a bit confusing...
image

@HyperBrain
Copy link
Member

HyperBrain commented Nov 14, 2017

@zamirdan Thanks for the feedback 👍
You're right. This section of the README only targets the entry definition. Maybe it would be good if the plugin automatically would set the target property to node too.

@HyperBrain
Copy link
Member

Opened a separate feature request for the improvement. Closing this issue now.

@swarajgiri
Copy link

swarajgiri commented Dec 7, 2017

Hey @HyperBrain - I am facing the same issue when trying to access process.env.BLA in functions.

'TypeError: Cannot read property \'BLA\' of undefined'

serverless.yml

frameworkVersion: "=1.24.1"
package:
  individually: true

provider:
  name: aws
  runtime: nodejs6.10
  stage: dev
  cfLogs: true
  region: us-east-1
  environment:
    BLA: test

custom:
  webpackIncludeModules: true 

plugins:
  - serverless-webpack
  - serverless-offline-scheduler
  - serverless-pseudo-parameters
  - serverless-offline

webpack.config.js

'use strict'

const nodeExternals                 = require('webpack-node-externals'),
      webpack                       = require('webpack'),
      path                          = require('path'),
      UglifyJSPlugin                = require('uglifyjs-webpack-plugin'),
      slsw                          = require('serverless-webpack'),
      LodashModuleReplacementPlugin = require('lodash-webpack-plugin');

module.exports = {
    entry: slsw.lib.entries,
    output: {
        libraryTarget: 'commonjs',
        path: path.join(__dirname, '.webpack'),
        filename: '[name].js'
    },
    target: 'node',
    externals: [
        nodeExternals(),
    ], 
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                include: [
                    path.resolve(__dirname)
                ],
                exclude: [
                    path.resolve(__dirname, 'node_modules'),
                ],
                query: {
                    presets: [
                        [
                            'env',
                            {
                                'targets': {
                                    'node': '6.10',
                                    'uglify': false
                                },
                                'useBuiltIns': true,
                                'modules': false,
                                'debug': false
                            }
                        ]
                    ],
                    plugins: [
                        'transform-runtime',
                        'transform-async-to-generator',
                        'transform-export-extensions',
                        'transform-es2015-modules-commonjs',
                        'lodash',
                    ],
                }
            },
            {
                test: /\.json$/,
                loader: 'json-loader'
            }
        ]
    },
    plugins: [
        new LodashModuleReplacementPlugin({
            'collections': true,
            'shorthands': true
        }),
        new webpack.DefinePlugin({
            'process.env': {NODE_ENV: JSON.stringify('production')}
        }),
    ],
};

@HyperBrain
Copy link
Member

HyperBrain commented Dec 7, 2017

@swarajgiri Your configuration looks good. Do you have the problem with more than one project or only with this one?

'TypeError: Cannot read property \'BLA\' of undefined' would even mean that process.env undefined.

You could do some checks:

  • serverless package and check the generated CF template in .serverless for the function resource (check the environment)
  • Disable all plugins but serverless-webpack and see if the environment variables are there
  • try babel-preset-node6 instead of env to verify.

Strange is, that serverless-webpack does not do anything with the configuration of your functions - only serverless composes them. If the function configuration in the CF template or in the AWS console show the variable, then something with the configuration (webpack config) is wrong.

@swarajgiri
Copy link

@HyperBrain - I just encountered this issue in a new project. Wasn't using env variables before.
Also, checked aws lambda console. It shows the environment variables there.
Strange that i cannot access it in the functions.

Will try out the checks and report back.

@swarajgiri
Copy link

Tried out the suggestions, found that the cf template contains the env variables and they are also available on aws lambda console. Its just that the function does not find them.

function

module.exports.handler = (event, context, cb) => {
    const response = {
        statusCode: 200,
        body: JSON.stringify({
            'data':   process.env.BLA,
        })
    };
    cb(null, response);
};

serverless.yml

plugins:
  - serverless-webpack
  - serverless-offline

and
webpack.config.js

    presets: [
        'node6'
    ],

Same error in both cases
"errorMessage":"Uncaught error in your 'moveToPriorityQueue' handler","errorType":"TypeError","stackTrace":["TypeError: Cannot read property 'BLA' of undefined"

The env vars are present in cf template

    "MoveToPriorityQueueLambdaFunction": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "FunctionName": "content-processing-dev-moveToPriorityQueue",
        "Handler": "moveToPriorityQueue.handler",
        "MemorySize": 128,
        "Role": {
          "Fn::GetAtt": [
            "IamRoleLambdaExecution",
            "Arn"
          ]
        },
        "Runtime": "nodejs6.10",
        "Timeout": 10,
        "Description": "Move processing requests to priority queues",
        "Environment": {
          "Variables": {
            "BLA": "test"
          }
        }
      },
    },

Node: v8.9.1
OS: Ubuntu 16.04.3 LTS

@swarajgiri
Copy link

@HyperBrain - Any ideas on what might be causing this?

@HyperBrain
Copy link
Member

@swarajgiri Cannot read property 'BLA' of undefined actually means that it could not find process.env itself. The main reason for this is a missing target: "node" setting in the webpack config. Can you check that?

@swarajgiri
Copy link

@HyperBrain - I havetarget: node is there in webpack config but process.env is always undefined

const nodeExternals                 = require('webpack-node-externals'),
      webpack                       = require('webpack'),
      path                          = require('path'),
      UglifyJSPlugin                = require('uglifyjs-webpack-plugin'),
      slsw                          = require('serverless-webpack'),
      LodashModuleReplacementPlugin = require('lodash-webpack-plugin');

module.exports = {
    entry: slsw.lib.entries,
    output: {
        libraryTarget: 'commonjs',
        path: path.join(__dirname, '.webpack'),
        filename: '[name].js'
    },
    target: 'node',
    externals: [
        nodeExternals(),
        'aws-sdk',
    ], // exclude external modules,
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                include: [
                    path.resolve(__dirname)
                ],
                exclude: [
                    path.resolve(__dirname, 'node_modules'),
                ],
                query: {
                    presets: [
                        [
                            'env',
                            {
                                'targets': {
                                    'node': '6.10',
                                    'uglify': true
                                },
                                'useBuiltIns': true,
                                'modules': false,
                                'debug': false
                            }
                        ]
                    ],
                    plugins: [
                        'transform-runtime',
                        'transform-async-to-generator',
                        'transform-export-extensions',
                        'transform-es2015-modules-commonjs',
                        'lodash',
                    ],

                }
            },
            {
                test: /\.json$/,
                loader: 'json-loader'
            }
        ]
    },
    plugins: [
        new LodashModuleReplacementPlugin({
            'collections': true,
            'shorthands': true
        }),
        new UglifyJSPlugin({
            cache : true,
            parallel : true,
        }),
        new webpack.DefinePlugin({
            'process.env': {NODE_ENV: JSON.stringify('production')}
        }),
    ],
};

@HyperBrain
Copy link
Member

I think it's your define here:

new webpack.DefinePlugin({
            'process.env': {NODE_ENV: JSON.stringify('production')}
        }),

You declare the complete process.env as compile time constant.
Can you try to change that to:

new webpack.DefinePlugin({
            'process.env.NODE_ENV': 'production'
        }),

Then only the very specific env var is replaced in the code

@swarajgiri
Copy link

Tried that. process.env is still undefined.

Would it help if i create a repo replicating the issue?

@HyperBrain
Copy link
Member

But can you first remove the define plugin from your webpack config completely, just to check if it still isn't some configuration issue there? Then a repro repo would help.

@swarajgiri
Copy link

Tried that too. Still undefined.

@tyrauber
Copy link

tyrauber commented May 15, 2020

@HyperBrain I am running into this issue as well. I am applying opt:stage to provider as the environment variable, STAGE. The expectation is that process.env.STAGE would be available in webpack.config.js, but it is undefined. The purpose of doing this would be able to compile different code for various environments, for example where the output changes depending upon the stage, or other configuration variables.

# serverless.yml
service: serverless-webpack-env-test

provider:
  name: aws
  runtime: nodejs12.x
  stage: ${opt:stage, 'dev'}
  region: ${self:custom.settings.region, 'us-east-1'}
  environment:
    STAGE: ${opt:stage, 'dev'}

frameworkVersion: '>=1.0.0 <2.0.0'

environment:
  NODE_ENV: production

custom:
  webpack:
    webpackConfig: 'webpack.config.js'  

plugins:
  - serverless-webpack
  - serverless-offline
// webpack.config.js
if(process.env.STAGE == undefined)
  console.log("env", process.env)
  throw "STAGE ENV variable is undefined"

const serverless =  {
  target: 'node'
}

module.exports = serverless

Run $ sls offline to see the issue.

Perhaps there is another way of meeting this requirement that I am not seeing, but I am surprised that the serverless env variables aren't available to webpack.config.js.

Any suggestions would be greatly appreciated.

Edit:

You can access the provider env variables in the webpack.config.js, like so:

const env = slsw.lib.serverless.service.provider.environment

Originally posted by @pizzarob in #222 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants