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

时间:2017-08-15 03:50:20

标签: angular typescript npm webpack

请参见底部的进一步更新 ...

我有一个非常大的应用程序,我试图从Angular 1.6转换为Angular 4.0。它已成为一项艰巨的任务,我陷入了困境。我们在两个不同的应用程序之间使用了一组通用实用程序。试图将其编译成可以通过" npm link"导入的模块。导入我的应用程序时出现以下错误。

我正在使用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)

我创建了一个测试用例,最小化了我的问题。它看起来有点复杂,因为我将webpack.config和package.json文件与我的实际案例大致相同,但代码减少到最低限度。

您可以看到代码https://github.com/crowmagnumb/ng-migration-test以及完全重新创建问题的步骤。

我的应用中的 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']);
});

......我的模块看起来像......

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

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

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

感谢您的帮助。

更新

我将TestModule的导入更改为相对路径,而不是通过链接的npm模块加载,如此...

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

......我得到了同样的结果。所以它似乎与 npm link 无关,而是与代码的特定分离有关。任何人都可以阐明这一点吗?

我已经检查了上述回购的变化。

进一步更新

现在我完全不理解这一点。如果我将导入更改为阅读...

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

...我在 ng-app-test / src 中创建一个名为 ng-module-test 的目录,然后复制的内容ng-module-test / src 文件夹,然后在评论中发现@Hosar。但是,如果我使用 ln -s ../../ng-module-test/src ng-module-test 对代码进行符号链接,以便有效地从底层操作系统的立场完全相同, IT DOESN&#34; T WORK。

2 个答案:

答案 0 :(得分:1)

你需要在ng-module-test / package.json中使所有的@angular包成为peerDependency和devDependency而不是依赖

然后将以下内容添加到ng-app-test / src / tsconfig.json:

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

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

答案 1 :(得分:1)

我找到了符号链接方向的解决方案。只需要在webpack.config.js的resolve部分中将符号链接设置为false(反直觉)。例如......

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

但是这仍然不允许我使用 npm链接,因为它仍然失败。但是现在这样可以让我继续前进。在某些方面,它更好,因为现在手表系统会自动获取我的打字稿文件中的更改。但是,如果我确定需要/需要发布此库,它并没有提供很大的灵活性。但是,如果我稍后想出来,那将只是一个全局搜索并替换以修复它。

所以,最后,看起来我会在我的应用中添加一个符号链接&#39; src dir指向我库的src目录。然后我将通过...导入该库中的内容。

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

......或(例如)......

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

...取决于我导入的文件有多深入src dir。我将查看webpack配置的模块属性,看看我是否可以将其作为...来解决...

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

......无处不在。或者更好,甚至放弃主力。如果我管理它,我会给出解决方案。

<强>更新

更好的解决方案。多亏了这个link我能够实现一个更好的解决方案,它不涉及符号链接(除非你想使用一个而不是将相对路径放到我想的库模块中)。

如果我将以下内容添加到 tsconfig.json 文件中:

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

...然后将 webpack.config.js 中的解决方案更改为...

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'
        })
    ]
}

...然后,我可以通过...

引用导入到我的外部库
import {Blah} from 'NgModuleTest/main';

...无论我在src树中的哪个位置。另外,我可以添加尽可能多的这些路径,以便我可以以同样简单的方式引用内部模块。尼斯。我没有测试,看看tsconfig.json中的路径是否接受符号链接,正如我所说,这对于syml的symlink属性意味着什么。但我可以使用tsconfig.json指向该目录之外的代码,就像我上面所做的那样。

哦,顺便说一句,我将tsrc.json从src移到了根目录下与webpack.config.js一起,因为我有一些路径问题似乎可以在同一个位置解决它们。它确实如此。我认为这可能是必要的,以便插件具有与tsconfig.json相同的相对路径。

使用此解决方案更新了上面的回购。