美文网首页DTeam团队日志
Angular第三方库开发实践

Angular第三方库开发实践

作者: Laura_hu | 来源:发表于2019-03-23 22:30 被阅读91次

    从接触Angular到如今,做了不少Angular项目,使用了不少第三方库,但是却没有勇气触碰第三方库的开发,一是没有太多的积累,二是没有找到合适的“Hello world”的文档。
    最近有机会要把项目中常用的Component做成第三方库,方便更多的项目使用。根据网上找到的各种资料,加上走的各种弯路,终于摸清楚了开发第三方库的流程。

    搭建项目框架

    为了方便第三方库的开发,我们首先要创建一个主应用A:

    ng new projectnameA    //创建主应用
    

    主应用A创建好之后,创建Lib:

    cd projectnameA
    ng g library libName --prefix  prefixName //--prefix是Lib使用的前缀
    

    上述命令会对主应用如下改变:

    1. 在主应用A下创建 projects/libName 目录,并将Lib的相关文件放于此;

    2. 在 angular.json 文件中添加 libName 项目;

       "libName": {
         "root": "projects/libName",
         "sourceRoot": "projects/libName/src",
         "projectType": "library",
         "prefix": "dteam-top",
         "architect": {
           "build": {
             "builder": "@angular-devkit/build-ng-packagr:build",
             "options": {
               "tsConfig": "projects/libName/tsconfig.lib.json",
               "project": "projects/libName/ng-package.json"
             },
             "configurations": {
               "production": {
                 "project": "projects/libName/ng-package.prod.json"
               }
             }
           },
           "test": {...},
           "lint": {...}
         }
       }
      

      其中:
      root为Lib的根目录;
      sourceRoot为Lib的源代码目录;
      projectType为项目的类型;
      prefix为组件使用的前缀;
      architect为Angular的构建配置,可设置 build、test 和 lint。

    3. 在 package.json 文件中添加 ng-packagr 依赖;

    4. 在 tsconfig.json 文件中添加 libName 库的引用;

          {    
              ...
              "paths": {
                  "libName": [
                      "dist/libName"
                  ]
              }
              ...
          }
      

    这样项目框架就搭建好了,可以开始写Lib的代码了。

    Lib开发

    在Lib中需要注意一个文件:public_api.ts,这个文件是Lib的入口文件,取代了之前使用的index.ts文件,其中定义了Export的内容:

    ````
    export * from './app/libName.component';
    export * from './app/libName.module';
    ````
    

    主应用A要使用Lib,在app.module.ts文件中直接引用:

    import { LibNameModule } from '../../../../projects/libName/src/app/libName.module'
    
    imports: [
        ...
        LibNameModule,
        ...
    ]
    

    对于Lib中使用的其他组件,可在主应用A下通过npm安装,这里提醒下,这里是安装到主应用A的目录下,修改的是主应用A的package.json和package.lock.json文件。
    这样,就可以开发自己的Lib了。

    测试Lib的安装

    Lib开发好之后,需要先在本地试安装。这时有疑问了,Lib中用到的其他组件的引入都是在主应用A的package.json中声明的,这对于Lib是不对滴。
    细心的开发者会发现,在Lib的目录下也有一个package.json文件,其缺省内容为:

    {
        "name": "libName",
        "version": "0.0.1",
        "peerDependencies": {
            "@angular/common": "7.0.2",
            "@angular/core": "7.0.2",
        }
    }
    

    我们需要把这个文件补充完整,将Lib中用到的其他第三方组件在peerDependencies中引入,并将Lib的其他属性也加入。例如:

    {
        "name": "ligName",
        "version": "0.0.1",
        "keywords": ["keyword1","keyword2"],
        "license": "MIT",
        "author": "authorName",
        "description": "description",
        "peerDependencies": {
            "@angular/common": "7.0.2",
            "@angular/core": "7.0.2",
            "@angular/forms": "7.0.2",
            "@angular/router": "7.0.2", 
            "@angular/cdk": "7.0.2",
            "@angular/material": "7.0.2",
            "ngx-spinner": "7.0.0",
            "ngx-clipboard": "12.0.0", 
            "ethers": "4.0.27",
            "rxjs": "6.3.3"
        }
    }
    

    同时,还可以添加一个README.md文件,介绍Lib的使用方法。
    准备工作做好之后,将Lib编译成产品:

    ng build libName --prod
    

    编译后的文件会放置在主应用A的dist/libName目录下。另外创建一个Angular应用B,在此应用下执行:

    npm install 主应用A/dist/libName 
    

    安装时会对libName使用的其他第三方库给出类似如下的提示:

    npm WARN libName@0.0.1 requires a peer of @angular/core@^7.2.0 but none is installed. You must install peer dependencies yourself.
    

    根据提示,自行安装缺少的组件即可。
    在应用B的package.json中会看到对libName的引入:

     "libName": "file:../projectnameA/dist/
    

    在应用B的package-lock.json文件中加入如下内容:

    "libName": {
      "version": "file:../projectnameA/dist/libName",
      "requires": {
        "tslib": "^1.9.0"
      },
      "dependencies": {
        "tslib": {
          "version": "1.9.3",
          "bundled": true
        }
      }
    }
    

    在应用B的app.module.ts文件中引入libName:

    import { LibNameModule } from 'libName';
    
    ...
    imports: [
        ...
        LibNameModule,
        ...
    ],
    ...
    

    在应用B中可以测试libName能否正常使用。

    Lib发布

    上述过程结束后,就可以将应用发布到npm上。准备工作:

    1. npm上注册账号。
    2. 在命令行下执行:npm adduser,将账号添加到本地。

    好了,可以发布libName了。进入到projectnameA/dist/libName目录下执行:

    npm publish
    

    看到了发布成功提示,还有点小激动。进入到npm中,可以看到已经发布成功的libName。
    如果想删除这个libName,可以使用如下命令:

    npm unpublish libNamet@0.0.1 --force
    

    这里需要特别注意的是:删除后的libName,在24小时内不能再发布了,见如下提示:

    npm ERR! libName cannot be republished until 24 hours have passed. 
    

    总结

    npm为第三方库的开发还提供了一些便利的方法,如npm link命令。这些都有待我们在今后的开发中摸索和体验,以便更好的打磨精品组件。

    附录

    在开发过程中遇到了几个错误,现汇总如下:

    1. 权限错误:

       npm ERR! publish Failed PUT 403
       npm ERR! code E403
       npm ERR! You do not have permission to publish "libName". Are you logged in as the correct user? : libName
      

      解决办法,执行: npm adduser

    2. libName若注入了其第三方的服务,主应用调用时出现如下错误:

      Error: inject() must be called from an injection context 
      

      解决方法,在主应用的angular.json文件中添加:

      "projects": {
          "projectName": {
              "architect": {
                  "build": {
                      "options": {
                          "preserveSymlinks":true
                      },
                  },
              }
          }
        }
      },
      
    3. 若libName定义了自己的route,需要在主应用中注入RouterModule。

    相关文章

      网友评论

        本文标题:Angular第三方库开发实践

        本文链接:https://www.haomeiwen.com/subject/ixievqtx.html