发布一个属于自己的Library,实现项目模块化能做什么?
它可以实现你的组件从项目中脱离,在多个项目中灵活使用。
这篇文章主要在说什么?
这篇文章主要是从配置出发,扫描知识盲区,带你了解lib的实现过程,其中有大量的知识点,枯燥无味但不得不了解。
1.我将分析lib的实现的意义。
2.我将告诉你如果去实现css这类资源文件的打包。
3.我将我开发过程中了解到,个人认为重要的的记录下来,希望对今后开发有帮助。
在Angular2 以后提出来了一个概念------模块化
这个模块的其实并不新奇,因为从事过Android的开发 ,我很早就知道模块化的好处。
1.只有一个主入口,其他功能可以像积木一样去拼接我们的项目,随时拆解替换。
2.我们多人同时开发的情况下预留出接口,可以做到互不影响功能,降低耦合度。
当然还有其他的好处,在这里就不细说了(毕竟我想藏私),今天的主题不在这里。我打算记录一下,这次探索的心得。
当我接触Angular 前端项目的时候,我为了多快好省采用了ng-bootstrap,primeng,两大框架。但是我在运用的过程中发现他们的控件很大程度上影响了项目功能上的发挥。
第一 primeng 的css 处理做的优化没有bootstrap好,很难去修改primeng 的控件样式。
第二 bootstrap采用全加载的方式,很多模块并用不上,却随着被使用模块一起加载了,影响效率,其次他的css居然是另一个包,我修改样式的时候快疯了。
我不禁思考这2个框架可以不可以整合在一起。既能模块拆分,又能实现css样式的修改。
于是我开始考虑如何去写一个Library。
(篇幅很长,只适合学习交流,不适合vc大法)
提出的第一个问题:怎么去创建一个自己的Angular Library?
因为primeng和bootstrap提供了Angular Library,我就觉的可以写一个自己的Angular Library来满足自己的项目。
于是乎百度得出这么一个流程:
创建第三方包
开发第三方包
测试第三方包
发布第三方包
使用第三方包
嗯,我就不说详细的步骤了 ,反正能百度的就不手写。说几个npm命令
ng new projectname 创建一个新的项目 projectname 是你的项目名称
cd projectname 到新项目目录下下去
ng g library libraryname --prefix prefix # libraryname : 第三方包名字 # prefix : 组件前缀(如 nz-zorro 的组件前都是 nz-xxx)
这三行命令是一个基本步骤。下面我讲解下几个知识点:
首先你在完成上面命令时会生成这个样的目录结构 projects文件夹就是你lib包放的代码了 。默认是libraryname 文件夹下有一个src文件夹然后包涵如图所示没有画红线的文件。
值得我们注意的是 ng-package.json,tsconfig.lib.json,和package.json 三个文件。
这三个文件决定了自己lib的好坏。
在了解这个三个文件之前我们有2个文件不得不了解一下。
angular.json 和package.json
这里又出现了一次package.json
其实这两package.json的作用都是一样的:都是用来定义项目,和发布项目的,他们是基于node的,有node基础的人可以很快从这个文件中读取项目的信息和配置。如果不了解,我在这里指出几个关键的参数简单的过一遍。
2个package.json 的原理是一样的都是为npm服务的。
其中
name 是项目的名称; 你在发布成npm的时候利用的就是这个参数。 version是版本号;利用这个参数你可以实现版本的迭代。 description是对这个包的说明; author作者; peerDependencies,dependencies你的项目所依赖的包区别在于前者可以忽略,后者必须有; 如果你不希望授权别人以任何形式使用私有包或未发布的包,可以这样写"private": false。 还有些参数我就不一一列举了有兴趣可以去看看node和npm 重点来了 scripts 这参数在发布的时候没有什么用,但是在你开发的时候会很有用,它是一个简单的脚本,你可以利用它来执行一些脚本文件。
下面我将结合angular.json来说说scripts
我们看到项目中的angular.json 在Angular CLI 6以后 angular-cli改名为angular.json,在这个的基础上做了一些优化,这个不在本文章的讨论范围类。
我们来所说scripts和angular.json的关系。可以看到angular.json中有个
projects参数 这个参数就是包涵了你的angular工程中的所有项目(ng new projectname 上面我说创建一个新的项目 ,其实是创建的一个工作空间,而projects就是对你工作空间项目的工作说明)
它的语法是{‘projectname ’:{ config...}} ,projectname是你的项目名称,config是你这个项目的配置。重点说说config 因为前面提到的scripts就是和这个config挂钩的
root 你项目的根目录
sourceRoot 你项目的资源目录
上面两个的作用就是定义你文件的起始位置,方便 在项目开发过程中你可以用‘./’代替。
projectType 决定了你的项目是一个 application 还是 library ;library 就是作为我们库存在的; application才是我们的应用项目,我们所有的支撑的主入口。至少我是这么理解的。因为在开发过程中我发现2个都使用ng serve跑起来项目,所以我认为最大的区别就在于一个可以被引用,而另一个不可以。 prefix 仅仅还是定义了你的前缀,如果不写 默认“app”。嗯 就是你的@Component中的selector要写成${prefix}-xxxx的形式。@Component({ selector:"${prefix}-xxxx" })
schematics 这个配置最重要的一点可以决定你得项目是scss,sass,lass还是css。
ok,这次重点真的来了
architect 这个参数就是你的脚本啦。它的语法是{‘scripts’:{ config...}} 重点中的重点还是config
architect它的config由builder ,options, configurations 组成。builder决定你将使用哪个node工具,options, configurations都是对这个功能的配置来实现你要的效果。
举个例子 我们在packag.jso的scripts参数中写下了"start": "ng serve",在architect中写下了
"serve": { "builder": "@angular-devkit/build-angular:dev-server", ... }
那么我们输入scripts npm start 的将会执行ng serve命令从而调用@angular-devkit/build-angular:dev-server的工具。
ok讲到这里我们对package.json和angular.json有了个基本的概念。那么开始对library开发做下讲解。
如何去开发library?
前面说到了ng-package.json,tsconfig.lib.json,和package.json 三个文件。package.json 我们已经了解大概知识,那来所说ng-package.json。(tsconfig.lib.json,我将做为另一个知识点在后面讲。)
我们看到ng-package.json的开头有一个这样的参数
嗯,路径都告诉你了,那就去项目中找找看,这个文件有说明ng-package.json应该怎么去配置(同理,但我们在其他的jjson文件中看到了这个也可以去参考,试着编写参数),下面我们看到lib生成的时候默认的配置。
前面的参数很好理解,核心参数是“ngPackage”,lib 是定义你的入口文件
以 export * from “文件路径”的形式去定义文件。这样你才能保证你的lib在其他项目中能调用你所需要的功能。
这样说可能有点模糊,需要自己去实际体验一番。稍后我将在文章的最后写一个流程并指出每一步的知识点,莫慌兄弟。
在我们配置好了 ng-package.json ,我们就可以开始在我们的lib包下开发我们自己的功能,按项目正常开发模块就好了,值得注意的是它虽然可以写
module,component,injector,directive但是我们不能将资源文件打包(类似css,img,sass,svg)所以我们得出结论这个只能打包ts文件。
好了,接下来就引发了另一个问题
如何打包资源文件?
继续刚才对ng-package.json的讨论。我们发现ng-package.json 有2个参数styleIncludePaths和cssUrl,那么他们可不可以打包资源呢?
经过翻看资料我发现不可以。他们能做到的仅仅是帮助你引用资源文件,但是这些资源文件无法实现本地化。所以我们还是要想办法。
我使用的是scss-bundle这个插件,它能将你的资源文件打包进去。但是我发现了一个更简单粗暴的,直接copy到你打包好的文件夹下就好了。
上传的时候是一起上传的。
为了解惑 我告诉你步骤:
1.到github或者npm上搜索scss-bundle
2.在项目中安装scss-bundle
3.添加一个scss-bundle.config.json在你的library工程下,里面的内容大致如下
(entry:资源文件的位置,dest:资源文件的输出目录,这个json是一个集合,所以你可以写多个这样的对象来导出你所有的资源文件)
{ "entry": "./src/lib/component/menubar/menubar.component.scss", "dest": "../../dist/dhcc-design/lib/menubar/menubar.scss" }
4.在你的library工程下的package.json中,添加和修改你的scripts(如下图):
5.打包的时候执行 build命令就好,资源文件一并打包了
好了。我将知识点差不多快点完了。
最后一个点
tsconfig.lib.json 这个文件其实没有什么好多说的,它就是决定了你打包你的lib或者项目的时候你的ts文件将是以什么样的形式生成。唯一值得注意的是当你创建lib的时候 你需要检查你项目中的angular.json 有没有下面的一段代码
"paths": { "libraryname": [ "xxx/xxx" ], "libraryname/*": [ "xxx/xxx/*" ] }
这段代码是来告诉你的application 你的lib包的路径。但是在你打包以后这个将没有什么作用,因为你的lib将在devDependencies或者dependencies中引用。
其次是你的tsconfig.lib.json 中是否有
"include": [ "./**/*.ts", "./**/*.d.ts" ]
很关键的,它决定了你的lib包涵那些的文件。
ok,我将开发中遇到的疑惑在这里整理了一遍 那么 我还是将整个流程细说一下,不涉及代码
首先 我们要创建一个lib 使用命令
ng g library libraryname --prefix prefix
在生成好的 libraryname 项目下的开发自己的功能。(在生成过程中我们之前提到的所有文件都会自动添加,只要手不抖,就不会出问题)
在开发完成以后,把我们需要导出的功能写在public_api.ts 这个文件下(当然你可以自己定一个名字,但是你要修改ng-package.json的lib下的配置),在默认配置的基础上我们检查一下。
我们分别要检查三个文件ng-package.json,tsconfig.lib.json,和package.json 三个文件,看他们是否满足我们的要求。
然后发布? no!
我们要在application项目中调用,因为你创建lib的时候 angular.json自动生成了paths 所以你可以直接调用lib组件(这个时候你的 css或者说scss都是可以使用的)进行测试,当然你可以使用angular内嵌的karma测试。
测试没有问题后,打包我们的lib (这里又有一个小知识点,虽然我们在打包application和library时都是使用的angular cli自动 build这个命令,但是application使用的是@angular-devkit/build-angular:browser工具,ibrary使用的是@angular-devkit/build-angular:protractor)
可以打包没有问题后(有问题看错误日志解决,谢谢)就可以发布了
发布命令 npm publish
#切到目录
cd dist/libraryname
#发布
npm publish
嗯,好了 这个时候再说个知识点,这个时候你得登录你的npm 不然会报异常,至于是什么异常自己去感受百度吧。
到这里我们开发一个angular library包的知识点差不多了,总结一下,在开发过程中我们首先要熟悉的是他的配置环境。
angular.json,package.json,tsconfig.lib.json,ng-package.json等等,要了解他们能做什么,不能做什么,这需要一定的node基础。End,以上是这次开发我的心得,未来我将开发一个类似ant design的框架,预计三个月后出一个版本。
附上一点参考资料:
https://github.com/ng-packagr/ng-packagr (ng-packgr是angular cli6 以后内嵌的打包lib工具,之前的版本要打包lib也是单独使用它打包的)
https://github.com/ng-bootstrap/ng-bootstrap(ng-bootstrap 的源码地址,bootstrap提供了2种库一个是它一个是ngx-bootstrap)
https://github.com/primefaces/primeng (primeng 的源码地址)
http://www.semlinker.com/ng-library-quickstart/ (喜欢vc的朋友可以直接cv这个 !!! —3 —);
这篇文章仅仅是记录心得,有错误的地方欢迎请指正。
最后的最后附上生成打包的文件目录,同时这个demo我也上传到了npm(当热是打包过的啦,源码不给主要是我的design还么有成型)。
(再说一句话:因为angular library 为了库类应用更自由,建立了一套名为angular package format的打包格式 不同格式可以在不同的环境中使用,所以你会看到esm5啊 这些文件,如果不想要 你去tsconfig.lib.json中修改compilerOptions的参数)