Tree Shaking概念详解

标签: webpack  Tree Shaking  模块操作  

Tree Shaking 值的就是当我引入一个模块的时候,我不引入这个模块的所有代码,我只引入我需要的代码,这就需要借助 webpack 里面自带的 Tree Shaking 这个功能来帮我们实现。

官方有标准的说法:Tree-shaking的本质是消除无用的js代码。无用代码消除在广泛存在于传统的编程语言编译器中,编译器可以判断出某些代码根本不影响输出,然后消除这些代码,这个称之为DCE(dead code elimination)

在 webpack 项目中,有一个入口文件,相当于一棵树的主干,入口文件有很多依赖的模块,相当于树枝。实际情况中,虽然依赖了某个模块,但其实只使用其中的某些功能。通过 Tree-Shaking,将没有使用的模块摇掉,这样来达到删除无用代码的目的。

在production 模式下不用在webpack.config.js中配置

optimization: {
usedExports: true

}
当在development模式下配置tree shaking时:
webpack.config.js

//HtmlWebpackPlugin
//当我们整个打包过程结束的时候,自动生成一个html文件,
//并把打包生成的自动引入到html这个文件中;
 
var HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const webpack = require('webpack')
module.exports = {
    //打包模式,当为‘production’,打包后的文件会被压缩,
    //当为‘development’时打包后的文件不会被压缩,按照开发环境进行打包
    mode: 'development', //在开发者模式中SourceMap默认已经被配置在项目里了。
    // devtool: 'none', //关闭SourceMap
    //cheap:在生成SourceMap的时候,可以不带列信息,只带行信息,不要包含loader里面的SourceMap的生成,
    //只对业务代码进行SourceMap的生成
    //module:对loader里面的代码也进行一个SourceMap的生成
    //eval:eval是一种执行方式
    devtool: 'cheap-module-eval-source-map', //打开SourceMap
    // devtool: 'cheap-module-source-map', //要线上的代码可以映射
    // 打包的入口文件
    entry: './src/index2.js',
    // entry: {
    //     main: './src/index2.js'
    // },
    devServer: {
        contentBase: './dist', //我们要在哪一个目录下去启动这个服务器
        open: true, //会自动的打开一个浏览器,然后自动访问服务器的地址(localhost:8080)
        hot: true, //指是否支持热更新(hmr)
        hotOnly: true, //即使不支持hmr或者hmr有问题,也不刷新浏览器
        proxy: {
            '/api': {
                //当访问localhost:8080/api的时,它会直接帮你转发到http://localhost:3000
                target: 'http://localhost:3000',
                pathRewrite: { '^/api': '' }
            }
        }
    },
    module: {
        rules: [{
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader'
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        //url-loader会把图片转化成一个base64的字符串,
                        //然后直接放到bundle.js里,而不是单独生成一个图片文件,
                        //好处:不用再额外的请求图片的地址,省了一次http请求;
                        //缺点:如果图片特别大过大,打包生成的js文件就会很大,
                        //那么加载js文件的时间就会很长,所以在一开始很长的时间里,页面上什么都显示不出来;
                        //所以,url-loader最佳的使用方式:加一个limit
                        //如果图片小于limit的值就把图片变为一个base64的字符串放到打包好的js中,
                        //若大于limit的值,就以file-loader的生成一个图片放到dist目录下。
                        limit: 8192, //好处是可以对小图片的http请求数减少,提升网页加载数度
                        name: 'images/[name].[hash].[ext]'
                    }
                }
            },
            {
                test: /\.(css|scss|less)$/,
 
                //"css-loader":会帮我们分析出几个css文件之间的关系,最终把这些css文件合并成一段css;
                //"style-loader":会把‘css-loader’生成的内容挂在到页面的head部分
                //在webpack的配置中,loader是有先后执行顺序的,
                //loader的执行顺序是从下到上,从右到左;
                //“sass-loader”会先对sass代码进行翻译,翻译为css代码后给到css-loader,
                //都处理好了之后再交给‘style-loader’挂在到页面上
                //postcss-loader会自动添加css3的厂商前缀;比如:  transform: translate(100px, 100px)
                use: [
                    'style-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 2,
                            modules: true //使得css模块化,
                        }
                    },
                    'postcss-loader',
                    'sass-loader'
                ]
            },
            {
                // 可以打包字体文件
                test: /\.(eot|ttf|svg)$/,
                use: {
                    loader: 'file-loader'
                }
            }
        ]
    },
 
    // 打包的出口文件
    output: {
        // 打包后的文件名
        // filename: 'bundle.js',
        filename: '[name].js', //name就是entry值的key:'main','sub'
        // 打包后的文件目录为'dist'
        path: path.resolve(__dirname, 'dist'),
        publicPath: '/' //表示的是我所有的打包生成的文件之间的引用前面都加一个根路径
    },
    //plugin可以在webpack运行到某个时刻的时候,帮你做一些事情(类似生命周期函数)
    plugins: [
        // CleanWebpackPlugin可以在每次打包的时候帮我们对dist目录做一个清空
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            //HtmlWebpackPlugin帮我们自动的生成一个dist目录下的html文件
            template: './src/index.html'
        }),
        //HotModuleReplacementPlugin帮我们实现HMR
        new webpack.HotModuleReplacementPlugin()
    ],
    //在开发模式下配置 tree shakeing
    optimization: {
        usedExports: true
    }
}

