angular4 aot throw require 未定义错误

Posted

技术标签:

【中文标题】angular4 aot throw require 未定义错误【英文标题】:angular4 aot throw require is not defined error 【发布时间】:2017-09-04 00:01:40 【问题描述】:

我花了一段时间用 angular 4 做 AOT,但总是得到这个错误: 未捕获的 ReferenceError:未定义要求

我收到此错误是因为我在我的应用程序中使用 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 将无法工作?

感谢并希望听到您的建议。

我尝试使用这个: 从 'jquery' 导入 * 作为 jQuery; 然后它的工作方式与要求相同,并且在 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');

        


有什么想法吗?

【问题讨论】:

您不应该将require--module es2015 一起使用,这将导致TypeScript 编译错误。它没有的唯一原因是您使用的是 var..require 表单,而不是 TypeScript 中正确的 import..require 表单。由于前面提到的原因,它仍然不正确。尝试import jQuery from 'jquery';,如果在运行时抛出未定义jQuery,请尝试import * as jQuery from 'jquery'; 【参考方案1】:

您不能将require--module es2015 一起使用。

这将导致 TypeScript 编译错误。唯一没有这样做的原因是您使用的是 var..require 表单,而不是 TypeScript 中正确的 import..require 表单。

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

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

试试

import jQuery from 'jquery';

如果上面在运行时抛出没有定义 jQuery,试试

import * as jQuery from 'jquery';

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

不能调用命名空间('jQuery') 使用表单时,这实际上是正确的规范兼容行为

import * as ns from 'module';

从分配给 module.exports 的 CommonJS 模块导入(在 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 应用程序,而不必知道这个陷阱!

【讨论】:

这对我有用: import * as jQuery_ from 'jquery';让 jQuery:any = (jQuery_).default || jQuery_;谢谢 @user3006967 似乎很奇怪,它有时会是default,而不是其他人... import jQuery from 'jquery'; 是否会默认失败?不管你不需要诉诸any,使用JQueryStatic作为let的类型,应该是const

以上是关于angular4 aot throw require 未定义错误的主要内容,如果未能解决你的问题,请参考以下文章

升级到 Angular4 后找不到名称“require”

angular 5 noty 和 AOT

类型“AbstractControl”Angular 4 上不存在属性“控件”[重复]

"throw" is deprecated in favour of "revert()", "require()" and "a

Socket send() method throws TypeError: a bytes-like object is required, not 'str'

node_modules/express/lib/router/index.js:458 throw new TypeError('Router.use() requires a middleware