如何在 npm 上发布 angular 2 typescript 库

Posted

技术标签:

【中文标题】如何在 npm 上发布 angular 2 typescript 库【英文标题】:how to publish angular 2 typescript library on npm 【发布时间】:2017-01-23 19:54:46 【问题描述】:

我为 Angular 2 创建了一个打字稿库,便于访问我的后端服务。

到目前为止它是一个私人仓库,但我想将它作为一个开源库上传到 github 并在 npm 上注册。

我不太确定现在该做什么,因为很难找到有关此主题的文档。

文件夹结构如下:

src
|--sdk.ts // entry point
|--services
   |--auth.ts
   |--database.ts
   |--5 more ts files
|--utils
   |--utils.ts
   |--interfaces.ts
|--tests (8 ..spec.ts files)

我的入口点(sdk.ts)看起来像这样

import  NgModule, ModuleWithProviders  from '@angular/core';
import  Injectable  from '@angular/core';
import  SelfbitsDatabase  from './services/database';
import  SelfbitsAuth  from './services/auth';
import  SelfbitsAppConfig  from './utils/interfaces';
import  SelfbitsFile  from './services/file';
import  SelfbitsUser  from './services/user';
import  SelfbitsDevice  from './services/device';
import  SelfbitsPush  from './services/push';
import  HttpModule  from '@angular/http';

@Injectable()
export class SelfbitsAngular 
    constructor(
        public auth : SelfbitsAuth,
        public database : SelfbitsDatabase,
        public file : SelfbitsFile,
        public user : SelfbitsUser,
        public device: SelfbitsDevice,
        public push : SelfbitsPush
    )


export const SELFBITS_PROVIDERS:any[] = [
    SelfbitsAngular,
    SelfbitsAuth,
    SelfbitsDatabase,
    SelfbitsFile,
    SelfbitsUser,
    SelfbitsDevice,
    SelfbitsPush
];

@NgModule(
    providers:SELFBITS_PROVIDERS,
    imports:[ HttpModule ]
)

export class SelfbitsAngularModule
    static initializeApp(config:SelfbitsAppConfig):ModuleWithProviders
        return 
            ngModule:SelfbitsAngularModule,
            providers:[
                 provide: 'SelfbitsConfig', useValue: config 
            ]
        
    

这里的 webpack.config.js 并没有真正做到我想要的......

module.exports = 
    entry:'./src/sdk.ts',
    output:
        path: helpers.root('dist'),
        filename:'selfbitsangular2sdk.js'
    ,
    resolve: 
        extensions: ['', '.js', '.ts']
    ,

    module: 
        loaders: [
            
                test: /\.ts$/,
                exclude:'/test/',
                loaders: ['ts-loader']
            
        ]
    
;

我不确定 webpack 是否是正确的选择……或者是否应该捆绑和缩小。欢迎任何提示和提示!

干杯

【问题讨论】:

【参考方案1】:

发布过程本身非常简单:

# Login with your existing npm user
npm login

# Bump library version
npm version --patch

# Publish your library
npm publish

最难的部分是正确准备 package.json 的内容以及存放构建库的文件夹(命名它的常用方法之一是 dist)。

您的 dist 文件夹应该包含可供 Angular JIT 项目和 Angular AOT 项目使用的文件。它还应该包含可供浏览器直接使用的库包(比如说通过 SystemJS)。

因此,您的 dist 文件夹应包含以下文件:

index.umd.js - 可供 SystemJS 使用的 UMD 包 index.umd.min.js - 压缩包以节省用户流量 index.umd.js.mapindex.umd.min.js.map - 用于调试目的 *.js — [由 tsc 生产,记住 ngc 是一个包装器] 已编译的 javascript 表示您的库的组件或服务 *.ts 文件。 *.d.ts — [由 tsc 生产,记住 ngc 是一个包装器] 声明文件。由于具有类型的 *.ts 文件被转换为不支持类型的 *.js 文件,TypeScript 编译器需要将所有类型信息放入单独的 *.d.ts 文件中,以便能够使用这些 *.js 文件稍后在 TypeScript 项目中。顺便说一句,DefinitelyTyped 项目包含许多类型定义,这些定义已经为大量 JS 非 TypeScript 库做出贡献。 *.metadata.json — 与当前组件(或 NgModule)关联的元数据。它是我们传递给@Component、@NgModule 装饰器的对象的一种 JSON 表示。该文件包含项目(而非库)NGC 需要的信息,这些信息位于原始库 *.ts 文件中,但未包含在 *.d.ts 文件中。

在这种情况下,您的 package.json 应该通过 mainmoduletypings 字段通知您的构建文件:

 
   ...
   "main": "./dist/index.umd.js",
   "module": "./dist/index.js",
   "typings": "./dist/index.d.ts",
   ...
 

您可以在How to create AOT/JIT compatible Angular 4 library with external SCSS/html templates 文章中找到有关dist 文件夹中应包含哪些文件以及如何编译它们的更详细说明

【讨论】:

【参考方案2】:

Angular 大学有一个很好的分步教程,介绍如何将 Angular 2 库发布到 npm 以解决您的顾虑/问题。

如果您愿意,您可以提供捆绑和非捆绑版本,不过我总是会提供非捆绑版本。在我的库中,我不提供捆绑版本,而是将其留给消费者进行捆绑和缩小。

