andrey-skl / ng-annotate-loader

Webpack loader to annotate angular applications
MIT License
120 stars 28 forks source link

Webpack 2 TypeError: ngAnnotate options #31

Open Darkbladecr opened 7 years ago

Darkbladecr commented 7 years ago

I have tried to migrate to webpack@^2.1.0-beta.27 however I am struggling with a strange options error. This is pointing to the ng-annotate options input is null?

ERROR in ./src/index.js
Module build failed: TypeError: Cannot read property 'list' of null
    at Object.ngAnnotate (/Users/Stefan/Documents/Github/ques_webpack/node_modules/ng-annotate/build/es5/ng-annotate-main.js:1038:16)
 @ multi app

I have attached my truncated webpack config below:

'use strict';
var webpack = require('webpack'),
    path = require('path');

var APP = __dirname + '/src';

var config = {
    context: APP,
    entry: {
        app: [path.join(APP, '/index.js')],
        vendor: [
            'angular',
        ]
    },
    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            filename: 'vendor.bundle.js'
        })
    ],
    module: {
        loaders: [{
            test: /\.js$/,
            exclude: /node_modules|bower_components|libs_modified/,
            use: [
                {
                    loader: 'ng-annotate',
                    options: {
                        es6: true
                    }
                },
                'babel-loader',
                'jshint-loader'
            ]
        }],
    },
    output: {
        path: APP,
        filename: 'bundle.js'
    }
};

if (process.env.NODE_ENV === 'production') {
    config.devtool = 'sourcemap';
    config.plugins.push(new webpack.DefinePlugin({
        'process.env': {
            'NODE_ENV': JSON.stringify('production')
        }
    }));
    config.plugins.push(new webpack.LoaderOptionsPlugin({
        minimize: true,
        debug: false
    }));
    config.plugins.push(new webpack.optimize.UglifyJsPlugin({
        compress: {
            screw_ie8: true,
            warnings: false
        }
    }));
    config.plugins.push(new webpack.optimize.AggressiveMergingPlugin());
} else {
    config.devtool = 'eval';
    config.entry.app.unshift(
        'webpack/hot/dev-server'
    );
    config.plugins.push(new webpack.HotModuleReplacementPlugin());
}

module.exports = config;
Cornally commented 7 years ago

I ran into the exact same issue and realized I forgot to append "-loader". Try changing 'ng-annotate' to 'ng-annotate-loader':

use: [ { loader: 'ng-annotate-loader', options: { es6: true } }, 'babel-loader', 'jshint-loader' ]

pselden commented 7 years ago

Just curious @Cornally -- did you actually get this to work with webpack 2? I am trying this out and it does not actually annotate anything (and I have everything marked up with 'ngInject')

Cornally commented 7 years ago

Correct, it's working with webpack 2.1.0-beta.27. I didn't flag anything with 'ngInject' and ended up setting explicitOnly : false under the options for ng-annotate-loader. I just verified my outputted bundle and it's correctly annotated.

e.g -- use: [ { loader: 'ng-annotate-loader', options: { explicitOnly: false } }, 'babel-loader', 'jshint-loader' ]

pselden commented 7 years ago

Interesting, did you have babel turn your modules into commonjs? I'm was using the preset: ["es2015", {"modules": false}] so that webpack-2 can use tree-shaking (when I was using babel) and it wasn't working at all.

Right now I'm seeing this error when I log the result of ngAnnotate inside the loader:

   [ 'error: couldn\'t process source due to parse error',
     '\'import\' and \'export\' may appear only with \'sourceType: module\' (1:0)' ] }

Edit: what's also is interesting is that I see in the 'es6' option doesn't actually exist in ng-annotate! It was proposed but rejected here: https://github.com/olov/ng-annotate/pull/241

Edit2: Yeah, that must be what happened. When I switched typescript to use commonjs instead of es6 modules it started working -- unfortunately that means webpack cannot use tree shaking :(

Cornally commented 7 years ago

I'm using the same preset. Here are the contents of my .bablerc file: { "presets": [ ["es2015", { "modules": false }] ], "plugins": [["angularjs-annotate", { "explicitOnly" : false}]] }

Which loader file is complaining and on which line is the error being thrown?

pselden commented 7 years ago

Wait, I see you have another plugin running -- angularjs-annotate -- I believe it's actually the angularjs-annotate plugin with babel that's doing the annotation for you -- not this loader.

Cornally commented 7 years ago

Look at that, you're right. For what it's worth, I just yanked this loader and as noted, I'm letting "babel-plugin-angularjs-annotate" handle the annotation.

rbosneag commented 7 years ago

adding to @Cornally's answer, Webpack@2.x-rc.y requires -loader to be appended to each loader. Meaning that loader: "style!css!sass" becomes loader: "style-loader!css-loader!sass-loader". Saved me some headaches.

ersimont commented 7 years ago

I'm having the same problem as @pselden, and I am not using babel. Is there a workaround for this, or do I have to choose between "no tree shaking" and "start using Babel" to use ng-annotate at this time?

mohamedaboelmagd commented 7 years ago

@pselden error [ 'error: couldn\'t process source due to parse error', '\'import\' and \'export\' may appear only with \'sourceType: module\' (1:0)' ] } this error from import so replace this to require. but babel-core or babel-loader isn't work babel-core throw this error /loader-runner/lib/loadLoader.js:35 throw new Error("Module '" + loader.path + "' is not a loader (must have normal or pitch function)");

nevcos commented 7 years ago

I got the same problem.

In my case, I'm not using Babel, just plain ES6 with imports/exports. So the issue is that ng-annotate doesn't support the ES6 syntax (and will not support it).

Because of that, I ended using ng-annotate-patched that supports ES6 and it's now up and running.

You can specify a different ngAnnotate plugin this way:

{
        test: /\.js$/,
        use: [
          {
            loader: 'ng-annotate-loader',
            options: {
              ngAnnotate: "ng-annotate-patched",
              es6: true,
              explicitOnly: false
            },
          }
        ],
      }

More details here: https://github.com/huston007/ng-annotate-loader#using-a-fork-of-ng-annotate https://github.com/bluetech/ng-annotate-patched

volodymyr-kryvoshapov commented 6 years ago

From ng-annotate doc: ES6 and TypeScript support ng-annotate supports ES5 as input so run it with the output from Babel, Traceur, TypeScript (tsc) and the likes. Use "ngInject" on functions you want annotated. Your transpiler should preserve directive prologues, if not please file a bug on it.

So:

module: {
        rules: [
            {
                test: /\.ts$/,
                loader: 'ts-loader'
            },
            {
                test: /\.js$/,
                loader: 'ng-annotate-loader'
            }
        ]
    }