网络包的树形分析
树木切割介绍
树共享是Webpack 2后续版本的优化功能。顾名思义,就是“抖”掉多余的代码。在开发中,我们经常会用到一些第三方库,但是这些第三方库只使用了这个库的一部分功能或者代码,没有用到的代码也要打包,这样导出的文件会很大。树共享帮助我们解决了这个问题,它可以过滤掉每个模块中未使用的方法。
AST语法树分析
假设我们现在使用ElementUI库的两个组件,通常是通过解构赋值引入的。
优化前
从“元素-用户界面”导入{按钮,警报};有了这些参考资料,Webpack将找到元素ui,并在打包时将其中的所有代码打包到导出文件中。我们只用两个组件,所有的包装都不是我们想要的。树分片是通过在Webpack中配置babel-plugin-import插件来实现的,它可以将解构后的代码转换为如下形式。
优化后
从“元素-ui/lib/button”导入Button;从“元素-用户界面/库/警报”导入警报;转换后,您将进入node_modules中的element-ui模块,找到与Button和Alert组件对应的文件,并将其打包成导出文件。
从上面的转换可以看出,树分片的实现原理是通过改变AST语法树的结构来实现的。我们可以通过在线转换网站http://esprima.org/demo/parse.html.用AST语法树替换JS代码
优化前的AST语法树
{ 'type': 'Program ',' body ' :[{ 'type ' : ' import declaration ','说明符' :[{ ' type ' : ' import说明符',' local ' : { ' type ' : ' Identifier ',' name': 'Button' },' import ' 3: { ' type ' 3: ' Identifier ' },{ ' type '
{ 'type': 'Program ',' body ' :[{ ' type ' : ' ImportDeclaration ','说明符' :[{ ' type ' : 'importdefault说明符',' local ' : { ' type ' : ' Identifier ',' name': 'Button' } } ],' source ' : { ' type ' : ' Literal ',' value ' 3: ' element-UI/Source指向element-ui,经过优化后,两个组件被拆分成两个对象并存储在body中。每个对象的说明符只存储一个组件,并指向源中当前组件对应的路径。
模拟树木饥饿
现在我们知道了要修改的语法树的位置,我们将使用AST来模拟树分片函数。语法树的操作依赖于两个核心模块,babel-core和babel-type,我们将首先安装依赖项。
NPM安装巴别塔核心巴别塔类型文件
const babel=require(' babel-core ');const type=require(' babel-type ');让代码=`从element-ui“`”导入{按钮,警报};让import plugin={ visitor : { import declaration(路径){让node=path.node让source=节点。来源。价值;让说明符=节点。说明符;//判断是否是默认导出,其中一个不是默认导出,则都不是默认导出if(!types.isImportDefaultSpecifier说明符说明符(说明符[0]){//如果不是默认导出,则需要转换说明符=说明符。地图(说明符={ //数组内容:当前默认导出的标识、从哪里导入返回类型。import declaration([类型。导入默认值说明符(说明符。本地)],类型。stringlinear(` $ { source }/lib/$ { 0说明符。本地的。名字。ToLowerCase()} `);});//替换树结构path.replaceWithMultiple(说明符);} } }};让结果=babel.transform(代码,{ plugins :[import plugin]});控制台。日志(结果。代码);//从"元素-用户界面/库/按钮"导入按钮;//从"元素-ui/lib/alert "导入警惕;通过上面的代码可以发现我们使用巴别塔核心和巴别塔类型两个模块的核心方法对语法书进行了遍历、修改和替换,更详细的应用程序接口可以查看https://github.com/babel/babel/tree/6.x/packages/babel-types。
结合Webpack使用插件
前面只是验证了砍树中射流研究…语法的转换过程,接下来将上面的代码转换成插件配合Webpack使用,来彻底感受砍树的工作过程。
文件:~ node _ modules/babel-plugin-my-import。射流研究…
const babel=require(' babel-core ');const type=require(' babel-type ');让import plugin={ visitor : { import declaration(路径){让node=path.node让source=节点。来源。价值;让说明符=节点。说明符;//判断是否是默认导出,其中一个不是默认导出,则都不是默认导出if(!types.isImportDefaultSpecifier说明符说明符(说明符[0]){//如果不是默认导出,则需要转换说明符=说明符。地图(说明符={ //数组内容:当前默认导出的标识、从哪里导入返回类型。import declaration([类型。导入默认值说明符(说明符。本地)],类型。stringlinear(` $ { source }/lib/$ { 0说明符。本地的。名字。ToLowerCase()} `);});//替换树解构path.replaceWithMultiple(说明符);} } }};module.exports=importPlugin上面删掉了多余的测试代码,将模块中的导入插件插件导出,并把巴别塔插件my-import.js移入了节点_模块当中。
接下来安装需要的依赖:
新公共管理安装网络包网络包加载器巴别塔预设-envnpm安装某视频剪辑软件元素-ui -保存安装完依赖,写一个要编译的文件,使用Webpack进行打包,查看使用插件前和使用插件后出口文件的大小。
文件:import.js
从“Vue”导入Vue从"元素-用户界面"导入{按钮,警报};下面来写一个简单的Webpack配置文件。
文件:webpcak.config.js
模块。exports={ mode : ' development ',entry: 'import.js ',output : { filename : ' bundle。js ',path: __dirname },模块: { rules 3360 [{ test :/\ .js$/,使用: { loader : ' babel-loader ',options: { presets: [ 'env ',],plugins: [ //插件:不使用插件打包注释掉该行即可['my-import ',{ libararyname : ' element-ui ' }]} },exclude :/node _ modules/}]} };为了防止巴别塔相关的依赖升级7.0 后出现一些问题导致Webpack无法启动,再此贴出package.json文件,按照对应版本下载依赖保证上面Webpack配置生效。
文件:package.json
{ ' name ' : ' ast-lease ',' version': '1.0.0 ',' description ' : ' tree-starking ',' main': 'index.js ',' scripts ' : { ' test ' : ' echo ' error :没有指定测试' exit 1' },' keywords': [],' author ' : ' ',' license ' : ' isc ',' dependencies ' 333: '
然后,在使用插件和不使用插件时执行打包命令,并检查导出文件bondle.js的大小
在为npx webpack使用babel-plugin-my-import之前:
使用巴别塔插件我的导入:
相比之下,我们可以看到,在使用我们自己的babel-plugin-my-import插件tree-sharking后,打包的导出文件大大减少。原因是引入第三方库的所有未使用的代码都会被过滤掉,只打包有效的代码。
摘要
上面分析了Webpack的树共享,通过模拟巴别塔插件导入,简单实现了树共享的优化插件版本。在这个过程中,相信大家都已经明白了树共享的原理和实现类似插件的思路,已经具备了开发类似插件的基本条件。最后需要补充的是,树共享优化方法是根据ES6语法导入“静态”引入的特性实现的。如果说树共享功能强大,不如说ES6模块化规范“静态”引入的特性功能强大。因为是基于“静态”的引入,目前树共享只支持遍历一层导入关键词。
以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。