angular4 aot throw require未定义错误

时间:2017-04-08 16:52:13

标签: angular angular2-aot

我花了一段时间用角度4做AOT,并且总是得到这个错误: 未捕获的ReferenceError:未定义require

我收到此错误是因为我在我的应用程序中使用了jquery,而在应用程序中,我有这个代码:

var jQuery = require('jquery');
jQuery("xxxx").val()

如果我删除它,整个AOT就像一个魅力。

我的tsconfig-aot.json:

{
  "compilerOptions": {
    "target": "es5",
    "module": "es2015",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
"lib": ["es5", "dom"],
    "noImplicitAny": true,
    "suppressImplicitAnyIndexErrors": true
  },
 "files": [
    "src/app/app.module.ts",
    "src/main.ts"
  ],

  "angularCompilerOptions": {
   "genDir": "aot",
   "skipMetadataEmit" : true
 }
}

我的汇总配置:

import rollup      from 'rollup'
import nodeResolve from 'rollup-plugin-node-resolve'
import commonjs    from 'rollup-plugin-commonjs';
import uglify      from 'rollup-plugin-uglify'

export default {
  entry: 'src/main.js',
  dest: 'public/build.js', // output a single application bundle
  sourceMap: false,
  format: 'iife',
  onwarn: function(warning) {
    // Skip certain warnings

    // should intercept ... but doesn't in some rollup versions
    if ( warning.code === 'THIS_IS_UNDEFINED' ) { return; }
    // intercepts in some rollup versions
    if ( warning.indexOf("The 'this' keyword is equivalent to 'undefined'") > -1 ) { return; }

    // console.warn everything else
    console.warn( warning.message );
  },
  plugins: [
      nodeResolve({jsnext: true, module: true}),
      commonjs({
        include: [ 'node_modules/rxjs/**','node_modules/jquery/**']
      }),
      uglify()
  ]
}

这是否意味着,如果您在ng4应用程序中使用require(),那么AOT将不起作用?

感谢并希望听取您的意见。

我试过用这个: import * as jQuery from' jquery&#39 ;; 然后它与require一样工作,在JIT模式下,它工作正常。而且,ngc包很好。但是当我使用汇总时,输出有这个错误:

   Cannot call a namespace ('jQuery')
src/app/app.component.js (14:8)
12:     }
13:     AppComponent.prototype.ngOnInit = function () {
14:         jQuery('h1').html('New Content');
            ^
15:     };
16:     return AppComponent;

这是更新的代码:

import  * as jQuery from 'jquery';

@Component({
    selector: 'my-app',
    templateUrl: './app.component.html',
    styleUrls: ['./scss/app.component.scss']
})
export class AppComponent implements OnInit{

    ngOnInit(){

        jQuery('h1').html('New Content');

    }    

}

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

您无法将require--module es2015一起使用。

这将导致TypeScript编译错误。它没有的唯一原因是您使用var..require形式而不是正确的TypeScript,import..require形式。

这不会引发编译错误的唯一原因是某个地方存在require的环境声明,例如在@types包中。

仍然不太可能工作,因为require不是点火模块语法的一部分,因为你使用Rollup它绝对不会被识别,至少不会添加一堆插件和配置。

尝试

import jQuery from 'jquery';

如果上面在运行时抛出未定义jQuery,请尝试

import * as jQuery from 'jquery';

查看更新后的问题,我发现您收到了错误

  

无法调用命名空间('jQuery')   使用表单

时,这实际上是符合规范的正确行为
import * as ns from 'module';

从CommonJS模块导入,该模块分配给module.exports(在TypeScript中为export =)以便导出其值。

与CommonJS模块的互操作应该使module.exports导出下的default值可用,这将转换为导入的模块命名空间对象的default属性。也就是说表格

import jQuery from 'jquery';

实际上只是

的简写
import {default as jQuery} from 'jquery';

不幸的是,很多环境,转换器,加载器和捆绑器以不同的方式处理它时,互操作性很差。

NodeJS本身甚至都没有实现它。

这是一个非常罕见的区域,其中TypeScript做了绝对错误的事情。它根本不处理这种情况。而是推荐

import * as ns from 'module';

在符合规范的环境中

会失败的表单
ns()

因为导入的模块命名空间对象没有[[Call]]插槽。

幸运的是,您可以通过使用TypeScript输出es2015模块并使用其他工具(如Rollup)处理它们来回避此行为,正如您当前所做的那样。

另一种选择是使用TypeScript的system模块选项和SystemJS。

这可能看起来有点过于详细,同时有点挥手,但我认为重要的是要意识到互操作实际上是多么糟糕,以便我们有一天可以修复它(我希望)。

<强>更新

The TypeScript team is actively looking into the问题,似乎正确的语法

import jQuery from 'jquery';

最终将得到TypeScript的支持,而不需要另外的转换层。

有一天,您的孩子将能够在不知道这个陷阱的情况下编写Web应用程序!