简体   繁体   English

将Angular4模块链接到Angular4应用程序:模块'AppModule'导入了意外的值'TestModule'。 请添加@NgModule批注

[英]Linking Angular4 Module to Angular4 app: Unexpected value 'TestModule' imported by the module 'AppModule'. Please add a @NgModule annotation

See FURTHER UPDATE at bottom... 请参阅底部的进一步更新 ...

I have a very large app that I am trying to convert from Angular 1.6 to Angular 4.0. 我有一个非常大的应用程序,试图将Angular 1.6转换为Angular 4.0。 And it has become a herculean task and I am stuck at a particular point. 这已经成为一项艰巨的任务,我被困在特定的位置。 We have a common set of utilities that we use between two different apps. 我们在两个不同的应用程序之间使用一组通用的实用程序。 In trying to get that to compile to a module that can be imported through "npm link" I get the following error upon importing into my app. 在尝试将其编译为可以通过“ npm链接”导入的模块时,在导入到我的应用程序时出现以下错误。

I am using webpack 3. 我正在使用webpack 3。

compiler.es5.js:1690 Uncaught Error: Unexpected value 'TestModule' imported by the module 'AppModule'. Please add a @NgModule annotation. at syntaxError (compiler.es5.js:1690) at compiler.es5.js:15382 at Array.forEach (<anonymous>) at CompileMetadataResolver.getNgModuleMetadata (compiler.es5.js:15365) at JitCompiler._loadModules (compiler.es5.js:26795) at JitCompiler._compileModuleAndComponents (compiler.es5.js:26768) at JitCompiler.compileModuleAsync (compiler.es5.js:26697) at PlatformRef_._bootstrapModuleWithZone (core.es5.js:4536) at PlatformRef_.bootstrapModule (core.es5.js:4522) at Object.<anonymous> (main.ts:26)

I have created a test case that minimally recreates my issue. 我创建了一个测试案例,以最小程度地再现我的问题。 It looks a little more complex because I left my webpack.config and package.json files roughly the same as my real life cases but the code is reduced to a minimum. 看起来有点复杂,因为我保留了我的webpack.config和package.json文件与现实生活中的情况大致相同,但是代码减少到最低限度。

You can see the code https://github.com/crowmagnumb/ng-migration-test and the steps to recreate the issue exactly. 您可以看到代码https://github.com/crowmagnumb/ng-migration-test以及准确地重新创建问题的步骤。

My main.ts file in my app looks like this... 我的应用程序中的main.ts文件看起来像这样...

import './polyfills';

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {UpgradeModule} from '@angular/upgrade/static';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';

import {TestModule} from 'ng-module-test';

@NgModule({
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        UpgradeModule,
        TestModule
    ]
})
export class AppModule {
    // Override Angular bootstrap so it doesn't do anything
    ngDoBootstrap() {
    }
}

// Bootstrap using the UpgradeModule
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
    console.log("Bootstrapping in Hybrid mode with Angular & AngularJS");
    const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
    upgrade.bootstrap(document.body, ['au.website']);
});

... and that of my module looks like ... ...而我的模块看起来像...

import {NgModule} from '@angular/core';

import {Utils} from './utils/module';

@NgModule({
    imports: [
        Utils
    ]
})
export class TestModule {};

Thanks for your help. 谢谢你的帮助。

UPDATE 更新

I changed my import of TestModule to be a relative path instead of loading through the linked npm module like so ... 我将TestModule的导入更改为相对路径,而不是像这样通过链接的npm模块加载...

// import {TestModule} from 'ng-module-test';
import {TestModule} from '../../ng-module-test/src/main';

... and I get the same result. ...我得到相同的结果。 So it doesn't appear to have anything to do with npm link but rather the specific separation of code that entails. 因此,它似乎与npm链接无关,而与代码的特定分离有关。 Can anyone shed light on that? 谁能阐明这一点?

I've checked that change into the above repo. 我已经检查了上述回购中的更改。

FURTHER UPDATE 进一步更新

