zoukankan      html  css  js  c++  java
  • webpack之tree shaking

    什么是tree-shaking?

    前端中的tree-shaking可以理解为通过工具"摇"我们的js文件,将其中用不到的代码"摇"掉,是一个性能优化的范畴。具体来说,在webpack项目中,
    有一个入口文件,相当于一棵树的主干,入口文件有很多依赖的模块,相当于树枝。实际情况中,虽然依赖啦某个模块,但其实只使用其中的某些功能。通过
    tree-shaking,将没有使用的模块摇掉,这样来达到删除无用代码的目的。

    tree-shaking原理

    tree-shaking原理,简单来说

    • tree shaking的本质是消除无用的Javascript代码
    • 因为ES6模块的出现,ES6模块依赖关系是确定的,和运行时的状态无关,可以进行可靠的静态分析

    怎么使用tree-shaking?

    • 在webpackDemo/demo下新建一个文件tree-shaking,文件目录如下

    • index.js内容如下

    import {add} from "./math.js"
    console.log(mathFn)
    function component(){
    	var element = document.createElement("pre");
    	element.innerHTML = [
    		"hello webpack",
    		"5 cubed is equal to " + add(5,6)
    	].join("
    
    ");
    	return element;
    }
    document.body.appendChild(component())
    
    
    • math.js内容如下
    export function add(a,b){
    	console.log("add");
    	return a+b;
    }
    
    export function minus(a,b){
    	console.log("minus")
    	return a-b
    }
    
    export function multiply(a,b){
    	console.log("mutiply");
    	return a*b;
    }
    
    export function divide(a,b){
    	console.log("divide");
    	return a/b;
    }
    
    
    
    • tree-shaking.js内容如下
    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const {CleanWebpackPlugin} = require("clean-webpack-plugin");
    const webpack = require("webpack");
    module.exports = {
    	mode:"development",
    	entry:path.resolve(__dirname,"src/index.js"),
    	module:{
    		rules:[
    			{
    				test:/.m?js$/,
    				exclude:/(node_modules|bower_components)/,
    				use:{
    					loader:"babel-loader",
    					options:{
    						presets:["@babel/preset-env"],
    						plugins:[
    							"@babel/plugin-transform-runtime"
    						]
    					}
    				}
    			}
    		]
    	},
    	output:{
    		filename:"bundle.js",
    		path:path.resolve(__dirname,"dist")
    	},
    	plugins:[
    		new CleanWebpackPlugin(),
    		new HtmlWebpackPlugin(),
    //		new webpack.NamedModulesPlugin(),
    //		new webpack.HotModuleReplacementPlugin()
    	],
    	devtool:"inline-source-map",
    //	devServer:{
    //		contentBase:"./dist",
    //		hot:true,
    //		inline:true
    //	}
    }
    
    
    • package.json 内容如下
    {
      "name": "webpackDevServer",
      "sideEffects": false,
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo "Error: no test specified" && exit 1",
        "dev": "webpack-dev-server --config demo/webpack-dev-server/webpack-dev-server.js",
        "server": "node demo/webpack-dev-middleware/server.js",
        "hmr": "webpack-dev-server  --config demo/HMR/webpack.hmr.js",
        "treeShaking:dev": "webpack-dev-server --config demo/tree-shaking/tree-shaking.js",
        "treeShaking:build": "webpack  --config demo/tree-shaking/tree-shaking.js"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "@babel/core": "7.6.4",
        "@babel/plugin-transform-runtime": "^7.6.2",
        "@babel/preset-env": "^7.6.3",
        "babel-loader": "8.0.6",
        "clean-webpack-plugin": "3.0.0",
        "css-loader": "3.2.0",
        "express": "4.17.1",
        "html-webpack-plugin": "3.2.0",
        "style-loader": "1.0.0",
        "webpack": "4.41.2",
        "webpack-cli": "3.3.9",
        "webpack-dev-middleware": "3.7.2",
        "webpack-dev-server": "3.8.2"
      }
    }
    
    
    • 执行 npm run treeShaking:build

    执行结果如下

    执行后我们可以看到bundle.js文件,可以发现math.js中所有的代码都被打包了,而我们只用了文件中的add函数,我们没用到的函数不想打包到文件,这时我们可以用到tree-shaking

    • 启用webpack
      当前项目中使用的是webpack4,讲mode设置为production即可开启tree shaking

    关于side effects(副作用)

    副作用是指除了函数返回值以外,任何在函数调用之外观察到的应用程序状态改变。副作用包括:

    • 改变了任何外部变量或对象属性(例如,全局变量,或者一个在父级函数作用域链上的变量)
    • 写日志
    • 在屏幕输出
    • 写文件
    • 发网络请求
    • 触发任何外部进程
    • 调用另一个有副作用的函数

    tree shaking不能自动的识别那些代码属于side effects,因此手动指定这些代码非常重要,如果不指定可能会出现一些意想不到的问题

    在webpack中,是通过packge.json的sideEffects属性来实现的
    {
    "name":"tree-shaking",
    "sideEffects":false
    }

    如果所有代码都包含副作用,我们可以简单地将属性标记为false,并告知webpack,他可以安全地删除未用到的export导出

    如果你的代码确实有一些副作用,那么可以改为提供一个数组

    {
    "name": "tree-shaking",
    "sideEffects": [
    "./src/common/polyfill.js"
    ]
    }

    总结

    • tree shaking 不支持动态导入(如CommonJS的require()语法),只支持纯静态的导入(ES6的import/export)
    • webpack中可以在项目package.json中添加一个"sideEffects"属性,手动指定有副作用的脚本

    将mode修改,在package.json里设置sideEffects:false结果如下

    我们可以看出使用了tree shaking后,代码体积变小,并且我们引用的math.js函数add被转换,其他未引用的代码并没有出现

  • 相关阅读:
    第一条博客
    (原创)c#学习笔记08--面向对象编程简介01--面向对象编程的含义01--对象的含义01--属性和字段
    (原创)c#学习笔记06--函数06--委托
    (原创)c#学习笔记06--函数05--函数的重载
    (原创)c#学习笔记06--函数04--结构函数
    (原创)c#学习笔记06--函数03--main函数
    (原创)c#学习笔记06--函数02--变量的作用域02--参数和返回值与全局数据
    (原创)c#学习笔记06--函数02--变量的作用域01--其他结构中变量的作用域
    (原创)c#学习笔记06--函数01--定义和使用函数02--参数
    (原创)c#学习笔记06--函数01--定义和使用函数01--返回值
  • 原文地址:https://www.cnblogs.com/dehenliu/p/12523231.html
Copyright © 2011-2022 走看看