ng-hot-loader
前言
webpack-dev-server
自带支持模块热替换特性(HMR),不刷新页面实现代码局部更新,使用HMR
可以大幅提升开发效率。
实现目标
[x] 样式热替换 --
style-loader
本身即支持HMR
,建议依赖库css
直接解析出文件link
,降低热替换成本[x] 模板热替换
[x] 服务热替换
[x] 过滤器热替换 --
expression
变动才会重新实例化过滤器[x] 指令热替换 -- 目前
low level
的支持[x] 控制器热替换
实现策略
合理划分angular
模块,将angular
模块划分为主模块,业务模块。路由
,业务服务
,全局服务
合理分散到主模块与业务模块中。参照angular
组件单一职责,单个模块(文件)仅承担有限职责,。
HMR
关键核心为组件声明
=> 组件定位
=> 组件更新
。
文件命名建议按照官方
styleguide
关联
filter
,service
,directive
在单一模块中声明。关键核心依旧在模块,路由声明。路由声明中,模板与控制器统一采用
ES6
引入方案,template: templateVariable
,控制器声明统一采用pure function
的方式,而不是字符串的方式。路由声明与组件声明在
*.module.js
统一文件内部声明。控制器暂时不考虑通过
$controllerProvider
注册的类型。路由不考虑热更新。
/** * @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
- 分析组件的声明与定位,主要包括import
,register token
的分析。最终汇总,实现模块定位 <--> 模块导出实例 <--> NG组件注册的图谱。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.name}); }); };
项目实现
https://github.com/bornkiller... 热替换DEMO
TODO
支持字符串声明控制器
调整模板
scope
定位方式