http://blog.angular-university.io/how-to-create-an-angular-2-library-and-how-to-consume-it-jspm-vs-webpack/


更新答案

以下步骤将完成创建、测试和发布未捆绑的 Angular 模块以供消费者使用捆绑器(webpack、angular cli 等)使用的过程。有关包括捆绑的更完整答案,请参阅@OleksiiTrekhleb 的答案。

发布一个 Angular 2 库可能会令人生畏,但当它失败时,它与在 NPM 上发布任何其他包真的没有什么不同。以下信息将使用文件夹结构:

包根 源代码 分布

1。设置 tsconfig.json

与任何打字稿库一样,您希望在tsconfig.json 下的compilerOptions 中将declaration 选项设置为true,以确保我们的消费者可以利用我们包中的类型:

"declaration": true

compilerOptions 中,我们还想指定我们的outDir 以将转译的代码与源代码分开:

"outDir": "./dist"

我们希望include 选项指向我们的源文件夹(注意includecompilerOptions 的兄弟):

"include": [
  "./src"
]

启用compilerOptions下的实验性装饰器选项:

"experimentalDecorators": true,
"emitDecoratorMetadata": true 

为避免在转译时出现一些错误,您还需要启用skipLibCheck

"skipLibCheck": true

结果


  "compilerOptions": 
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "skipLibCheck": true,
    "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    "outDir": "./dist",                        /* Redirect output structure to the directory. */
    "strict": true,                            /* Enable all strict type-checking options. */
    "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    "emitDecoratorMetadata": true         /* Enables experimental support for emitting type metadata for decorators. */
  ,
  "include": [
    "./src"
  ]

2。模块

此示例将使用具有单个组件的模块。该组件相当简单:

./src/helloWorld/helloWorld.component.ts

import  Component  from "@angular/core";

@Component(
    selector: 'hello-world',
    template: '<div>Hello, world</div>'
)
export class HelloWorldComponent 


模块应该在declarationsexports中添加消耗组件。我们需要添加到导出中,这样当消费者导入我们的模块时,他们也可以使用我们的组件。

./src/helloWorld/helloWorld.module.ts

import  NgModule  from '@angular/core'
import  HelloWorldComponent  from './helloWorld.component';

const components: any[] = [
    HelloWorldComponent
];

@NgModule(
    declarations: components,
    exports: components // Don't forget to export!
)
export class HelloWorldModule 


3。桶

为了简化导入我们的模块,我们使用了一个桶,该文件导出所有内容供我们的消费者使用。

./src/index.ts

export  HelloWorldModule  from './helloWorld/helloWorld.module';
export  HelloWorldComponent  from './helloWorld/helloWorld.component';

4。设置 NPM

Package.json

package.json 中,将main 属性更改为指向我们的转译桶./dist/index.js。还要添加typings 属性以指向我们的桶定义文件./dist/index.d.ts

package.json 的脚本下添加属性prepublish

"scripts": 
    "prepublish": "tsc"

另请注意,您的角度和相关依赖项应在peerDependencies 下,而不是dependencies

NPM 忽略

在包的根目录中创建一个.npmignore 文件,并忽略src 文件夹以及您不想与包一起发布的任何其他文件

src/
*.log

5。测试

您可以使用npm link 在本地轻松测试您的 npm 包。在您的模块包文件夹中,运行命令npm link

然后在你的测试项目中,运行命令npm link &lt;my package name&gt;

现在您可以导入您的模块并将其添加到您的测试项目导入中,而无需发布。

6。出版

现在可以使用简单的npm publish 发布您的包

【讨论】:

我在本教程中运气不佳,示例已经过时了。 是的,很麻烦。那里没有蚂蚁好的清洁指南吗? medium.com/@OCombe/… @clint 教程已经过时了。该教程于 2015 年 12 月 27 日发布。现在是 2018 年 01 月 7 日。通过在此处发布页面的相关内容并保持您的答案是最新的,可以避免这个问题。 @clint 这是否也包括模板?我们不需要捆绑模块什么的吗?【参考方案3】:

对于那些仍在试图弄清楚如何做到这一点的人:

    使用@jvandemo 的Angular Lib Yeoman generator创建您的库

    之后您只需运行:npm addusernpm publish

【讨论】:

【参考方案4】:

我一直在使用/编写一些 Angular (2+) 库,捆绑和发布的过程一直很痛苦,我发现 this tool 完成了所有工作并使库准备好与 ES5 一起发布, ES6 和 CommonJS 格式。

它非常易于使用,您只需在 tsconfig 中放置一个文件(入口文件),我将抓取您的所有文件并捆绑您的 Angular 库,它还内联样式和组件模板!

我认为它对其他人有用。

祝你好运。

【讨论】:

以上是关于如何在 npm 上发布 angular 2 typescript 库的主要内容,如果未能解决你的问题,请参考以下文章

如何正确将 angular 2 (npm) 升级到最新版本?

在 Meteor 1.3 + angular1 上使用 npm(凹凸!)

使用 TS 但没有 NPM 在 Angular2 上开发

自定义npm包——typeScript版本

如何在离线时安装 npm 包?

将 Typescript 2.3 模块发布到 NPM 以供 Angular 4 使用