Now I totally don't understand this. 现在我完全不明白这一点。 If I change the import to read ... 如果我将导入更改为...

import {TestModule} from './ng-module-test/main';

... and I make a directory called ng-module-test inside of ng-app-test/src and I copy the contents of the ng-module-test/src folder into that then it works as @Hosar kindly discovered in the comments. ...然后在ng-app-test / src内创建一个名为ng-module-test的目录,然后将ng-module-test / src文件夹的内容复制到该目录中,然后它就像@Hosar一样在评论。 BUT if I make a symlink using ln -s ../../ng-module-test/src ng-module-test to the code so that effectively from the standpoint of the underlying OS the exact same thing, IT DOESN"T WORK. 但是,如果我使用ln -s ../../ng-module-test/src ng-module-test对代码进行符号链接,以便从底层OS的角度有效地完全相同, 那工作。

You need to make all the @angular packages a peerDependency and devDependency instead of a dependency in ng-module-test/package.json 您需要将所有@angular软件包设置为peerDependency和devDependency,而不是ng-module-test / package.json中的依赖项

Then add the following to ng-app-test/src/tsconfig.json: 然后将以下内容添加到ng-app-test / src / tsconfig.json中:

{
  "compilerOptions": {
    // ...
    // Note: these paths are relative to `baseUrl` path.
    "paths": {
      "@angular/*": [
        "../node_modules/@angular/*"
      ]
    }
  }
}

See full explanation: https://github.com/angular/angular-cli/wiki/stories-linked-library 查看完整说明: https : //github.com/angular/angular-cli/wiki/stories-linked-library

I found a solution to the symlink direction. 我找到了符号链接方向的解决方案。 Just need to set symlinks to false (counter-intuitively) in the resolve section of webpack.config.js. 只需在webpack.config.js的resolve部分中将符号链接设置为false(反直觉)。 For example ... 例如 ...

resolve: {
    extensions: ['.ts', '.tsx', '.js'],
    symlinks: false
},

But this still does not allow me to use npm link as that still fails. 但这仍然不允许我使用npm链接,因为那仍然失败。 But this is fine for now to get me going forward. 但这现在可以使我前进。 In some ways it's better since now the watch system will pick up changes in my typescript files automatically. 从某些方面讲,这是更好的选择,因为现在监视系统将自动提取我的打字稿文件中的更改。 But it doesn't provide for much flexibility should I decide I do want/need to publish this library. 但是,如果我决定要发布此库,它并不能提供太多的灵活性。 But if I figure that out later it would be just a global search and replace to fix it. 但是,如果以后再弄清楚,那将是一个全局搜索并替换以进行修复。

So, in the end, it looks like I will add a symlink in my apps' src dir pointing to the src directory of my library. 因此,最后,看来我将在应用程序的src目录中添加一个符号链接,指向我的库的src目录。 And then I will import stuff from that library through ... 然后我将通过...从那个库中导入东西

import {Blah} from './ng-module-test/main';

... or (eg) ... ...或(例如)...

import {Blah} from '../../ng-module-test/main';

... depending on how deep into the src dir the file I'm importing into is. ...取决于我要导入的文件在src目录中的深度。 I'm going to look into the modules property of webpack config to see if I can just address it as ... 我将研究webpack config的modules属性,看看是否可以将其寻址为...

import {Blah} from 'ng-module-test/main';

... everywhere. ...无处不在。 Or better yet even drop the main. 甚至更好,甚至放弃主要。 I'll give that solution if I manage it. 如果可以的话,我会提供解决方案。

UPDATE 更新

Better solution. 更好的解决方案。 Thanks to this link I was able to realize a better solution that doesn't involve symlinks (unless you want to use one instead of putting relative path to the library module I suppose). 多亏有了此链接,我才能够实现一个不涉及符号链接的更好的解决方案(除非您想使用一个而不是将相对路径放置到我想的库模块中)。

If I add the following to my tsconfig.json file: 如果我将以下内容添加到tsconfig.json文件中:

"paths": {
    "NgModuleTest/*": ["../ng-module-test/src/*"]
}

