Webpack —— tree-starking 解析

Tree shaking 的概念、作用和原理 ① 使用 ES6(ES2015)模块语法中的 import 和 export 才可以触发这个机制;这是因为 tree shaking 只能在静态 modules 下工作。ECMAScript 6 模块加载是静态的,因此整个依赖树可以被静态地推导出解析语法树。所以在ES6中使用 tree shaking 是非常容易的。② 在项目的 package.json 文件中,添加 "sideEffects" 属性;③ 使用 mode 为 "production" 的配置项以启用更多优化项。 阅读详情

在这里插入图片描述


阅读原文


tree-sharking 简介

tree-sharking 是 Webpack 2 后续版本的优化功能,顾名思义,就是将多余的代码给 “摇晃” 掉,在开发中我们经常使用一些第三方库,而这些第三方库只使用了这个库的一部门功能或代码,未使用的代码也要被打包进来,这样出口文件会非常大,tree-sharking 帮我们解决了这个问题,它可以将各个模块中没有使用的方法过滤掉,只对有效代码进行打包。


AST 语法树分析

假设我们现在使用了 ElementUI 库的两个组件,通常会使用解构赋值来引入。

// 优化前
import { Button, Alert } from "element-ui";

这样引用资源, Webpack 在打包的时候会找到 element-ui 并把里面所有的代码全部打包到出口文件,我们只使用了两个组件,全部打包不是我们所希望的,tree-sharking 是通过在 Webpack 中配置 babel-plugin-import 插件来实现的,它可以将解构的代码转换成下面的形式。

// 优化后
import Button from "element-ui/lib/button";
import Alert from "element-ui/lib/Alert";

转化后会去 node_modules 中的 element-ui 模块找到 Button 和 Alert 两个组件对应的文件,并打包到出口文件中。

通过上面的转换可以看出,其实 tree-sharking 的实现原理是通过改变 AST 语法树的结构来实现的,如果不了解抽象语法树可以参考 AST 抽象语法树,我们可以通过在线转换网站 http://esprima.org/demo/parse.html 将 JS 代码装换成 AST 语法树。

优化前的 AST 语法树:

{
    "type": "Program",
    "body": [
        {
            "type": "ImportDeclaration",
            "specifiers": [
                {
                    "type": "ImportSpecifier",
                    "local": {
                        "type": "Identifier",
                        "name": "Button"
                    },
                    "imported": {
                        "type": "Identifier",
                        "name": "Button"
                    }
                },
                {
                    "type": "ImportSpecifier",
                    "local": {
                        "type": "Identifier",
                        "name": "Alert"
                    },
                    "imported": {
                        "type": "Identifier",
                        "name": "Alert"
                    }
                }
            ],
            "source": {
                "type": "Literal",
                "value": "element-ui",
                "raw": "\"element-ui\""
            }
        }
    ],
    "sourceType": "module"
}

优化后的 AST 语法树:

{
    "type": "Program",
    "body": [
        {
            "type": "ImportDeclaration",
            "specifiers": [
                {
                    "type": "ImportDefaultSpecifier",
                    "local": {
                        "type": "Identifier",
                        "name": "Button"
                    }
                }
            ],
            "source": {
                "type": "Literal",
                "value": "element-ui/lib/button",
                "raw": "\"element-ui/lib/button\""
            }
        },
        {
            "type": "ImportDeclaration",
            "specifiers": [
                {
                    "type": "ImportDefaultSpecifier",
                    "local": {
                        "type": "Identifier",
                        "name": "Alert"
                    }
                }
            ],
            "source": {
                "type": "Literal",
                "value": "element-ui/lib/Alert",
                "raw": "\"element-ui/lib/Alert\""
            }
        }
    ],
    "sourceType": "module"
}

从上面的语法树对比,可以看出在优化前 body 里面只有一个对象,使用的组件信息存在 specifiers 里,source 指向了 element-ui,而在优化后,将两个组件分别拆成了两个对象存在 body 中,每个对象的的 specifiers 只存储一个组件,并在 source 里面指向了当前组件对应的路径。


模拟 tree-starking

既然我们已经清楚要修改语法树的位置,下面就使用 AST 来模拟 tree-sharking 功能,对语法树的操作是依赖于 babel-core 和 babel-types 两个核心模块的,下面先安装依赖。

npm install babel-core babel-types

// 文件:babel-plugin-my-import.js
const babel = require("babel-core");
const types = require("babel-types");

let code = `import { Button, Alert } from "element-ui"`;

