浅谈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 计算两个整数的百分比值
Dec 26 Javascript
jquery改变tr背景色的示例代码
Dec 28 Javascript
JS实现的用来对比两个用指定分隔符分割的字符串是否相同
Sep 19 Javascript
JavaScript实现页面跳转的几种常用方式
Nov 28 Javascript
基于JavaScript将表单序列化类型的数据转化成对象的处理(允许对象中包含对象)
Dec 28 Javascript
浅析JavaScript函数的调用模式
Aug 10 Javascript
微信小程序之滚动视图容器的实现方法
Sep 26 Javascript
网页爬虫之cookie自动获取及过期自动更新的实现方法
Mar 06 Javascript
vue项目中实现的微信分享功能示例
Jan 21 Javascript
一个Java程序猿眼中的前后端分离以及Vue.js入门(推荐)
Apr 19 Javascript
返回上一个url并刷新界面的js代码
Sep 12 Javascript
JavaScript快速调试的两个技巧
Nov 04 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
PHP IPV6正则表达式验证代码
2010/02/16 PHP
PHP调用Linux的命令行执行文件压缩命令
2013/01/27 PHP
php smarty模板引擎的6个小技巧
2014/04/24 PHP
php操作XML、读取数据和写入数据的实现代码
2014/08/15 PHP
CI框架源码解读之URI.php中_fetch_uri_string()函数用法分析
2016/05/18 PHP
PHP生成(支持多模板)二维码海报代码
2018/04/30 PHP
js中的值类型和引用类型小结 文字说明与实例
2010/12/12 Javascript
浅谈Javascript 执行顺序
2013/12/18 Javascript
js仿百度贴吧验证码特效实例代码
2014/01/16 Javascript
JavaScript实现班级随机点名小应用需求的具体分析
2014/05/12 Javascript
5个书写JavaScript代码的坏习惯,看看你中枪了没?
2014/11/06 Javascript
jquery validate表单验证的基本用法入门
2016/01/18 Javascript
KnockoutJS 3.X API 第四章之click绑定
2016/10/10 Javascript
JavaScript数据结构与算法之队列原理与用法实例详解
2017/11/22 Javascript
前端深入理解Typescript泛型概念
2020/03/09 Javascript
安装ElasticSearch搜索工具并配置Python驱动的方法
2015/12/22 Python
Selenium控制浏览器常见操作示例
2018/08/13 Python
Python创建一个空的dataframe,并循环赋值的方法
2018/11/08 Python
Python设计模式之外观模式实例详解
2019/01/17 Python
Python绘制三角函数图(sin\cos\tan)并标注特定范围的例子
2019/12/04 Python
Python基础之字典常见操作经典实例详解
2020/02/26 Python
Python基础教程之输入输出和运算符
2020/07/26 Python
如何将json数据转换为python数据
2020/09/04 Python
详解tf.device()指定tensorflow运行的GPU或CPU设备实现
2021/02/20 Python
英国领先的品牌珠宝和配件供应商:Acotis Jewellery
2018/03/07 全球购物
植村秀美国官网:Shu Uemura美国
2019/03/19 全球购物
Abbacino官网:包、钱包和女士配饰
2019/04/15 全球购物
Antler英国官网:购买安特丽行李箱、拉杆箱
2019/08/25 全球购物
客服主管岗位职责
2013/12/13 职场文书
写给女生的道歉信
2014/01/08 职场文书
先进集体事迹材料
2014/02/17 职场文书
8和9的加减法教学反思
2014/05/01 职场文书
运动会加油口号
2014/06/07 职场文书
教师批评与自我批评
2014/10/15 职场文书
综治目标管理责任书
2015/05/11 职场文书
MySQL 全文索引使用指南
2021/05/25 MySQL