如何在 npm 上发布 angular 2 typescript 库
how to publish angular 2 typescript library on npm
我已经为 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 是否是正确的选择..或者是否应该捆绑和缩小。欢迎任何提示和建议!
干杯
Angular 大学有一个很好的、循序渐进的教程,介绍如何将 Angular 2 库发布到 npm 来解决您的 concerns/questions.
如果您愿意,您可以提供捆绑和非捆绑版本,不过我总是会提供非捆绑版本。在我的库中,我不提供捆绑版本并将其留给消费者捆绑和缩小。
更新答案
以下步骤将完成创建、测试和发布未捆绑的 angular 模块以供消费者使用捆绑器(webpack、angular cli、 ETC)。有关包括捆绑在内的更完整的答案,请参阅@OleksiiTrekhleb 的答案。
发布一个 angular 2 库可能令人生畏,但当它归结起来时,它与在 NPM 上发布任何其他包真的没有什么不同。以下信息将使用文件夹结构:
- 包根目录
- 源码
- 距离
1。正在设置 tsconfig.json
与任何打字稿库一样,您希望在 compilerOptions
下的 tsconfig.json
中将 declaration
选项设置为 true,以确保我们的消费者可以利用我们包中的类型:
"declaration": true
在 compilerOptions
中,我们还想指定 outDir
以将转译后的代码与源代码分开:
"outDir": "./dist"
我们希望 include
选项指向我们的源文件夹(注意 include
是 compilerOptions
的兄弟):
"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 {
}
模块应该添加消耗组件到declarations
和exports
。我们需要添加到导出,以便当消费者导入我们的模块时,他们也可以使用我们的组件。
./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"
}
另请注意,您的 angular 和相关依赖项应位于 peerDependencies
而不是 dependencies
NPM 忽略
在包的根目录中创建一个 .npmignore
文件并忽略 src
文件夹和您不想与包一起发布的任何其他文件
src/
*.log
5。测试
您可以使用 npm link 在本地轻松测试您的 npm 包。在您的模块包文件夹中,运行 命令 npm link
.
然后在你的测试项目中,运行命令npm link <my package name>
现在您可以导入您的模块并将其添加到您的测试项目导入中,而无需发布。
6。发布
您的包现在可以通过简单的 npm publish
发布
对于那些仍在努力弄清楚如何去做的人:
使用@jvandemo 的 Angular Lib Yeoman generator
创建您的库
之后你只需 运行: npm adduser
和 npm publish
发布过程本身非常简单:
# 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.map, index.umd.min.js.map - 用于调试目的
- *.js — [由 tsc 制作,记住 ngc 是一个包装器]编译的 JavaScript 组件或服务 *.ts 文件的表示你的库.
- *.d.ts — [由tsc制作,记住ngc是一个wrapper]声明文件。由于带有类型的 *.ts 文件被转换为不支持类型的 *.js 文件,因此 TypeScript 编译器需要将所有类型信息放入单独的 *.d.ts 文件中,以便能够使用这些 *.稍后在 TypeScript 项目中添加 js 文件。顺便说一句,有一个 DefinitelyTyped 项目,其中有很多类型定义,已经为大量 JS 非 TypeScript 库做出了贡献。
- *.metadata.json — 与当前组件(或 NgModule)关联的元数据。它是我们传递给@Component、@NgModule 装饰器的对象的一种 JSON 表示。此文件包含项目(而非库)的 NGC 所需的信息,这些信息位于原始库 *.ts 文件中,但未包含在 *.d.ts 文件中。
在这种情况下,您的 package.json 应该通过 main
、module
和 typings
字段收到关于您的构建文件的通知:
{
...
"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
文件夹中应包含哪些文件以及如何编译它们的更详细说明
我一直在 with/writing 几个 Angular (2+) 个库工作,捆绑和发布的过程一直很痛苦,我发现 this tool工作并使库准备好以 ES5、ES6 和 CommonJS 格式发布。
它非常易于使用,您只需在您的 tsconfig 中放入一个文件(入口文件),我将抓取您的所有文件并捆绑您的 Angular 库,它将组件的样式和模板内联为好吧!
我认为它对其他人有用。
祝你好运。
我已经为 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 是否是正确的选择..或者是否应该捆绑和缩小。欢迎任何提示和建议!
干杯
Angular 大学有一个很好的、循序渐进的教程,介绍如何将 Angular 2 库发布到 npm 来解决您的 concerns/questions.
如果您愿意,您可以提供捆绑和非捆绑版本,不过我总是会提供非捆绑版本。在我的库中,我不提供捆绑版本并将其留给消费者捆绑和缩小。
更新答案
以下步骤将完成创建、测试和发布未捆绑的 angular 模块以供消费者使用捆绑器(webpack、angular cli、 ETC)。有关包括捆绑在内的更完整的答案,请参阅@OleksiiTrekhleb 的答案。
发布一个 angular 2 库可能令人生畏,但当它归结起来时,它与在 NPM 上发布任何其他包真的没有什么不同。以下信息将使用文件夹结构:
- 包根目录
- 源码
- 距离
1。正在设置 tsconfig.json
与任何打字稿库一样,您希望在 compilerOptions
下的 tsconfig.json
中将 declaration
选项设置为 true,以确保我们的消费者可以利用我们包中的类型:
"declaration": true
在 compilerOptions
中,我们还想指定 outDir
以将转译后的代码与源代码分开:
"outDir": "./dist"
我们希望 include
选项指向我们的源文件夹(注意 include
是 compilerOptions
的兄弟):
"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 {
}
模块应该添加消耗组件到declarations
和exports
。我们需要添加到导出,以便当消费者导入我们的模块时,他们也可以使用我们的组件。
./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"
}
另请注意,您的 angular 和相关依赖项应位于 peerDependencies
而不是 dependencies
NPM 忽略
在包的根目录中创建一个 .npmignore
文件并忽略 src
文件夹和您不想与包一起发布的任何其他文件
src/
*.log
5。测试
您可以使用 npm link 在本地轻松测试您的 npm 包。在您的模块包文件夹中,运行 命令 npm link
.
然后在你的测试项目中,运行命令npm link <my package name>
现在您可以导入您的模块并将其添加到您的测试项目导入中,而无需发布。
6。发布
您的包现在可以通过简单的 npm publish
发布对于那些仍在努力弄清楚如何去做的人:
使用@jvandemo 的 Angular Lib Yeoman generator
创建您的库
之后你只需 运行:
npm adduser
和npm publish
发布过程本身非常简单:
# 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.map, index.umd.min.js.map - 用于调试目的
- *.js — [由 tsc 制作,记住 ngc 是一个包装器]编译的 JavaScript 组件或服务 *.ts 文件的表示你的库.
- *.d.ts — [由tsc制作,记住ngc是一个wrapper]声明文件。由于带有类型的 *.ts 文件被转换为不支持类型的 *.js 文件,因此 TypeScript 编译器需要将所有类型信息放入单独的 *.d.ts 文件中,以便能够使用这些 *.稍后在 TypeScript 项目中添加 js 文件。顺便说一句,有一个 DefinitelyTyped 项目,其中有很多类型定义,已经为大量 JS 非 TypeScript 库做出了贡献。
- *.metadata.json — 与当前组件(或 NgModule)关联的元数据。它是我们传递给@Component、@NgModule 装饰器的对象的一种 JSON 表示。此文件包含项目(而非库)的 NGC 所需的信息,这些信息位于原始库 *.ts 文件中,但未包含在 *.d.ts 文件中。
在这种情况下,您的 package.json 应该通过 main
、module
和 typings
字段收到关于您的构建文件的通知:
{
...
"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
文件夹中应包含哪些文件以及如何编译它们的更详细说明
我一直在 with/writing 几个 Angular (2+) 个库工作,捆绑和发布的过程一直很痛苦,我发现 this tool工作并使库准备好以 ES5、ES6 和 CommonJS 格式发布。
它非常易于使用,您只需在您的 tsconfig 中放入一个文件(入口文件),我将抓取您的所有文件并捆绑您的 Angular 库,它将组件的样式和模板内联为好吧!
我认为它对其他人有用。
祝你好运。