let importPlugin = {
    visitor: {
        ImportDeclaration(path) {
            let node = path.node;
            let source = node.source.value;
            let specifiers = node.specifiers;

            // 判断是否是默认导出,其中一个不是默认导出,则都不是默认导出
            if (!types.isImportDefaultSpecifier(specifiers[0])) {
                // 如果不是默认导出,则需要转换
                specifiers = specifiers.map(specifier => {
                    // 数组内容:当前默认导出的标识、从哪里导入
                    return types.importDeclaration(
                        [types.importDefaultSpecifier(specifier.local)],
                        types.stringLiteral(`${source}/lib/${specifier.local.name.toLowerCase()}`)
                    );
                });

                // 替换树结构
                path.replaceWithMultiple(specifiers);
            }
        }
    }
};

let result = babel.transform(code, {
    plugins: [importPlugin]
});

console.log(result.code);

// import Button from "element-ui/lib/button";
// import Alert from "element-ui/lib/alert";

通过上面的代码可以发现我们使用 babel-core 和 babel-types 两个模块的核心方法对语法书进行了遍历、修改和替换,更详细的 API 可以查看 https://github.com/babel/babel/tree/6.x/packages/babel-types。


结合 Webpack 使用插件

前面只是验证了 tree-sharking 中 JS 语法的转换过程,接下来将上面的代码转换成插件配合 Webpack 使用,来彻底感受 tree-sharking 的工作过程。

// 文件:~node_modules/babel-plugin-my-import.js
const babel = require("babel-core");
const types = require("babel-types");

let importPlugin = {
    visitor: {
        ImportDeclaration(path) {
            let node = path.node;
            let source = node.source.value;
            let specifiers = node.specifiers;

            // 判断是否是默认导出,其中一个不是默认导出,则都不是默认导出
            if (!types.isImportDefaultSpecifier(specifiers[0])) {
                // 如果不是默认导出,则需要转换
                specifiers = specifiers.map(specifier => {
                    // 数组内容:当前默认导出的标识、从哪里导入
                    return types.importDeclaration(
                        [types.importDefaultSpecifier(specifier.local)],
                        types.stringLiteral(`${source}/lib/${specifier.local.name.toLowerCase()}`)
                    );
                });

                // 替换树解构
                path.replaceWithMultiple(specifiers);
            }
        }
    }
};

module.exports = importPlugin;

上面删掉了多余的测试代码,将模块中的 importPlugin 插件导出,并把 babel-plugin-my-import.js 移入了 node_modules 当中。

接下来安装需要的依赖:

npm install webpack webpack-cli babel-loader babel-presets-env

npm install vue element-ui --save

安装完依赖,写一个要编译的文件,使用 Webpack 进行打包,查看使用插件前和使用插件后出口文件的大小。

// 文件:import.js
import Vue from "vue";
import { Button, Alert } from "element-ui";

下面来写一个简单的 Webpack 配置文件。

// 文件:webpcak.config.js
module.exports = {
    mode: "development",
    entry: "import.js",
    output: {
        filename: "bundle.js",
        path: __dirname
    },
    module: {
        rules: [{
            test: /\.js$/,
            use: {
                loader: "babel-loader",
                options: {
                    presets: [
                        "env",
                    ],
                    plugins: [
                        // 插件:不使用插件打包注释掉该行即可
                        ["my-import", { libararyName: "element-ui" }]
                    ]
                }
            },
            exclude: /node_modules/
        }]
    }
};

为了防止 babel 相关的依赖升级 7.0 后出现一些问题导致 Webpack 无法启动,再此贴出 package.json 文件,按照对应版本下载依赖保证上面 Webpack 配置生效。

文件:package.json

{
  "name": "ast-lesson",
  "version": "1.0.0",
  "description": "tree-starking",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "babel-preset-env": "^1.7.0",
    "babel-types": "^6.26.0",
    "escodegen": "^1.10.0",
    "esprima": "^4.0.0",
    "estraverse": "^4.2.0",
    "webpack": "^4.16.0",
    "webpack-cli": "^3.0.8"
  },
  "devDependencies": {
    "vue": "^2.5.17",
    "element-ui": "^2.4.6"
  }
}

对比使用插件前后的出口文件

接下来分别在使用插件和不使用插件时执行打包命令,查看出口文件 bondle.js 的大小。

npx webpack

使用 babel-plugin-my-import 前:

在这里插入图片描述

使用 babel-plugin-my-import 后:

在这里插入图片描述

通过对比,可以看到使用 tree-sharking 即我们自己实现的 babel-plugin-my-import 插件后,打包的出口文件大大减小,其原因是将引入第三方库没有使用的代码全都过滤掉了,只打包了有效代码。


总结