在 package.json 中配置:

{
    "name": "webpack-demo",
//@babel/polyfill和css文件不使用tree shaking
    "sideEffects": [
        "@babel/polyfill",
        "*.css"
    ],
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "bundle": "webpack",
        "watch": "webpack --watch",
        "start": "webpack-dev-server",
        "server": "node server.js"
    },
    "author": "susie",
    "license": "ISC",
    "devDependencies": {
        "@babel/core": "^7.5.4",
        "@babel/plugin-transform-runtime": "^7.5.0",
        "@babel/preset-env": "^7.5.4",
        "@babel/preset-react": "^7.0.0",
        "autoprefixer": "^9.6.1",
        "babel-loader": "^8.0.6",
        "clean-webpack-plugin": "^3.0.0",
        "css-loader": "^3.0.0",
        "file-loader": "^4.0.0",
        "html-webpack-plugin": "^3.2.0",
        "node-sass": "^4.12.0",
        "postcss-loader": "^3.0.0",
        "sass-loader": "^7.1.0",
        "style-loader": "^0.23.1",
        "url-loader": "^2.0.1",
        "webpack": "^4.35.3",
        "webpack-cli": "^3.3.5",
        "webpack-dev-server": "^3.7.2"
    },
    "dependencies": {
        "@babel/polyfill": "^7.4.4",
        "@babel/runtime": "^7.5.4",
        "@babel/runtime-corejs2": "^7.5.4",
        "react": "^16.8.6",
        "react-dom": "^16.8.6"
    }
}

如果需要对某个模块不进行Tree Shaking

 "sideEffects": ["@babel/poly-fill"],  //该模块不进行Tree Shaking

为什么某些引入模块不希望进行Tree Shaking呢?

下面引入的style.css模块,如果也使用tree shaking,由于css文件没有导出任何模块,那么就有可能在打包的时候该引入模块就被摇晃掉了,导致bug。

在这里插入图片描述
在package.json中进行配置,即匹配到的任何css文件都不进行Tree Shaking

在这里插入图片描述
不使用Tree Shaking打包时,可以看到打包文件中exports provided: add, mins两种方法

在这里插入图片描述

版权声明:本文为weixin_45820444原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_45820444/article/details/108845845

智能推荐

Flutter 性能优化:tree shaking 和延迟加载