... and then change resolve in my webpack.config.js to ... ...然后将我的webpack.config.js中的resolve更改为...

const TsConfigPathsPlugin = require('awesome-typescript-loader').TsConfigPathsPlugin;

resolve: {
    extensions: ['.ts', '.tsx', '.js'],
    // symlinks: false,
    modules: [
        `${__dirname}/node_modules`
    ],
    plugins: [
        new TsConfigPathsPlugin({
            tsconfig: './tsconfig.json',
            compiler: 'typescript'
        })
    ]
}

... I can then reference imports to my external library via ... ...然后我可以通过...将导入引用到我的外部库

import {Blah} from 'NgModuleTest/main';

... no matter where I am in the src tree. ...无论我在src树中的什么位置。 Plus I can add as many of these paths as I want so that I can reference internal modules in the same easy way. 另外,我可以根据需要添加任意数量的这些路径,以便以相同的简便方式引用内部模块。 Nice. 真好 I did not test to see if paths in tsconfig.json accepts a symlink or not, as I said, and what that means for the symlink property of resolve. 正如我所说,我没有进行测试来查看tsconfig.json中的路径是否接受符号链接,这对于resolve的symlink属性意味着什么。 But I'm fine with using the tsconfig.json to point to code outside of that directory as I am doing above. 但是我可以像上面一样使用tsconfig.json指向该目录之外的代码。

Oh, by the way, I moved tsconfig.json out of src into the root to be alongside webpack.config.js because I had some path issues that seemed like it would be solved with them in the same location. 哦,顺便说一句,我将tsconfig.json从src移到了根目录,并与webpack.config.js并存,因为我遇到了一些路径问题,似乎可以在同一位置使用它们来解决。 And it did. 它做到了。 I think this might be necessary so that the plugin has the same relative path as the tsconfig.json. 我认为这可能是必要的,以便插件具有与tsconfig.json相同的相对路径。

Updated repo above with this solution. 使用此解决方案更新了上面的回购。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 angular 8 错误:模块“AppModule”导入的意外值“HttpClient”。 请添加@NgModule 注释 - angular 8 Error: Unexpected value 'HttpClient' imported by the module 'AppModule'. Please add a @NgModule annotation 模块“AppModule”导入的意外值“MatSnackBar”。 请添加@NgModule 注解 - Unexpected value 'MatSnackBar' imported by the module 'AppModule'. Please add a @NgModule annotation 模块&#39;AppModule&#39;导入的意外值&#39;MDCTextField&#39;。 请添加@NgModule注释 - Unexpected value 'MDCTextField' imported by the module 'AppModule'. Please add a @NgModule annotation 模块'AppModule'导入的意外值'DataTablesModule'。请添加@NgModule注释 - Unexpected value 'DataTablesModule' imported by the module 'AppModule'. Please add a @NgModule annotation 模块“ AppModule”导入的异常值“ AngularFireDatabase”。 请添加@NgModule批注 - Unexpected value 'AngularFireDatabase' imported by the module 'AppModule'. Please add a @NgModule annotation 模块“ AppModule”导入了意外值“ Validators”。 请添加@NgModule批注 - Unexpected value 'Validators' imported by the module 'AppModule'. Please add a @NgModule annotation 由模块“AppModule”导入的意外值“FormBuilder”。 请添加@NgModule 注释 - Unexpected value 'FormBuilder' imported by the module 'AppModule'. Please add a @NgModule annotation 模块&#39;AppModule&#39;导入了意外的值&#39;MatMenu&#39;。 请添加@NgModule批注 - Unexpected value 'MatMenu' imported by the module 'AppModule'. Please add a @NgModule annotation 由模块“AppModule”导入的意外值“MatBottomSheet”。 请添加@NgModule 注释 - Unexpected value 'MatBottomSheet' imported by the module 'AppModule'. Please add a @NgModule annotation 模块“AppModule”导入的意外值“MatTableDataSource”。 请添加@NgModule 注解 - Unexpected value 'MatTableDataSource' imported by the module 'AppModule'. Please add a @NgModule annotation
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM