serverless-heaven / serverless-webpack

Serverless plugin to bundle your lambdas with Webpack

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Did 4.0.0+ become incompatible with awesome-typescript-loader & hot-reload?

SpencerGreene opened this issue · comments

This is a Bug Report (or misconfiguration on my side)

Description

  • What went wrong?
    I upgraded from serverless-webpack 2.2.3 to latest, and serverless-offline no longer hot-reloads serverless-offline in local. It throws an error "Unhandled rejection TypeError: Cannot read property 'watcher' of undefined" as further detailed below. Digging into awesome-typescript-loader, it appears that "watching.compiler.watchFileSystem.wfs" is undefined.

In triangulating versions, I see that this error is not thrown for serverless-webpack up to and including 3.1.2. It is thrown for 4.0.0 onward.

  • What did you expect should have happened?
    When saving a change to the code of an endpoint, the running serverless-offline should recompile and continue without throwing error.

  • What was the config you used?

var path = require('path');
var webpack = require('webpack');
var slsw = require('serverless-webpack');
var GitRevisionPlugin = require('git-revision-webpack-plugin');
var gitRevisionPlugin = new GitRevisionPlugin();
var nodeExternals = require('webpack-node-externals');

module.exports = {
    entry: slsw.lib.entries,
    devtool: 'inline-source-map',
    target: 'node',
    externals: [
        'aws-sdk',
        // Possible drivers for knex - we'll ignore them
        'sqlite3',
        'mariasql',
        'mssql',
        'mysql2',
        'mysql',
        'oracle',
        'strong-oracle',
        'oracledb',
        'pg-query-stream',
        nodeExternals()
    ],
    module: {
      loaders: [
          {
              test: /\.ts(x?)$/,
              loader: 'awesome-typescript-loader',
              exclude: /node_modules/,
              query: {
                  presets: ['es2015', 'stage-0']
              }
          }
      ]

      },
    resolve: {
        extensions: ['.ts', '.js', '.tsx', '.jsx']
    },
    output: {
        libraryTarget: 'commonjs',
        path: path.join(__dirname, '.webpack'),
        filename: '[name].js'
    },
    plugins: [
        new webpack.IgnorePlugin(/\.\/native/),
        new webpack.DefinePlugin({
          'VERSION': JSON.stringify(gitRevisionPlugin.version()),
          'COMMITHASH': JSON.stringify(gitRevisionPlugin.commithash()),
          'BRANCH': JSON.stringify(gitRevisionPlugin.branch()),
        })    
      ]
};

and tsconfig.json:

{
  "compilerOptions": {
    "baseUrl": "",
    "target": "es2015",
    "module": "commonjs",
    "sourceMap": true,
    "allowJs": false,
    "alwaysStrict": true
  },
  "exclude": [
    "node_modules"
  ],
  "lib": [
    "es7",
    "esnext"
  ],
  "types": [
    "node",
    "aws-sdk"
  ]
}
  • What stacktrace or error message from your provider did you see?
Unhandled rejection TypeError: Cannot read property 'watcher' of undefined
    at Compiler.<anonymous> (/Users/sgreene/src/gl-api/node_modules/awesome-typescript-loader/src/instance.ts:369:54)
    at next (/Users/sgreene/src/gl-api/node_modules/tapable/lib/Tapable.js:204:14)
    at Compiler.compiler.plugin (/Users/sgreene/src/gl-api/node_modules/webpack/lib/CachePlugin.js:48:5)
    at Compiler.applyPluginsAsyncSeries (/Users/sgreene/src/gl-api/node_modules/tapable/lib/Tapable.js:206:13)
    at Watching._go (/Users/sgreene/src/gl-api/node_modules/webpack/lib/Compiler.js:48:17)
    at Watching.compiler.readRecords.err (/Users/sgreene/src/gl-api/node_modules/webpack/lib/Compiler.js:40:9)
    at Compiler.readRecords (/Users/sgreene/src/gl-api/node_modules/webpack/lib/Compiler.js:391:11)
    at new Watching (/Users/sgreene/src/gl-api/node_modules/webpack/lib/Compiler.js:37:17)
    at Compiler.watch (/Users/sgreene/src/gl-api/node_modules/webpack/lib/Compiler.js:222:20)
    at startWatch (/Users/sgreene/src/gl-api/node_modules/serverless-webpack/lib/wpwatch.js:37:32)
    at BbPromise.fromCallback.cb (/Users/sgreene/src/gl-api/node_modules/serverless-webpack/lib/wpwatch.js:75:17)
    at tryCatcher (/Users/sgreene/src/gl-api/node_modules/serverless-webpack/node_modules/bluebird/js/release/util.js:16:23)
    at Function.Promise.fromNode.Promise.fromCallback (/Users/sgreene/src/gl-api/node_modules/serverless-webpack/node_modules/bluebird/js/release/promise.js:180:30)
    at serverless.pluginManager.spawn.then (/Users/sgreene/src/gl-api/node_modules/serverless-webpack/lib/wpwatch.js:74:32)
    at tryCatcher (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:693:18)
    at Async._drainQueue (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:133:16)
    at Async._drainQueues (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:756:18)
    at tryOnImmediate (timers.js:717:5)
    at processImmediate [as _immediateCallback] (timers.js:697:5)

