有意思的webpack——tree-shaking

what

首先,咱們來看一張圖。(很形象,借用別處)css

如圖所示,咱們的js文件就至關於這棵樹,tree-shaking就至關對搖動這個操做,目的是讓枯黃的葉子和壞掉的蘋果掉下來。說到這裏,tree-shaking的原理就是,經過搖動咱們的js文件,剔除掉DCE(Dead Code Elimination)。是一種優化性能的方式。前端

why

具體說,每個webpack項目中,都有一個入口,至關於樹的主幹,依賴了不少模塊,至關於樹枝。在咱們的實際使用的過程當中,咱們其實只是使用了模塊裏的某個方法,咱們須要把不使用的樹枝給搖落下來,也就是過濾掉這些無用的代碼。起到性能優化的目的。webpack

用到這一方法的工具備rollUp,webpack,cc。該文章只介紹webpack中tree-shaking的使用。web

原理

tree-shaking的本質是消除無用代碼。無用代碼也就是所謂的dead code elimination。json

function test(){
        const a = 1;
        return a+1;
        // dce 不會被執行的代碼
        const b = 2; 
        return b;
    }
    test();
複製代碼
function test(){
        const a = 1;
        if(false){
           .... 
        }
        const b = 2;
        return b;
    }
    test();
複製代碼

什麼是Dead Code Elimination?

  • 不會被執行的代碼。
  • 代碼執行的結果不會被用到。
  • 代碼只寫不讀。

傳統的編譯型語言中,都是將DCE從AST(抽象語法樹)中刪除掉。那JavaScript是怎麼作到呢?性能優化

JavaScript怎麼剔除DCE的呢?

webapck的DCE是uglify作的,你可能會問,那tree-shaking 是作什麼呢?tree-shaking只是幫助DCE。打個比方,就好像咱們要從一堆水果裏面,拿掉蘋果。首先咱們得把蘋果選出來。tree-shaking就是一個選蘋果的過程。可是拿掉蘋果是選出來以後的操做。bash

實踐

目錄結構: babel

// ./src/index.js

import printMe from "./print.js"; // unused
import { cube } from './math.js';
import menu from './menu.js'; // unused
import './styles.css';
// if(process.env.NODE_ENV !== 'production'){
//   console.log('development mode!')
// }
function component(){
  var element = document.createElement('pre');
  element.innerHTML = [
    'hello webpack',
    '5 cubed is equal to ' + cube(5)
  ].join('\n\n')

  return element;
}
document.body.appendChild(component());
複製代碼

mode='development'

webpack的mode='development'會將 DefinePlugin 中 process.env.NODE_ENV 的值設置爲 development。啓用 NamedChunksPlugin 和 NamedModulesPlugin。app

打包結果:ide

雖然標識出來是不被用到的,可是依然打進去了。

mode='production'

mode='production'會將 process.env.NODE_ENV 的值設爲 production。啓用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin.

打包結果:

在production的時候,這些都被過濾掉了。達到了咱們去除dead code的目的。

使用注意事項

先思考一個問題,爲何tree-shaking是最近幾年流行起來了?而前端模塊化概念已經有不少年曆史了,其實tree-shaking的消除原理是依賴於ES6的模塊特性。

require能夠嗎?

// import _ from "lodash";
import printMe from "./print.js";
import { cube } from './math.js';
// import menu from './menu.js';
const menu = require('./menu.js');
import './styles.css';
.....

複製代碼

production模式下,require的也被打進去了。因此require這種動態引入的是不行的。require須要js執行的時候才知道。import是屬於靜態引入。

借用官網注意事項:

  • 使用ES2015模塊語法(即import和export)。
  • 在項目 package.json 文件中,添加一個 "sideEffects" 屬性。(這個是告訴webpack能夠過濾掉無用的代碼,也能夠根據條件設置對應的文件)
  • 確保沒有 compiler 將 ES2015 模塊語法轉換爲 CommonJS 模塊(這也是流行的 Babel preset 中 @babel/preset-env 的默認行爲 )
  • 經過將 mode 選項設置爲 production,啓用 minification(代碼壓縮) 和 tree shaking。
相關文章
相關標籤/搜索