上面对 Webpack 的 tree-sharking 进行了分析,并模拟 babel-plugin-import 简易的实现了一版 tree-sharking 的优化插件,这个过程中相信大家已经了解了 tree-sharking 的原理以及实现类似插件的思路,并已经具备了开发类似插件的基本条件,最后还有一点需要补充,tree-sharking 优化的方式是根据 ES6 语法 import “静态” 引入的特性实现的,如果要说 tree-sharking 很强大,还不如说 ES6 模块化规范 “静态” 引入的特性强大,正由于是基于 “静态” 引入,所以目前 tree-sharking 只支持遍历一层 import 关键字。


tree- shaking的用途,原理 Tree Shaking 是现代 JavaScript 打包工具中一项关键的优化技术,它能够显著减少最终打包文件的体积。下面我将从多个维度详细解析其用途和工作原理。 阅读详情

相关推荐

“风色幻想XX:交错轨迹游戏卡顿:从解决d3dx9_xx.dll缺失开始——风色幻想XX优化指南

《风色幻想XX:交错轨迹》作为一款深受玩家喜爱的角色扮演游戏,以其丰富的剧情、独特的角色设定和精美的画面赢得了广泛的赞誉。然而,在游戏过程中,部分玩家可能会遇到游戏卡顿的问题,这不仅影响了游戏体验,还可能让玩家错失精彩的剧情和战斗瞬间。在众多导致游戏卡顿的因素中,d3dx9_xx.dll文件的缺失往往是一个不容忽视的原因。

czl922的博客 1257

Tree Shaking概念详解

Tree Shaking 值的就是当我引入一个模块的时候,我不引入这个模块的所有代码,我只引入我需要的代码,这就需要借助 webpack 里面自带的 Tree Shaking 这个功能来帮我们实现。 官方有标准的说法:Tree-shaking的本质是消除无用的js代码。无用代码消除在广泛存在于传统的编程语言编译器中,编译器可以判断出某些代码根本不影响输出,然后消除这些代码,这个称之为DCE(dead code elimination) 在 webpack 项目中,有一个入口文件,相当于一棵树的主干,入口文件

weixin_45820444的博客 2万+

NVIDIA GPU任务调度全景:从Block分配到Warp发射

GPU并行计算的核心是任务调度,而CUDA kernel在GPU上的执行并非简单的一次性操作,而是经过从CPU命令队列到硬件前端,再到GigaThread引擎和Warp Scheduler的多层协同。理解这一过程,是性能优化的基础。Warp作为硬件调度的基本单位,其状态切换与延迟隐藏能力直接决定计算单元的利用率;而Occupancy作为衡量SM上活跃Warp池大小的指标,也并非越高越好,需要结合访存模式与资源占用综合判断。对于多任务并发场景,Stream优先级、计算抢占、MIG硬件隔离与MPS软件共享等机制

weixin_32612263的博客 270

前端进阶(二十一)Tree-Sharking最佳实践

什么是Tree-Sharking? 直接帖上一篇百度外卖的文章:Tree-Shaking性能优化实践 - 原理篇 如果不想看长篇文章,我简单讲一下:简单说tree-sharking就是在前端在打包时,去掉不需要的代码。 Tree-shaking 较早由 Rich_Harris 的 rollup 实现,后来,webpack2 也增加了tree-shaking 的功能。其实在更早,googl...

前端产品工程师 4322

计算机组成原理(第三版)唐朔飞-第七章指令系统-课后习题

机器字长是指CPU一次能处理数据的位数通常与CPU的寄存器位数有关。指令字长是指机器指令中二进制代码的总位数。存储字长是指存储单元中存放二进制代码的总位数。三者可以相等也可以不等视不同机器而定。答:OP(4位)A1(6位)A_1(6位)A1​(6位)A2(6位)A_2(6位)A2​(6位)设二地址指令格式为该指令系统的基本格式,4位操作码共有16种编码,其中13种用来定义二地址指令,还剩3种可用作扩展标志。一地址指令条数=3∗26=192。

weixin_45735391的博客 7万+

【读代码】从claude skills到superpowers项目

最近claude skills成了大热门,今天一起看下GitHub 上的开源技能框架,他将“工作流”封装为“技能” (Skills)。本文尝试剖析该项目的技能粒度定义、多技能关联架构、应用逻辑等。与传统的 Function Calling 不同,Superpowers 中的 Skill 定义粒度并非“原子操作”,而是**“认知模式” (Cognitive Mode) 或“工作阶段”**。

kakaZhui的博客 1921

tree shaking(摇树优化)

前端性能优化之tree-shaking

m0_50074446的博客 1万+

