如何为多个 AngularJS 项目使用相同的代码库

How to use same Code base for multiple AngularJS projects

此问题是关于代码 angularJS 中的可重用性。

背景信息:我目前的应用程序(application1)在客户端使用angularjs + kendo UI,它是正在制作中。

我们将使用相同的技术再开发 4 个应用程序。 即将推出的 4 个应用程序的功能与应用程序 1 几乎 70-80% 相似。

在这一点上,我的管理层不想创建一个应用程序(它包含一个屋檐下所有 5 个应用程序的功能)。

当前approach/goal是:

1.create 5 个独立的应用程序,服务器端也有 5 个不同的 应用程序

2.reuse客户端代码尽可能多

我目前的计划:

  1. 分离出公共代码,并将此代码保留为核心模块的一部分(app.js)。

  2. 代码重构 - 按照 this link.

  3. 中的建议移动到 'feature based directory' 结构
  4. 为每个功能创建一个 angular 模块(大约 10 个模块)。

我的疑问是 - 因为我将对所有 5 个应用程序使用相同的“common”代码(复制粘贴截至现在),

我如何才能让这个通用代码在不同的应用程序中表现不同?

例如

  1. 如果应用程序 1,服务调用 /app1/gettasks 或者如果应用程序 2,服务调用 /app2/gettasks,在这种情况下,我如何通过 app1/app2/app3...在运行时?这是可配置的吗?

  2. 简单来说,我如何将 applicationName 告诉 angular 代码?之后,我可以像下面这样检查 applicationName...(伪代码)

    if(applicationName == app1){
       //do app1 specific things
    }else if (applicationName==app2) {
       //do app2 specific things
    }
    

PS: 在服务器端我使用 Spring Boot.

请post你的想法...

更新:

在我的公共代码中,有服务、指令和过滤器。 对于指令和过滤器 - 没有特定于应用程序的代码

  1. 但是,在 Services 中,我如何制作特定于应用程序的 REST URL

  2. While/after用户登录,"common code"如何知道当前应用名称?是application1还是2还是3?

您可以将控制器创建为对象,然后扩展每个项目的默认控制器以添加特定行为,并使用服务。

喜欢这里: https://github.com/nuxeo/nuxeo-drive/blob/master/nuxeo-drive-client/nxdrive/data/ui5/js/ndrive-settings.js

一个可能的解决方案是 -

  • 每个客户端应用程序维护一个 'config' 属性 文件
  • 根据这些配置值,使用 GruntGulp 等构建工具来 pre-process 您的 html/js/css 文件。它基本上是一个 text-search-replace 和条件包含。

例如https://github.com/jsoverson/grunt-preprocess

感谢@FrailWords 的回答。

我完成了为多个 angular 使用相同 UI 代码库的提议 applications.I 在这里分享我的想法。

有些方法和我在这个问题中提到的一样。

本提案要遵循的策略列表:

1.  Switch to feature based directory structure. 
2.  Create an angular module for each feature.
3.  Separate common code from instance specific code.
4.  Merge duplicate code.
5.  Remove unused code and outdated libraries.
6.  Re-organize codebase.
7.  Make common code as configurable.
8.  Use same configurable common code for all 5 instances.
9.  Use inheritance or similar mechanisms for extended functionality.
10. Identify & Move functions (methods) from instance specific code to common code.
11. Follow naming conventions.
12. Manage future requirements.
13. Use build tools like gulp or grunt and testing frameworks like jasmine.
14. Application specific look & feel.

如何实施这些策略:

我们将在下面看到每个策略的 solutions/approaches。

1.切换到基于功能的目录结构。

当前目录结构:

它基于angular layers/types。也就是说,我们将所有控制器放在一个文件夹中,将所有服务放在另一个文件夹中等等。这是很好的小型应用程序。

示例:

建议的目录结构:

/resources
--/ui_core                                                      ui-core or common code
-----/app
-------------------core_module.js                   inject all modules from /ui_core/modules into this 
-------------------config_module.js                declare constants and inject into core_module 
-----/shared_services                                   part of core_module 
-----/shared_directives                                part of core_module – place directive’s js+html here
-----/shared_filters                                       part of core_module 
-----/shared_views                    
-----/shared_interceptors                 
-----/shared_content
------------/images
------------/icons
------------/signatures
-----/modules
 ------------/common_feature1
