浅谈webpack下的AOP式无侵入注入


Posted in Javascript onNovember 12, 2017

说起来, 面向切面编程(AOP)自从诞生之日起,一直都是计算机科学领域十分热门的话题,但是很奇怪的是,在前端圈子里,探讨AOP的文章似乎并不是多,而且多数拘泥在给出理论,然后实现个片段的定式)难免陷入了形而上学的尴尬境地,本文列举了两个生产环境的实际例子论述webpack和AOP预编译处理的结合,意在抛砖引玉。当然,笔者能力有限,如果有觉得不妥之处,还请大家积极的反馈出来, 共同进步哈。

重要的概念

AOP: 面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

Joint point:表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。

Advice:Advice 定义了在 pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。

通过前面的定义,我们可以提炼出一句更简单的定义,利用静/动态的方式使代码块在何时/何地运行。

性能统计

项目的背景是一个利用vue+webpack打造的多页面应用 (多入口点),她的结构大概是这个样子的

var baseConf = {
// code here
entry: {
index: 'src/index',
list: 'src/list',
detail: 'src/detail',
// and so on ...
},
// code here
}

然后以index入口点举例,大概代码为src/index/index.js

import Vue from 'vue'
import App from './app'
new Vue({
el: '#app',
render: h => h(App)
})

期望引入一个vue插件,能够自动的监控当前页面的性能,于是,代码看起来像是这个样子

import Vue from 'vue'
Vue.use(performance) //性能统计
import App from './app'
new Vue({
el: '#app',
render: h => h(App)
})

由于这种方式意味着每个入口点均需要进行修改,(实际上这个项目的入口点超过30个,而且随时可能继续增加下去)简直就是一个体力活。所以,让我们用AOP的思想来考虑一下如何处理这个问题

首先观察入口点逻辑

原:引入vue -> 引入app组件 -> 实例化vue组件

新:引入vue -> 应用性能统计组件 -> 引入app组件 -> 实例化vue组件

套用到我们的定义上,可以轻松的得到

Joint point(何处) 引入vue

advice(何时) 之后

这样理论上的东西似乎闭着眼睛都可以推论出来,但是如何将这样的步骤替换到每一个入口点就是一个大问题了orz。幸运的是这是一个import,而翻阅webpack的文档恰好有着这样一个神奇的属性--alias