51单片机嵌入式开发:14、STC89C52RC 之HX1838红外解码NEC+数码管+串口打印+LED显示

对于C51单片机的设计思路,你可以使用类似的步骤来实现红外解码、数码管显示和LED显示的功能。下面是一个简单的设计思路:(1) 连接HX1838红外解码器、数码管和LED到C51单片机。将HX1838的信号引脚连接到C51单片机的外部中断引脚(例如INT0),数码管的CLK引脚连接到C51单片机的某个IO口引脚,数码管的DIO引脚连接到C51单片机的另一个IO口引脚,LED连接到C51单片机的某个IO口引脚。(2) 在C51的程序中,定义并初始化所需的IO口和外部中断。

sinat_30943509的博客 2977

关于webpack种tree-sharking优化策略与sideEffect

关于webpack种tree-sharking优化策略与sideEffect

qq_73917015的博客 815

B07:AI 时代怎么考核团队?我把 KPI 改了 5 版才找到答案

最后说一句掏心窝的话。绩效考核不是"管人"的工具,是"引导团队行为"的工具。你定什么指标,团队就会做什么行为。你定"AI 占比",团队就凑占比你定"效率提升",团队就挑软柿子你定"代码行数",团队就刷行数你定"工具使用率",团队就刷使用只有定"业务价值 + 工程质量 + 能力成长"三个维度的指标,团队才会真正关注长期价值。这套 KPI,我在我带的团队里跑了 6 个月,没有任何一个指标被"刷"出来。考核的是结果,不是过程。永远考核"创造了多少价值",永远不考核"用了多少 AI"。

刘一说的IT专栏 502

【深度学习新浪潮】深度学习特别是大模型在图像配准方面的研发进展

深度学习,尤其是大模型的出现,彻底改变了图像配准的技术范式——从“手工设计特征+几何约束”走向“数据驱动+通用特征学习”。当前,大模型配准已在医学影像、遥感、工业检测等领域实现商业化落地,解决了传统方法难以应对的跨模态、少样本、复杂形变等问题。但大模型配准仍面临推理效率、可解释性、数据隐私等挑战,未来的研发核心将是“精度与效率的平衡”“泛化能力的提升”“场景化适配的简化”。对于开发者而言,从简化版大模型配准代码入手,逐步理解预训练+微调的核心逻辑,是衔接前沿技术的有效路径。

专注:太空算力、AI infra、异构调度、大模型成本工程 425

tree shaking的原理是什么?

别名叫摇晃树,最早是由Rollup实现,是一种采用删除不需要的额外代码的方式优化代码体积的技术 tree-shaking会在打包过程中 静态分析 模块之间的导入导出,确定哪些模块导出值没有被使用,并将其删除,从而实现了打包产物的优化。在之前CommonJs、AMD、CMD的模块化方案中,这种导入导出是动态的,难以预测的,因此在打包阶段,是无法分析哪些模块被使用,例如: 而ES 静态module方案下,模块之间的依赖关系是高度确定的静态的,与运行状态无关,可以进行可靠的静态分析,因此整个依赖树可以被静态地推导

cxz 3913

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

webpack5学习进阶:多页面应用、Tree Shaking、PWA、Shimming

在线服务在服务停止后,浏览器是无法正常访问到网页的,同时在线服务会把启动编译的代码放在内存里,也就是说当我们修改代码之后重新启动服务,这个时候并不会把修改同步打包到dist文件夹下面,因为它放在内存里面了;在实际的项目开发中,一个完整的系统不会将所有的功能都放在一个网页里,这是因为会导致网页的性能不佳;打包过后,app1.js和app2.js都会被打包进dist/main.js文件中,按照数组里面的前后顺序,webpack会将前面的文件先打包,并且放在main.js的上面;......

weixin_43299180的博客 1116

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【告别普通打包】webpack打包结果优化特性:Tree Sharking 和 sideEffects

文章目录1. Tree Shaking(摇树)1.1 摇树讲解1.2 开启 Tree Shaking1.3 合并模块(扩展)1.4 探讨 babel-loader 的问题2. sideEffects2.1 sideEffects讲解2.2 sideEffects 作用2.3 sideEffects 注意 今天我将和你分享 Webpack 的两个高级特性,分别是 Tree Shaking 和 sideEffects。 它们都属于 Webpack 打包结果优化的必备特性,而且现在应用的也十分广泛。 1. T

鸭绒的博客 1396

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Tree-Shaking性能优化实践 - 原理篇