-------------------common_feature1_module.js
-------------------common_feature1Controller.js
-------------------common_feature1Service.js
-------------------common_feature1Directive.js
-------------------common_feature1Filter.js                                  if any
-------------------common_feature1_view.html
-------------------common_feature1_test.js
-------------------common_feature1.css                                         if any
------------/common_feature2
-------------------common_feature2_module.js
-------------------common_feature2Controller.js
-------------------common_feature2Service.js
-------------------common_feature2Directive.js
-------------------common_feature2Filter.js
-------------------common_feature2_view.html
-------------------common_feature2_test.js
-------------------common_feature2.css
-----/vendor                                                                      downloaded vendor libraries
------------/js
-------------------/angular
-------------------/kendo
-------------------/jquery
------------/css
-------------------/kendo
-------------------/bootstrap
------------/images
-------------------/kendo
-------------------/bootstrap
--/ui_equity                                    application specific code – for example: equity
-----/app                 
-------------------equity_module.js  inject ui_core module/any module as required.
-----/shared_services                     part of equity_module 
-----/shared_directives                  part of equity_module  – place directive’s js+html here
-----/shared_filters                         part of equity_module 
-----/shared_views
-----/interceptors
-----/content
------------/images
------------/icons
------------/signatures
-----/modules
 ------------/feature1
-------------------feature1_module.js
-------------------feature1Controller.js
-------------------feature1Service.js
-------------------feature1Directive.js
-------------------feature1Filter.js
-------------------feature1_view.html
-------------------feature1_test.js
-------------------feature1.css
------------/feature2
-------------------feature2_module.js
-------------------feature2Controller.js
-------------------feature2Service.js
-------------------feature2Directive.js
-------------------feature2Filter.js
-------------------feature2_view.html
-------------------feature2_test.js
-------------------feature2.css
--/minified
-----/ui_core
-----/ui_equity 
/webapp
-----/WEB-INF
------------/jsp
-------------------index.jsp
-------------------jsincludes.jsp
-------------------cssincludes.jsp
-------------------imageviewer.jsp
-------------------unauthorized.jsp

2。为每个功能创建一个 angular 模块。

为了使我们的应用程序模块化,为我们应用程序的每个主要 feature/functionality 创建一个 angular 模块。我们可以在任何需要的地方注入这些模块。

好处:

  1. 易于重用模块化应用程序。

  2. 提高可读性:无需将单个组件注入其他组件,注入模块就足够了。

3.将公共代码与实例特定代码分开。

可以成为ui_core(公共代码)

一部分的项目列表
a.  Most of the directives
b.  Filters
c.  Utilities , such as arrayUtilities.js, dateUtilities.js, stringUtilities.js
d.  Services
e.  KendoGridServices & relevant controllers.
To make   kendoGrid as part of common code, below changes are required.

For example,
-   Create model outside datasource - Currently schema “model” is hardcoded inside abccontroller.js , instead of this create “kendo model” outside abccontroller.js and pass/inject to abccontroller.js

-   Currently “columns” are hardcoded inside kendoabcgridservice.js. Instead of this, create “columns array” outside and inject it into kendoabcgridservice.js .

-   Similarly, move out any other instance specific code from kendo grid.

下面的策略是不言自明的,所以我们可以转到下一个...

    4.  Merge duplicate code.
    5.  Remove unused code and outdated libraries.
    6.  Re-organize codebase.

7.使通用代码可配置。

一个。在公共代码中创建一个配置模块

( /resources/ui_core/app/ config_module.js).

b。例如,在该模块内声明常量 APP_NAME = ‘equity’ 以及任何需要的东西。

c。修改公共代码(ui_core),使用APP_NAME常量, 因此相同的代码块对于不同的应用程序会有不同的行为。

例如,

而不是 $resource(‘/equity/tasks’) 使用 $resource(‘/APP_NAME/tasks’)

注意: 以上仅为示例目的(截至目前),服务调用 URL 的更改将在 Server/Java 端重构后最终确定。

示例 2:

If (APP_NAME == ‘equity’){
             //do ‘equity’ specific things
} else if (APP_NAME == ‘commodities’){  
           //do ‘commodities’ specific things
} else {
……………..
}

8.对所有 5 个实例使用相同的可配置通用代码。

    As explained earlier

9.使用继承或类似机制来扩展功能。

如果我们除了可用的功能之外还需要其他功能,而不是复制和粘贴现有文件并向该文件添加代码,我们可以在 angular 中使用继承类型的机制,如下所示。

使用

angular.extend 
Or 
angular.copy

或类似的方法。

10。识别并将函数(方法)从实例特定代码移动到通用代码。

As explained earlier

11。遵循命名约定

为了更好的可维护性和一致性,定义并遵循特定的文件命名约定。

例如,

如果功能名称是‘user’,那么命名可以像下面这样。

/modules
-----/user
----------user_controller.js
----------user_service.js
----------user_directive.js
----------user_view.html
----------user_test.js

遵循 user_controller.js 或 user_ctrl .js,但是,永远不要同时执行两者。

12。管理未来需求

当我们生活在现实世界中时,改变和提升是生活的一部分。 一旦我们实施了上述提案,就可以很容易地modify/enhance这些功能而不影响应用程序的其他部分。

无论如何,在向现有代码库添加任何功能之前,问自己这个非常重要的问题(此应用程序的开发人员) .

哪里我要添加这个功能,在通用代码还是应用程序特定代码?

Enjoy and Have Fun :-)