resolve: {
alias: {
'vue$': resolve('src/vueHook.js')
}

src/vueHook.js

import vue from 'vue/dist/vue.common'
vue.use(performance)
export default vue

这样,我们就完成了一个vue的全局钩子模块,我们按照步骤归纳,并且找到注入的位置 ,最后利用替换的方式成功的完成了无侵入式的组件应用

code spliting

可能上面的例子有点小打小闹的感觉,那么我们换一个案例,再来体验一下这种静态替换式的注入的威力,我们采用官方支持较差的react作为参考(vue在code spliting方面做得真心是超级棒~)

import SingleImage from '../../component-modules/magic-single-image/src/index';
import DoubleImage from '../../component-modules/magic-double-image/src/index';
import ThreeImage from '../../component-modules/magic-three-image/src/index';
// many component here
switch (componentName) {
case 'SingleImage':
PreviewingComponent = SingleImage;
break;
case 'DoubleImage':
PreviewingComponent = DoubleImage;
break;
case 'ThreeImage':
PreviewingComponent = ThreeImage;
break;
// many component here
}
return(<PreviewingComponent></PreviewingComponent>)

一段中规中矩的代码,对吧?相信大家已经发现了,在上述的代码里面似乎并不是每个组件都是必须的,那么,基于以上的思考,可以对上面组件进行按需加载处理。 Bundle.jsx

import React, { Component, PropTypes } from 'react';
class Bundle extends Component {
static propTypes = {
load: PropTypes.func,
children: PropTypes.func,
}
state = {
mod: null,
}
componentWillMount() {
this.load(this.props);
}
componentWillReceiveProps(nextProps) {
if (nextProps.load !== this.props.load) {
this.load(nextProps);
}
}
load(props) {
this.setState({
mod: null,
});
props.load().then((mod) => {
this.setState({
// handle both es imports and cjs
mod: mod.default ? mod.default : mod,
});
});
}
render() {
return this.state.mod ? this.props.children(this.state.mod) : null;
}
}
export default Bundle;

以及相应的alias hook

export default (
<Bundle
load={() => import(/* webpackChunkName: "widget" */
`../../component-modules/magic-single-image/src/index`
)}
>
{Widget => <Widget {...props} />}
</Bundle>
)

思考,当组件多的时候每一个模块都需要一个人口点吗,可以从webpack.context角度简化这个问题吗?

以上两个例子均是模块引用作为join point来进行注入操作的,而且完成了无侵入式的功能增强,这得益于webpack将js模块作为一等公民。我们拥有着超多的权利完成静态式的注入工作。 本文并没有在技术上涉及太多,还是那句话,抛砖引玉哈~~~

以上这篇浅谈webpack下的AOP式无侵入注入就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript 自定义类型方法小结
Mar 02 Javascript
javascript dom追加内容实现示例
Sep 21 Javascript
javascript获取ckeditor编辑器的值(实现代码)
Nov 18 Javascript
js利用prototype调用Array的slice方法示例
Jun 09 Javascript
JS实现在页面随时自定义背景颜色的方法
Feb 27 Javascript
14款经典网页图片和文字特效的jQuery插件-前端开发必备
Aug 25 Javascript
Javascript中引用类型传递的知识点小结
Mar 06 Javascript
Jquery EasyUI $.Parser
Jun 02 jQuery
详解基于node的前端项目编译时内存溢出问题
Aug 01 Javascript
JavaScript设计模式之装饰者模式定义与应用示例
Jul 25 Javascript
iview实现select tree树形下拉框的示例代码
Dec 21 Javascript
Node配合WebSocket做多文件下载以及进度回传
Nov 07 Javascript
JQ图片文件上传之前预览功能的简单实例(分享)
Nov 12 #Javascript
JS实现小球的弹性碰撞效果
Nov 11 #Javascript
jQuery实现checkbox即点即改批量删除及中间遇到的坑
Nov 11 #jQuery
解决vue组件中使用v-for出现告警问题及v for指令介绍
Nov 11 #Javascript
JS Input里添加小图标的两种方法
Nov 11 #Javascript
fetch 使用及如何接收JS传值
Nov 11 #Javascript
AngularJS使用ng-repeat遍历二维数组元素的方法详解
Nov 11 #Javascript
You might like
Base64在线编码解码实现代码 演示与下载
2011/01/08 PHP
php防止伪造的数据从URL提交方法
2014/06/27 PHP
PHP 实现类似js中alert() 提示框
2015/03/18 PHP
16个最流行的JavaScript框架[推荐]
2011/05/29 Javascript
ExtJs Excel导出并下载IIS服务器端遇到的问题
2011/09/16 Javascript
在标题栏显示新消息提示,很多公司项目中用到这个方法
2011/11/04 Javascript
javascript制作sql转换为stringBuffer的小工具
2015/04/03 Javascript
php+ajax+jquery实现点击加载更多内容
2015/05/03 Javascript
jQuery对象的链式操作用法分析
2016/05/10 Javascript
angularjs实现天气预报功能
2020/06/16 Javascript
使用vue的transition完成滑动过渡的示例代码
2018/06/25 Javascript
Node.js Koa2使用JWT进行鉴权的方法示例
2018/08/17 Javascript
微信小程序实现星级评价效果
2018/12/28 Javascript
ES6 新增的创建数组的方法(小结)
2019/08/01 Javascript
javascript实现倒计时效果
2020/02/17 Javascript
Vue中使用better-scroll实现轮播图组件
2020/03/07 Javascript
[38:44]DOTA2上海特级锦标赛A组小组赛#2 Secret VS CDEC第二局
2016/02/25 DOTA
[51:17]Mineski vs Secret 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.22
2019/09/05 DOTA
python中list常用操作实例详解
2015/06/03 Python
Python使用遗传算法解决最大流问题
2018/01/29 Python
Matplotlib中文乱码的3种解决方案
2018/11/15 Python
Python实现自动访问网页的例子
2020/02/21 Python
Django用户身份验证完成示例代码
2020/04/03 Python
解析python 类方法、对象方法、静态方法
2020/08/15 Python
python matplotlib工具栏源码探析二之添加、删除内置工具项的案例
2021/02/25 Python
Calzedonia美国官网:意大利风格袜子、打底裤和沙滩装
2018/07/19 全球购物
NICKIS.com荷兰:设计师儿童时装
2020/01/08 全球购物
捷克母婴用品购物网站:Feedo.cz
2020/12/28 全球购物
《广玉兰》教学反思
2014/04/14 职场文书
产品设计开发计划书
2014/05/07 职场文书
部队2014年终工作总结
2014/11/27 职场文书
2015个人年度工作总结范文
2015/05/28 职场文书
宾馆客房管理制度
2015/08/06 职场文书
Python如何把不同类型数据的json序列化
2021/04/30 Python
Python+tkinter实现高清图片保存
2022/03/13 Python
使用Bandicam录制鼠标指针并附带点击声音,还可以添加点击动画效果
2022/04/11 数码科技