webpack工具鏈熱替換 -- angularjs的粗放式實現

ng-hot-loader

前言

webpack-dev-server自帶支持模塊熱替換特性(HMR),不刷新頁面實現代碼局部更新,使用HMR能夠大幅提高開發效率。javascript

實現目標

  • [x] 樣式熱替換 -- style-loader自己即支持HMR,建議依賴庫css直接解析出文件link,下降熱替換成本css

  • [x] 模板熱替換html

  • [x] 服務熱替換java

  • [x] 過濾器熱替換 -- expression 變更纔會從新實例化過濾器webpack

  • [x] 指令熱替換 -- 目前low level的支持git

  • [x] 控制器熱替換angularjs

實現策略

合理劃分angular模塊,將angular模塊劃分爲主模塊,業務模塊。路由, 業務服務全局服務合理分散到主模塊與業務模塊中。參照angular組件單一職責,單個模塊(文件)僅承擔有限職責,。github

HMR關鍵核心爲組件聲明 => 組件定位 => 組件更新web

  • 文件命名建議按照官方styleguideexpress

  • 關聯filter, service, directive在單一模塊中聲明。

  • 關鍵核心依舊在模塊,路由聲明。路由聲明中,模板與控制器統一採用ES6引入方案,template: templateVariable,控制器聲明統一採用pure function的方式,而不是字符串的方式。

  • 路由聲明與組件聲明在*.module.js統一文件內部聲明。

  • 控制器暫時不考慮經過$controllerProvider註冊的類型。

  • 路由不考慮熱更新。

  • 全部模板文件,都經過ES6 default import導入,JS文件建議所有經過destruct的方式引用。

/**
 * @description - application level router config.
 * @author bornkiller <hjj491229492@hotmail.com>
 */

'use strict';

// layout module dependency
import layoutAuthorizeTemplate from './authority/authorize.html';
import { AuthorizeController } from './authority/authorize.controller';

import layoutNavbarTemplate from './flow/navbar.html';
import layoutSidebarTemplate from './flow/sidebar.html';
import layoutCoreTemplate from './flow/core.html';
import { SidebarController } from './flow/sidebar.controller';


// layout module name
const LAYOUT_MODULE = 'app.layout';

// layout module router
const LayoutRoute = [
  {
    name: 'authorize',
    url: '/authorize',
    views: {
      'core': {
        template: layoutAuthorizeTemplate,
        controller: AuthorizeController,
        controllerAs: 'vm'
      }
    }
  },
  {
    name: 'application',
    url: '/application',
    views: {
      'navbar': {
        template: layoutNavbarTemplate
      },
      'sidebar': {
        template: layoutSidebarTemplate,
        controller: SidebarController,
        controllerAs: 'vm'
      },
      'core': {
        template: layoutCoreTemplate
      }
    }
  }
];

angular.module(LAYOUT_MODULE, [])
  // eslint-disable-next-line angular/di
  .config(['$stateProvider', function ($stateProvider) {
    LayoutRoute.forEach((route) => {
      $stateProvider.state(route);
    });
  }]);

export { LAYOUT_MODULE };

模塊劃分

經過劃分模塊實現最終目標:

  • ng-hot-analyzer - 分析組件的聲明與定位,主要包括importregister token的分析。最終彙總,實現模塊定位 <--> 模塊導出實例 <--> NG組件註冊的圖譜。

  • ng-hot-loader - 匯聚子模塊操做,基於分析結果與對應模板,生成對應HMR代碼。

  • ng-hmr - 熱更新具體實現。

組件替換約定

服務在angularjs內部屬於單例,實例聲明經過factory的方式,聲明literal object服務。

過濾器僅支持ng-bind使用。

模板熱替換目前採用較爲粗放的容器定位策略,基於最近的ui-router view進行局部替換。

指令熱替換一樣採用較爲粗放的容器定位策略,經過路由模板替換實現。

控制器統一使用ES6 Class聲明,字段更新策略以下:

  • [x] 刪除字段

  • [x] 依賴注入服務,直接override

  • [x] 函數字段,直接override

  • [x] 經過控制器內聲明shouldFieldUpdate方法來精確控制對應字段是否更新。

  • [x] 若是控制器未聲明shouldFieldUpdate方法,默認斷定策略是類型變化,類型出現變化即直接override

HMR示例

if (module.hot) {
  module.hot.accept(['${descriptor.location}'], function () {
    ${translateImportType(descriptor)}
    $hmr.hmrOnChange('${capitalize(descriptor.category)}', '${descriptor.token}', ${descriptor.name});
    $hmr.hmrDoActive('${capitalize(descriptor.category)}', '${descriptor.token}', ${descriptor.name});
  });
};

項目實現

TODO

  • 支持字符串聲明控制器

  • 調整模板scope定位方式

相關文章
相關標籤/搜索