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
注册的类型。路由不考虑热更新。
所有模板文件,都通过
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
- 分析组件的声明与定位,主要包括import
,register 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});
});
};
项目实现
https://github.com/bornkiller... 热替换DEMO
TODO
支持字符串声明控制器
调整模板
scope
定位方式
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。