I have created a typescript library for angular 2 which facilitates the to access my backend service.
So far it's a private repo, but I want to upload it as an open source library to github and register it on npm.
I'm not really sure what to do now, since documentation on this subject is not easy to find.
the folder structure looks like this:
src
|--sdk.ts // entry point
|--services
|--auth.ts
|--database.ts
|--5 more ts files
|--utils
|--utils.ts
|--interfaces.ts
|--tests (8 ..spec.ts files)
my entry point (sdk.ts) looks like this
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 }
]
}
}
}
and here's the webpack.config.js which doesn't really do what I want...
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']
}
]
}
};
I'm not sure if webpack is even the right choice..or wether is should be bundled and minified or not. Any hints and tipps are welcome!
Cheers
The publishing process itself is pretty easy:
# Login with your existing npm user
npm login
# Bump library version
npm version --patch
# Publish your library
npm publish
The hardest part is to correctly prepare the content of your package.json
and the folder that will hold you build library (one of the common way to name it is dist
).
Your dist
folder should contain files that are ready to be consumed by Angular JIT projects as well as by Angular AOT projects. It is also should contain your library bundle that is ready to be consumed by the browser directly (let's say via SystemJS).
In a result your dist folder should contain the following files:
In this case your package.json should be notified about your build files via main
, module
and typings
fields:
{
...
"main": "./dist/index.umd.js",
"module": "./dist/index.js",
"typings": "./dist/index.d.ts",
...
}
You may find more detailed description of what files should be in dist
folder and how to compile them in How to create AOT/JIT compatible Angular 4 library with external SCSS/HTML templates article
Angular University has a good, step by step, tutorial on publishing an Angular 2 library to npm that addresses your concerns/questions.
You can provide a bundled and unbundled version if you wish, I would always provide an unbundled version though. In my libraries I do not provide a bundled version and leave it up to the consumer to bundle and minify.
http://blog.angular-university.io/how-to-create-an-angular-2-library-and-how-to-consume-it-jspm-vs-webpack/
The following steps will go through the process of creating, testing and publishing an unbundled angular module for consumption by a consumer using a bundler (webpack, angular cli, etc). For a more complete answer which includes bundling, see @OleksiiTrekhleb's answer.
Publishing an angular 2 library can be intimidating, but when it comes down it it's really no different than publish any other package on NPM. The following information will use the folder structure:
As with any typescript library you want to have the declaration
option set to true in your tsconfig.json
under compilerOptions
to ensure our consumers can take advantage of types within our package:
"declaration": true
In compilerOptions
we also want to specify our outDir
to keep transpiled code separate from the source:
"outDir": "./dist"
We want the include
option to point to our source folder (note include
is a sibling in relation to compilerOptions
):
"include": [
"./src"
]
Enable the experimental decorator options under compilerOptions
:
"experimentalDecorators": true,
"emitDecoratorMetadata": true
To avoid some errors when transpiling, you will need to enable skipLibCheck
as well:
"skipLibCheck": true
Result
{
"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"
]
}
This example will use a module with a single component. The component is fairly straight forward:
./src/helloWorld/helloWorld.component.ts
import { Component } from "@angular/core";
@Component({
selector: 'hello-world',
template: '<div>Hello, world</div>'
})
export class HelloWorldComponent {
}
The module should add consumable components to declarations
and exports
. We need to add to exports so when consumers import our module, they can use our components as well.
./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 {
}
To simplify importing our modules we use a barrel, which file that exports everything to be consumed by our consumers.
./src/index.ts
export { HelloWorldModule } from './helloWorld/helloWorld.module';
export { HelloWorldComponent } from './helloWorld/helloWorld.component';
Package.json
In package.json
, change the main
property to point to our transpiled barrel, ./dist/index.js
. Also add the typings
property to point to our barrels definition file ./dist/index.d.ts
.
Add the property prepublish
under scripts in your package.json
.
"scripts": {
"prepublish": "tsc"
}
Also note that your angular and related dependencies should be under peerDependencies
and not dependencies
NPM Ignore
Create a .npmignore
file in the root of your package and ignore the src
folder and any other files you do not want published with your package
src/
*.log
You can easily test your npm packages locally with npm link. In your module package folder, run the command npm link
.
Then in your test project, run the command npm link <my package name>
Now you can import your module and add it to your test projects imports without having to publish.
Your package can now be published with a simple npm publish
For those who are still trying to figure out how to do it:
Create your library using @jvandemo's Angular Lib Yeoman generator
After that you just run: npm adduser
and npm publish
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With