作者: 凹凸曼 - Bruce 本文是 Flutter 性能优化系列文章之一,记录了 Flutter 团队优化 Flutter Gallery(https://gallery.flutter.dev/#/) 的实践。本文主要介绍了 tree shaking 和延迟加载在性能优化中的使用。原文链接:https://medium.com/flutter/optimizing-performance-i...

webpack之babel-loader使Tree-shaking失效

webpack之babel-loader使Tree-shaking失效 前言 一、babel-loader导致Tree-shaking失效的原因 二、配置babel-loader后尝试打包 前言 由于早期webpack发展非常快,变化也比较多,所以当我们去找资料时,我们得到的结果并不一定适用于我们当前使用的版本,对于Tree-shaking也是如此。 很多资料都表示,如果我们使用了babel-lo...

2020年7月程序员工资统计,平均14357元,又跌了,扎心

点击上方 好好学java ,选择 星标 公众号 来源:csdn 连接:https://blog.csdn.net/juwikuang/article/details/107072931?utm_source=app 平均工资 2020年7月全国招收程序员288685人。2020年7月全国程序员平均工资14357元。上个月是14404,又跌了50元。一顿午饭跌...

Merge K Sorted List Leetcode #23 题解[C++]

题目来源 https://leetcode.com/problems/merge-k-sorted-lists/description/ 题目描述 Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. Example: Input: [ 1->4-&...

ubuntu14.04安装SSH服务及配置

ubuntu14.04安装SSH服务及配置 1、安装SSH服务 2、安装完服务后,查看ssh服务是否启动 如果有sshd服务,说明已启动,如图: 如果没有sshd服务,说明未启动,执行以下命令启动: 3、配置ssh服务 4、重启ssh 5、验证ssh登录 打开FlashFXP连接ubuntu,输入ifconfig可以查本地的IP,如图,已连上:...

猜你喜欢

【了解6大原则,23 种设计模式(一)】

前言 了解设计模式的朋友们,想必都听说过“六大设计原则”吧。其实最经典的 23 种设计模式中或多或少地都在使用这些设计原则,也就是说,设计模式是站在设计原则的基础之上的,所以我通过查找一些资料,然后也访问了一些分享技术的软件查了这些知识点,希望对大家有帮助。所以在学习设计模式之前,很有必要对这些设计原则先做一下了解 一,下面给大家详细的介绍一下这六个设计原则: (1)单一职...

自定义View学习笔记05—Canvas下操作画布

为什么要有画布操作? 疑问======>>>以默认的坐标系圆点为起点,画一条与X轴呈45°的射线,你会怎么操作? 以常规的数学思路来看,先使用三角函数计算出射线上任一点的坐标,然后调用drawLine即可。 有没有更加简单的方法?这个问题留在本笔记最后来解答。 现在进入操作画布的主题: 1、位移translate(float dx, float dy): 注意:这里的位移...

投影纹理

教程 投影纹理 1、投影纹理 将相机矩阵和模型矩阵相乘,最后得到纹理采样坐标: 顶点着色器: 片元着色器: 2、如何确定背面 片元着色器: <全文结束>...

C++ Primer(第五版) 第二章 变量和基本类型

目录 基本内置类型 1. 算术类型 2. 类型转换 3.字面值常量 变量 1. 变量定义 2. 变量声明与定义的关系 3. 标识符 4. 作用域 复合类型 1. 引用 2. 指针 3. 理解复合类型的声明 const限定词 1. const的引用 2. const和指针 3. 顶层const 4. constexpr和表达式 处理类型 1. 类型别名 2.auto类型说明符 3.decltype类...

CTF打卡第一天-BUU-不一样的flag

题目: 把题目提供的二进制文件下载下来,使用pe查壳,发现没有加壳,是一个32位文件: 使用ida打开,先搜索一下字符串,找到一串奇怪的字符串,不知道有什么用,先留着: F5反编译一下main函数: 可以看出有4个选择:上下左右,再加上那串字符串 很像以前做过的迷宫,试一下: 很明显 把1当做墙,把0看做路,解法就是从*到#,根据逻辑1234分别对应上下左右,因此得到222441144222 根据...