Angular npm 包 ng-packagr打包遇到的坑
deepthan opened this issue · 1 comments
1. es6语法不支持map
、startsWith
等报错
这是因为在配置文件中默认配置的是es5
,所以需要更为es6
+,在最外层tsconfig.json
中将target
更改为es6
,自己模块内的tsconfig.lib.json
中的target
也需要更改为es6
。
tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"module": "es2015",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5", // <-- 这里改为es6
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
}
}
2. includes
报错
Property 'includes' does not exist on type 'string[]'
报这个错的原因是includes
在ES6中只能是string
的方法,在ES7中可以对数组进行使用。
所以更新你的下面配置至es7
。
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"target": "es6",
"module": "es6",
...
"lib": [
"dom",
"es7" <-- 这里
]
},
}
3. 报错关于 Lambda not supported
/core/src/lib/core.module.ts:44:1: Error encountered in metadata genera ted for exported symbol 'CoreModule':
F:/v3-npm-package/iThinkDT-front/projects/core/src/lib/core.module.ts:20:10: Metadata collected contains an err or that will be reported at runtime: Lambda not supported.
{"__symbolic":"error","message":"Lambda not supported","line":19,"character":9}
Error: F:/v3-npm-package/iThinkDT-front/projects/core/src/lib/core.module.ts:44:1: Error encountered in metadata generated for exported symbol 'CoreModule':
F:/v3-npm-package/iThinkDT-front/projects/core/src/lib/core.module.ts:20:10: Metadata collected contains an err or that will be reported at runtime: Lambda not supported.
{"__symbolic":"error","message":"Lambda not supported","line":19,"character":9}
at F:\v3-npm-package\iThinkDT-front\node_modules\@angular\compiler-cli\src\metadata\collector.js:708:31
at Array.forEach (<anonymous>)
at validateMetadata (F:\v3-npm-package\iThinkDT-front\node_modules\@angular\compiler-cli\src\metadata\collec tor.js:696:46)
at MetadataCollector.getMetadata (F:\v3-npm-package\iThinkDT-front\node_modules\@angular\compiler-cli\src\me tadata\collector.js:551:21)
在你写
public static generateNonce(): Observable<string> {
...
}
@ngModule({
...
})
这样一个方法注入到元数据的时候,会报此错误,在函数前面加上一个注释// @dynamic
可以让其不报错误。
public static generateNonce(): Observable<string> {
...
}
// @dynami
@ngModule({
...
})
具体原因参见:
https://github.com/angular/angular/issues/19698#issuecomment-338340211
4. 包名字不符合规范
在package.json
中配置包的名字中带/
提示不符合要求,在前面加上@
即可。
报错
{
"name": "ithinkdt/core",
"version": "0.0.4",
"peerDependencies": {
"@angular/common": "^7.0.0",
"@angular/core": "^7.0.0"
}
}
这样改即可
{
"name": "@ithinkdt/core",
"version": "0.0.4",
"peerDependencies": {
"@angular/common": "^7.0.0",
"@angular/core": "^7.0.0"
}
}
这样配置的话会成为私有包,所以得加上--access=public
改成公用包发布
npm publish dist/core --access=public
参考
https://www.w3cvip.org/topics/393
5. 注释不需要注明参数类型
因为我们用的是ts,已经对参数和返回的值做了类型限定,所以不需要再注明类型。
错误写法
/**
*@param {string} b
*/
a(b:string){
...
}
规范写法: 去除类型注释
/**
*@param b
*/
a(b:string){
...
}
6. 打包之后新抛出的服务或者组件提示未找到
这是因为编辑器缓存的原因,需要重启下编辑器即可。
7. rxjs打包出错
打包之后成了$urlChange: import("rxjs/internal/Observable").Observable<{}>;
具体代码如下
打包前:
public urlChange = new Subject();
urlChange$ = this.urlChange.asObservable();
打包后:
urlChange: Subject<{}>;
urlChange$: import("rxjs/internal/Observable").Observable<{}>;
constructor();
}
需要将urlChange$ = this.urlChange.asObservable();
写到构造器里面初始化
public urlChange = new Subject();
urlChange$: any;
constructor() {
this.urlChange$ = this.urlChange.asObservable();
}
即可成功打包。
subject
方法写法如下:
错误写法:
public urlChange = new Subject();
urlChange$ = this.urlChange.asObservable();
// 有个推送的语句
this.urlChange.next(data);
正确写法
urlChange$ = new Subject<>();
// 有个推送的语句
this.$urlChange.next(data);
8. 在module.ts
中报错symbols are not supported in decorators but....
具体信息
core\src\lib\core.module.ts(25,7): Error during template compile of 'CoreModule'
Reference to a local (non-exported) symbols are not supported in decorators but 'PROVIDERS' was referenced
Consider exporting 'PROVIDERS'.
如果你的module
中有函数的话需要把这个函数抛出即可。
错误写法
function a(){
...
}
@ngModule({
...
})
正确写法
export function a(){
...
}
@ngModule({
...
})
9. 打包报引用的npm抛出来的未定义
错误1
: Unexpected value 'undefined' exported by the module 'IThinkDTSharedModule in F:/v3-npm-package/iThinkDT-front/node_modules/@ithinkdt/shared/ithinkdt-shared.d.ts'
: Unexpected value 'undefined' declared by the module 'IThinkDTSharedModule in F:/v3-npm-package/iThinkDT-front/node_modules/@ithinkdt/shared/ithinkdt-shared.d.ts'
: Cannot determine the module for class TheadFixedDirective in F:/v3-npm-package/iThinkDT-front/node_modules/@ithinkdt/shared/ithinkdt-shared.d.ts! Add TheadFixedDire ctive to the NgModule to fix it.
Cannot determine the module for class PermissionDirective in F:/v3-npm-package/iThinkDT-front/node_modules/@ithinkdt/shared/ithinkdt-shared.d.ts! Add PermissionDirect ive to the NgModule to fix it.
Error: : Unexpected value 'undefined' exported by the module 'IThinkDTSharedModule in F:/v3-npm-package/iThinkDT-front/node_modules/@ithinkdt/shared/ithinkdt-shared.d .ts'
: Unexpected value 'undefined' declared by the module 'IThinkDTSharedModule in F:/v3-npm-package/iThinkDT-front/node_modules/@ithinkdt/shared/ithinkdt-shared.d.ts'
: Cannot determine the module for class TheadFixedDirective in F:/v3-npm-package/iThinkDT-front/node_modules/@ithinkdt/shared/ithinkdt-shared.d.ts! Add TheadFixedDire ctive to the NgModule to fix it.
Cannot determine the module for class PermissionDirective in F:/v3-npm-package/iThinkDT-front/node_modules/@ithinkdt/shared/ithinkdt-shared.d.ts! Add PermissionDirect ive to the NgModule to fix it.
错误2
Cannot read property 'module' of undefined
TypeError: Cannot read property 'module' of undefined
解决办法
9.1. 问题
之前写法是在auth
模块的文件夹中建立了一个index.ts
把组件抛出来了,然后在module
中直接引用的,这样会报这个错误。
组件文件夹里的index.ts
export * from './login/login.component';
export * from './register/register.component';
module中的写法
import { LoginComponent, RegisterComponent } from './auth';
9.2. 错误1解决办法: 加上index
module中的写法
import { LoginComponent, RegisterComponent } from './auth/index';
但是这样的话之前错误不会报了,会报错误2
Cannot read property 'module' of undefined
TypeError: Cannot read property 'module' of undefined
9.3. 错误2解决办法: 一个一个引用
把你的组件等从它定义的地方一个一个引用过来即可解决问题。
module中的写法
import { LoginComponent } from './login/login.component.ts';
import { RegisterComponent } from './register/register.component.ts';
10. 报错关于 Cannot call a namespace ('moment')
错误信息如下
Cannot call a namespace ('moment')
将moment
引进来赋值给一个常量即可
import * as moment_ from 'moment';
const moment = moment_;
参考
https://github.com/jvandemo/generator-angular2-library/issues/221#issuecomment-355945207
11. http拦截器不起作用
httpClientModule
是http服务的模块,在项目中的某个懒加载模块再次引入的话会覆盖之前的http设置,这样注册在根模块的拦截器就会失效。
如果在npm包中配置了拦截器,用户项目中引入了http模块拦截器也会失效。
即最好保证httpClientModule
在一个项目中只会被注入到module
中一次。官方文档参考:
https://angular.io/guide/http#setup-installing-the-module
12. 在npm包的ngModule
中使用xxx()
导致报错Function calls are not supported
具体报错信息如下
Function calls are not supported in decorators but 'DndModule' was called.
解决方案
RouterModule
是angular的路由模块, routes
是自己配置的路由。
进行如下改写即可解决错误。
import { NgModule, ModuleWithProviders } from '@angular/core';
export const routerModuleForChild: ModuleWithProviders = RouterModule.forChild(routes)
@NgModule({
imports: [
routerModuleForChild
],
...
})
参考https://github.com/ng-packagr/ng-packagr/issues/778#issuecomment-385122626
13. 路由中懒加载引入npm包抛出模块报错
ERROR in Could not resolve module AuthModule relative to pages/pages.module.ts
之前的写法:
import {
AuthModule
} from '@my/pages';
export const PagesRouting: Routes = [
{
path: 'auth',
loadChildren: 'AuthModule'
},
]
正确写法
import {
AuthModule
} from '@my/pages';
export const PagesRouting: Routes = [
{
path: 'auth',
loadChildren: () => AuthModule
},
]
npm包中做路由懒加载也需要这样写。
参考https://github.com/aspnet/JavaScriptServices/issues/1258#issuecomment-327818748
14. 路由打包时构建错误,ModuleWithProviders
未被成功引入
npm包会构建成这样:
打包前
export const routerModuleForChild = RouterModule.forChild(routers)
打包后
export declare const routerModuleForChild: import("@angular/core/src/metadata/ng_module").ModuleWithProviders<RouterModule>;;
正确写法:
import { ModuleWithProviders } from "@angular/core";
export const routing: ModuleWithProviders = RouterModule.forRoot(routers);
参考https://stackoverflow.com/questions/41134288/angular-2-routing-error-with-modulewithproviders
路由配置时报路由配置错误
unhandled Promise rejection: Invalid configuration of route 'pages/'. One of the following must be provided: component, redirectTo, children or loadChildren ; Zone: <root> ; Task: Promise.then ; Value: Error: Invalid configuration of route 'pages/'. One of the following must be provided: component, redirectTo, children or loadChildren
这是因为路由里面有个空的{}
什么都没填,将其删除即可。
{ path: '401', component: Exception401Component, },
{
// path: 'demo',
// loadChildren: './demo/demo.module#DemoModule'
},
{ path: '403', component: Exception403Component},
删除后
{ path: '401', component: Exception401Component, },
{ path: '403', component: Exception403Component},
15. 路由模块报关于Consider changing the function expression into an exported function
错误
引入npm包中的模块在路由中配置之后,报错如下
ERROR in src\app\pages\pages.module.ts(23,7): Error during template compile of 'PagesModule'
Function expressions are not supported in decorators in 'PagesRouting'
'PagesRouting' contains the error at src\app\pages\pages.routing.ts(24,19)
Consider changing the function expression into an exported function.
之前写法
import {AModule,BModule,CModule} from 'ANpmPackage'
export const PagesRouting: Routes = [
{ path: 'a', loadChildren: ()=> AModule },
{ path: 'b', loadChildren: ()=> BModule },
{ path: 'c', loadChildren: ()=> CModule },
]
解决方法:
建立一个function抛出模块再引用这个方法。
正确写法
import {AModule,BModule,CModule} from 'ANpmPackage'
export function getAModule(){
return AModule;
}
export function getBModule(){
return BModule;
}
export function getCModule(){
return CModule;
}
export const PagesRouting: Routes = [
{ path: 'a', loadChildren: getAModule },
{ path: 'b', loadChildren: getBModule },
{ path: 'c', loadChildren: getCModule },
]
16. 测试项目中一直报错Can't resolve all parameters for AppComponent
这是因为你项目的polyfills.ts
文件中未引入'core-js/es7/reflect'
包,引入即可。
import 'core-js/es7/reflect';
更多信息请参考:
https://github.com/angular/angular/issues/19417#issuecomment-359722822
17. Runtime compiler is not loaded
在本地开发可以运行并且能打包,但是打包之后放在服务器会报错,具体错误信息
main.e81fa16196eccd7cdc8b.js:1 ERROR Error: Uncaught (in promise): Error: Runtime compiler is not loaded
Error: Runtime compiler is not loaded
原因
解决办法:
在app.routing.ts
中,你之前的写法可能是这样的
import { Routes } from "@angular/router";
import { AModule } from '@my/lib';
export const AppRouting: Routes = [
{
path: "a",
loadChildren: ()=> AModule
},
]
或者是这样的
import { Routes } from "@angular/router";
import { AModule } from '@my/lib';
export function loadAModule(){
return AModule;
}
export const AppRouting: Routes = [
{
path: "a",
loadChildren: loadAModule
},
]
又或者是这样的
import { Routes } from "@angular/router";
import { AModule } from '@my/lib';
export function loadAModule(){
return System.import("@@my/lib").then(
mod => mod.AModule
);
}
export const AppRouting: Routes = [
{
path: "a",
loadChildren: loadAModule
},
]
都还是会报错,
解决办法
新增一个module
,在这个模块里面把要用的包引进来,在路由中懒加载新建的这个模块即可。
新增的 A-module-loader.ts
import { NgModule } from "@angular/core";
import { AModule } from '@my/lib';
@NgModule({
imports: [
AModule
]
})
export class AModuleLoader {}
原来的app.routing.ts
中可以这样写
import { Routes } from "@angular/router";
export const AppRouting: Routes = [
{
path: "a",
loadChildren: './A-module-loader#AModuleLoader'
},
]
参考
1. https://github.com/angular/angular-cli/issues/6373#issuecomment-319116889
2. https://github.com/angular/angular-cli/issues/6373#issuecomment-424819684
3. https://github.com/angular/angular-cli/issues/6373#issuecomment-303013724
4. https://github.com/angular/angular-cli/issues/6373#issuecomment-304922035
5. https://stackoverflow.com/questions/45503497/how-to-load-dynamic-external-components-into-angular-application/45506470#45506470
6. https://stackoverflow.com/questions/41438198/implementing-a-plugin-architecture-plugin-system-pluggable-framework-in-angu
18. project does not support the 'build' target
Project './projects/core' does not support the 'build' target.
Error: Project './projects/core' does not support the 'build' target.
at BuildCommand.initialize (F:\AAA---v3-npm-package\iThinkDT-npm-package\node_modules\@angular\cli\models\architect-command.js:53:19)
at process._tickCallback (internal/process/next_tick.js:68:7)
at Function.Module.runMain (internal/modules/cjs/loader.js:721:11)
at startup (internal/bootstrap/node.js:228:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:576:3)
这是因为在你的angular.json
中未对打包规则进行配置,用ng g library xxx
会自动新增打包规则,但是在项目中的angular.json
则不会生成,需自己配置。
在projects
下面新增你的规则,如:
"projects": {
"core": {
"root": "projects/core",
"sourceRoot": "projects/core/src",
"projectType": "library",
"prefix": "lib",
"architect": {
"build": {
"builder": "@angular-devkit/build-ng-packagr:build",
"options": {
"tsConfig": "projects/core/tsconfig.lib.json",
"project": "projects/core/ng-package.json"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/core/src/test.ts",
"tsConfig": "projects/core/tsconfig.spec.json",
"karmaConfig": "projects/core/karma.conf.js"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/core/tsconfig.lib.json",
"projects/core/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
}
19. Cannot find module 'tsickle/src/tsickle'
这是ng-packer
更新版本之后依赖了tsickle
包,因此下载这个包即可。
npm i --save-dev tsickle
yarn add tsickle
🙏感谢分享,帮大忙了🙏