一. 什么是Tree-shaking先来看一下Tree-shaking原始的本意上图形象的解释了Tree-shaking 的本意,本文所说的前端中的tree-shaking可以理解为通过工具"摇"我们的JS文件,将其中用不到的代码"摇"掉,是一个性能优化的范畴。具体来说,在 webpack 项目中,有一个入口文件,相当于一棵树的主干,入口文件有很多依赖的模块,相当于树枝。实际情况中,虽然依赖了某个...

weixin_34273481的博客 1237

tree+shaking(摇树优化)

tree shaking就是类似一棵树有长熟的苹果,将已将长熟的苹果摇掉减轻树的负担,这就实现了这个机制。在ES6中的import和export才可以触发这个机制项目中对 tree-shaking的配置,production环境下默认是开启了tree-shaking机制的。tree-shaking对项目中的影响。

Joyce的博客 3105

webpack中tree-shaking的使用和原理

设置,打包后,会有有一段注释,告知Terser在优化时,可以删除掉这段代码。

我的博客简介 1370

tree-shaking的概念及其工作原理

tree-sharking

qq_37299525的博客 604

从过去到现在,聊聊 Tree-shaking 到底是什么?

前言 Tree-shaking 这一术语在前端社区内,起初是 Rich Harris 在 Rollup 中提出。简单概括起来,Tree-shaking 可以使得项目最终构建(Bundle)结果中只包含你实际需要的代码。 而且,说到 Tree-shaking,不难免提及 Dead Code Elimination,相信很多同学在一些关于 Tree-shaking 的文章中都会看到诸如这样的描述:Tree-shaking 是一项 Dead Code Elimination(以下统称 DCE)技术。 那么,既然

五柳 557

请简要介绍Vue3的Tree Shaking是什么?它的作用是什么?

通过Tree Shaking,我们可以在打包时自动删除未使用的模块,只保留项目中真正需要的代码,从而减少打包后的文件大小,提高应用的加载速度。总结来说,Vue3的Tree Shaking通过静态分析去除未使用的代码,帮助减少包的体积,提高应用性能,是优化Vue应用的重要手段之一。在打包时,由于只引用了util.js中的add函数,Tree Shaking会通过静态分析的方式检测到subtract和multiply函数没有被引用,因此会将这两个函数的代码从最终的输出文件中移除,减少包的体积。

有我更精彩的博客 719

webpack之Tree shaking(摇树优化)

概念: treeshaking就是只把用到的方法打入bundle,没有使用到的方法会在uglify阶段被擦除掉,这样得以优化项目体积。 使用: webpack默认支持,在.babelrc里面设置moudules:false即可(如果你要把es6转成es5,同时又要开启treeshaking,需要在.babelrc里面设置modules:false,不然babel默认会把es6转成com...

liuhua_2323的博客 714

Webpack--入门只看这一篇就够了(图文+代码)

代码分离(code splitting)和懒加载(lazy loading)是Webpack中用于优化资源加载的两种技术。代码分离是将打包生成的代码文件拆分成多个较小的文件,而不是将所有代码打包到一个文件中。这样做的好处是可以提高初始加载速度,并减小每个页面的加载所需的数据量。通过代码分离,只需在需要时加载特定模块,提高了页面的响应速度和用户体验。懒加载是指在需要时才加载某个模块,而不是在初始加载时就将所有代码一次性加载完毕。通过懒加载,可以将页面分成多个模块,并根据需要动态地加载模块。

小庄zzz的博客 3万+

Webpack中的tree-shaking

文章目录Webpack中的tree-shaking简单实践副作用sideEffectssideEffects配置项false数组结论 Webpack中的tree-shaking tree-shaking就是把js文件中无用的模块或者代码删掉。而这通常需要借助一些工具。在webpack中tree-shaking就是在打包时移除掉javascript上下文中无用的代码,,从而优化打包的结果。 在webpack5中已经自带tree-shaking功能,在打包模式为production时,默认开启 tree-sha

laplacepoisson的博客 6197

webpack详解

一、什么是webpack 1、官方解释:从本质上来讲,webpack是一个现在的javaScript应用的静态模块化打包工具。(从两点概括这句话即模块和打包) 下面来说一下模块和打包的概念! 2、前端模块化: 前端模块化的一些方案:AMD、CMD、CommonJS、ES6(浏览器不能识别它们,但是webpack可以做它们的底层支撑,方可进行模块化开发) ES6之前,要想进行模块化开发,就必须借助于其他的工具,让我们可以进行模块化开发 并且在通过模块化开发完成了项目后,还需要处理模块化间的各种依赖,并且将

qq_43743402的博客 6万+
上一篇: AST 抽象语法树
下一篇: NodeJS 多进程和集群
Panda Shen
博客等级 码龄10年 18粉丝 50原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值