Additional Data

  • Serverless-Webpack Version you're using: 2.2.3 and 3.1.2 work fine, 4.0.0 and other 4.x and 5.x versions fail.
  • Webpack version you're using: 3.11.0
  • Serverless Framework Version you're using: 1.30.0
  • awesome-typescript-loader version you're using: 3.5.0
  • Operating System: macOS
  • Stack Trace (if available):

Also tried with serverless-webpack 5.2.0, webpack 4.19.1, and awesome-typescript-loader 5.2.1. After updating webpack.config to webpack4 style, it throws exactly the same error.

Hi @SpencerGreene , that's strange. I'm quite sure that it works with all newer release of the plugin. Maybe there is just some small thing wrong ... @serverless-heaven/serverless-webpack-contributors any idea?

I'm using ts-loader without any problems. One can verify this by using aws-nodejs-typescript template (sls create --template aws-nodejs-typescript --path aws-nodejs-typescript). Add serverless-offline plugin (sls plugin install --name serverless-offline) and run sls offline start. Edit handler.ts and hot reload just works.

About the error, the stack points to this:
https://github.com/s-panferov/awesome-typescript-loader/blob/9bbc0656032a006d4cc9f083a5c24af989927e6d/src/instance.ts#L368-L369.

So watching.compiler.watchFileSystem or watching.compiler.watchFileSystem.wfs is undefined.

@SpencerGreene

Maybe you can try to use aws-nodejs-typescript template and then add serverless-offline and replace ts-loader by awesome-typescript-loader to try to isolate the problem.

At first I'm not sure this problem is specific to serverless-webpack plugin. I think it's a problem with awesome-typescript-loader (or at least with some configuration related to it).

I'm seeing very similar problems to what @SpencerGreene is seeing.

FYI - I was able to get passed it by commenting the whole else block here: https://github.com/serverless-heaven/serverless-webpack/blob/master/lib/wpwatch.js#L69

Maybe we should have a new option on offline start to keep the watcher alive to make it friendly with ATL?

I am using latest versions of everything, and using babel with ATL

Package.json:

    "awesome-typescript-loader": "5.2.1",
    "serverless": "1.32.0",
    "serverless-offline": "3.31.2",
    "serverless-webpack": "5.2.0",
    "typescript": "3.1.6",
    "webpack": "4.25.1",
    "webpack-cli": "3.1.2",
    "webpack-node-externals": "1.7.2",

webpack.config.js:

const { CheckerPlugin } = require('awesome-typescript-loader');

...

    module: {
      rules: [
        {
          test: /\.(ts|tsx)$/,
          loader: 'awesome-typescript-loader',
          exclude: /node_modules/,
          options: {
            useBabel: true,
            useCache: true,
            babelCore: '@babel/core',
          },
        },

...

    plugins: [
      new CheckerPlugin(),

One interesting thing I noticed about this problem is that the first hot reload succeeds. The failure happens after the hot-reload loads the new code. So I can get one (but only one) hot reload out of a debug session.

Also, I tried @morgothulhu's workaround of commenting out that else case and it worked flawlessly.

This issue and #465 are related. Both are caused by #319.

I'm working on a fix for this whilst still supporting #319. I just need to write a few more tests and then I'll create a PR.

The only issue I'm having as of right now is that the peerDependency for webpack is >= 3.0.0 < 5.
I need to track down which version of webpack added compiler.hooks, and add a workaround for older versions than that (or bump the webpack peerDependency, but we should be able to support both).

The PR will be part of the upcoming 5.3.0 release. I'll try to get the release schedule back to normal with the help of some people.

Released with 5.3.0