成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

webpack打包分析與性能優(yōu)化

joy968 / 1366人閱讀

摘要:打包分析與性能優(yōu)化背景在去年年末參與的一個(gè)項(xiàng)目中,項(xiàng)目技術(shù)棧使用,生產(chǎn)環(huán)境全量構(gòu)建將近三分鐘,項(xiàng)目業(yè)務(wù)模塊多達(dá)數(shù)百個(gè),項(xiàng)目依賴數(shù)千個(gè),并且該項(xiàng)目協(xié)同前后端開發(fā)人員較多,提高構(gòu)建效率,成為了改善團(tuán)隊(duì)開發(fā)效率的關(guān)鍵之一。

webpack打包分析與性能優(yōu)化 背景

在去年年末參與的一個(gè)項(xiàng)目中,項(xiàng)目技術(shù)棧使用react+es6+ant-design+webpack+babel,生產(chǎn)環(huán)境全量構(gòu)建將近三分鐘,項(xiàng)目業(yè)務(wù)模塊多達(dá)數(shù)百個(gè),項(xiàng)目依賴數(shù)千個(gè),并且該項(xiàng)目協(xié)同前后端開發(fā)人員較多,提高webpack 構(gòu)建效率,成為了改善團(tuán)隊(duì)開發(fā)效率的關(guān)鍵之一。

下面我將在項(xiàng)目中遇到的問題和技術(shù)方案沉淀出來與大家做個(gè)分享

從項(xiàng)目自身出發(fā)

我們的項(xiàng)目是將js分離,不同頁面加載不同的js。然而分析webpack打包過程并針對(duì)性提出優(yōu)化方案是一個(gè)比較繁瑣的過程,首先我們需要知道webpack 打包的流程,從而找出時(shí)間消耗比較長(zhǎng)的步驟,進(jìn)而逐步進(jìn)行優(yōu)化。

在優(yōu)化前,我們需要找出性能瓶頸在哪,代碼組織是否合理,優(yōu)化相關(guān)配置,從而提升webpack構(gòu)建速度。

1.使用yarn而不是npm

由于項(xiàng)目使用npm安裝包,容易導(dǎo)致在多關(guān)聯(lián)依賴關(guān)系中,很可能某個(gè)庫在指定依賴時(shí)沒有指定版本號(hào),進(jìn)而導(dǎo)致不同設(shè)備上拉到的package版本不一。yarn不管安裝順序如何,相同的依賴關(guān)系將以相同的方式安裝在任何機(jī)器上。當(dāng)關(guān)聯(lián)依賴中包括對(duì)某個(gè)軟件包的重復(fù)引用,在實(shí)際安裝時(shí)將盡量避免重復(fù)的創(chuàng)建。yarn不僅可以緩存它安裝過的包,而且安裝速度快,使用yarn無疑可以很大程度改善工作流和工作效率

2.刪除沒有使用的依賴

很多時(shí)候,我們由于項(xiàng)目人員變動(dòng)比較大,參與項(xiàng)目的人也比較多,在分析項(xiàng)目時(shí),我發(fā)現(xiàn)了一些問題,諸如:有些文件引入進(jìn)來的庫沒有被使用到也沒有及時(shí)刪除,例如:

import a from "abc";

在業(yè)務(wù)中并沒有使用到a 模塊,但webpack 會(huì)針對(duì)該import 進(jìn)行打包一遍,這無疑造成了性能的浪費(fèi)。

webpack打包分析

1.打包過程分析

我們知道,webpack 在打包過程中會(huì)針對(duì)不同的資源類型使用不同的loader處理,然后將所有靜態(tài)資源整合到一個(gè)bundle里,以實(shí)現(xiàn)所有靜態(tài)資源的加載。webpack最初的主要目的是在瀏覽器端復(fù)用符合CommonJS規(guī)范的代碼模塊,而CommonJS模塊每次修改都需要重新構(gòu)建(rebuild)后才能在瀏覽器端使用。

那么, webpack是如何進(jìn)行資源的打包的呢?總結(jié)如下:

對(duì)于單入口文件,每個(gè)入口文件把自己所依賴的資源全部打包到一起,即使一個(gè)資源循環(huán)加載的話,也只會(huì)打包一份

對(duì)于多入口文件的情況,分別獨(dú)立執(zhí)行單個(gè)入口的情況,每個(gè)入口文件各不相干

我們的項(xiàng)目使用的就是多入口文件。在入口文件中,webpack會(huì)對(duì)每個(gè)資源文件進(jìn)行配置一個(gè)id,即使多次加載,它的id也是一樣的,因此只會(huì)打包一次。

實(shí)例如下:
main.js引用了chunk1、chunk2,chunk1又引用了chunk2,打包后:bundle.js:

 ...省略webpack生成代碼
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    __webpack_require__(1);//webpack分配的id
    __webpack_require__(2);

/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
    //chunk1.js文件
    __webpack_require__(2);
    var chunk1=1;
    exports.chunk1=chunk1;

/***/ },
/* 2 */
/***/ function(module, exports) {
    //chunk2.js文件
    var chunk2=1;
    exports.chunk2=chunk2;

/***/ }
/******/ ]);

2.如何定位webpack打包速度慢的原因

我們首先需要定位webpack打包速度慢的原因,才能因地制宜采取合適的方案。我么可以在終端中輸入:

$ webpack --profile --json > stats.json

然后將輸出的json文件到如下兩個(gè)網(wǎng)站進(jìn)行分析

https://github.com/webpack/an...

http://alexkuz.github.io/webp...

這兩個(gè)網(wǎng)站可以將構(gòu)建后的組成用可視化的方式呈現(xiàn)出來,可以讓你清楚的看到模塊的組成部分,以及在項(xiàng)目中可能存在的多版本引用的問題,對(duì)于分析項(xiàng)目依賴有很大的幫助

優(yōu)化方案與思路

針對(duì)webpack構(gòu)建大規(guī)模應(yīng)用的優(yōu)化往往比較復(fù)雜,我們需要抽絲剝繭,從性能提升點(diǎn)著手,可能沒有一套通用的方案,但大體上的思路是通用的,核心思路可能包括但不限于如下:

1):拆包,限制構(gòu)建范圍,減少資源搜索時(shí)間,無關(guān)資源不要參與構(gòu)建

2):使用增量構(gòu)建而不是全量構(gòu)建

3):從webpack存在的不足出發(fā),優(yōu)化不足,提升效率

webpack打包優(yōu)化

1.減小打包文件體積

webpack+react的項(xiàng)目打包出來的文件經(jīng)常動(dòng)則幾百kb甚至上兆,究其原因有:

import css文件的時(shí)候,會(huì)直接作為模塊一并打包到j(luò)s文件中

所有js模塊 + 依賴都會(huì)打包到一個(gè)文件

React、ReactDOM文件過大

針對(duì)第一種情況,我們可以使用 extract-text-webpack-plugin,但缺點(diǎn)是會(huì)產(chǎn)生更長(zhǎng)時(shí)間的編譯,也沒有HMR,還會(huì)增加額外的HTTP請(qǐng)求。對(duì)于css文件不是很大的情況最好還是不要使用該插件。

針對(duì)第二種情況,我們可以通過提取公共代碼塊,這也是比較普遍的做法:

 new webpack.optimize.CommonsChunkPlugin("common.js");

通過這種方法,我們可以有效減少不同入口文件之間重疊的代碼,對(duì)于非單頁應(yīng)用來說非常重要。

針對(duì)第三種情況,我們可以把React、ReactDOM緩存起來:

    entry: {
        vendor: ["react", "react-dom"]
    },
    new webpack.optimize.CommonsChunkPlugin("vendor","common.js"),

我們?cè)陂_發(fā)環(huán)境使用react的開發(fā)版本,這里包含很多注釋,警告等等,部署線上的時(shí)候可以通過 webpack.DefinePlugin 來切換生產(chǎn)版本。

當(dāng)然,我們還可以將React 直接放到CDN上,以此來減少體積。

2.代碼壓縮

webpack提供的UglifyJS插件由于采用單線程壓縮,速度很慢 ,
webpack-parallel-uglify-plugin插件可以并行運(yùn)行UglifyJS插件,這可以有效減少構(gòu)建時(shí)間,當(dāng)然,該插件應(yīng)用于生產(chǎn)環(huán)境而非開發(fā)環(huán)境,配置如下:

var ParallelUglifyPlugin = require("webpack-parallel-uglify-plugin");
new ParallelUglifyPlugin({
   cacheDir: ".cache/",
   uglifyJS:{
     output: {
       comments: false
     },
     compress: {
       warnings: false
     }
   }
 })

3.happypack

happypack 的原理是讓loader可以多進(jìn)程去處理文件,原理如圖示:

此外,happypack同時(shí)還利用緩存來使得rebuild 更快

var HappyPack = require("happypack"),
  os = require("os"),
  happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });

modules: {
    loaders: [
      {
        test: /.js|jsx$/,
        loader: "HappyPack/loader?id=jsHappy",
        exclude: /node_modules/
      }
    ]
}

plugins: [
    new HappyPack({
      id: "jsHappy",
      cache: true,
      threadPool: happyThreadPool,
      loaders: [{
        path: "babel",
        query: {
          cacheDirectory: ".webpack_cache",
          presets: [
            "es2015",
            "react"
          ]
        }
      }]
    }),
    //如果有多帶帶提取css文件的話
    new HappyPack({
      id: "lessHappy",
      loaders: ["style","css","less"]
    })
  ]

4.緩存與增量構(gòu)建

由于項(xiàng)目中主要使用的是react.js和es6,結(jié)合webpack的babel-loader加載器進(jìn)行編譯,每次重新構(gòu)建都需要重新編譯一次,我們可以針對(duì)這個(gè)進(jìn)行增量構(gòu)建,而不需要每次都全量構(gòu)建。

babel-loader可以緩存處理過的模塊,對(duì)于沒有修改過的文件不會(huì)再重新編譯,cacheDirectory有著2倍以上的速度提升,這對(duì)于rebuild 有著非常大的性能提升。

var node_modules = path.resolve(__dirname, "node_modules");
var pathToReact = path.resolve(node_modules, "react/react");
var pathToReactDOM = path.resolve(node_modules,"react-dom/index");

{
        test: /.js|jsx$/,
        include: path.join(__dirname, "src"),
        exclude: /node_modules/,
        loaders: ["react-hot","babel-loader?cacheDirectory"],
        noParse: [pathToReact,pathToReactDOM]
}

babel-loader讓除了node_modules目錄下的js文件都支持es6語法,注意 exclude: /node_modules/很重要,否則 babel 可能會(huì)把node_modules中所有模塊都用 babel 編譯一遍!
當(dāng)然,你還需要一個(gè)像這樣的.babelrc文件,配置如下:

{
  "presets": ["es2015", "stage-0", "react"],
  "plugins": ["transform-runtime"]
}

這是一勞永逸的做法,何樂而不為呢?除此之外,我們還可以使用webpack自帶的cache,以緩存生成的模塊和chunks以提高多個(gè)增量構(gòu)建的性能。

在webpack的整個(gè)構(gòu)建過程中,有多個(gè)地方提供了緩存的機(jī)會(huì),如果我們打開了這些緩存,會(huì)大大加速我們的構(gòu)建

而針對(duì)增量構(gòu)建 ,我們一般使用:

webpack-dev-server或webpack-dev-middleware,這里我們使用webpack-dev-middleware

webpackDevMiddleware(compiler, {
                    publicPath: webpackConfig.output.publicPath,
                    stats: {
                      chunks: false,
                      colors: true
                    },
                    debug: true,
                    hot: true,
                    lazy: false,
                    historyApiFallback: true,
                    poll: true
                })

通過設(shè)置chunks:false,可以將控制臺(tái)輸出的代碼塊信息關(guān)閉

5.減少構(gòu)建搜索或編譯路徑

為了加快webpack打包時(shí)對(duì)資源的搜索速度,有很多的做法:

Resolove.root VS Resolove.moduledirectories

大多數(shù)路徑應(yīng)該使用 resolve.root,只對(duì)嵌套的路徑使用 Resolove.moduledirectories,這可以獲得顯著的性能提升

原因是Resolove.moduledirectories是取相對(duì)路徑,所以比起 resolve.root會(huì)多parse很多路徑:

resolve: {
    root: path.resolve(__dirname,"src"),
    modulesDirectories: ["node_modules"]
  },

DLL & DllReference

針對(duì)第三方NPM包,這些包我們并不會(huì)修改它,但仍然每次都要在build的過程消耗構(gòu)建性能,我們可以通過DllPlugin來前置這些包的構(gòu)建,具體實(shí)例:https://github.com/webpack/we...

alias和noPase

resolve.alias 是webpack 的一個(gè)配置項(xiàng),它的作用是把用戶的一個(gè)請(qǐng)求重定向到另一個(gè)路徑。 比如:

resolve: {  // 顯示指出依賴查找路徑
    alias: {
        comps: "src/pages/components"
    }
}

這樣我們?cè)谝虬哪_本中的使用 require("comps/Loading.jsx");其實(shí)就等價(jià)于require("src/pages/components/Loading.jsx")。

webpack 默認(rèn)會(huì)去尋找所有 resolve.root 下的模塊,但是有些目錄我們是可以明確告知 webpack 不要管這里,從而減輕 webpack 的工作量。這時(shí)會(huì)用到module.noParse 參數(shù)

在項(xiàng)目中合理使用 alias 和 noParse 可以有效提升效率,雖然不是很明顯

以上配置均由本人給出,僅供參考(有些插件的官方文檔給的不是那么明晰)

6.其他

開啟devtool: "#inline-source-map"會(huì)增加編譯時(shí)間

css-loader 0.15.0+ 使webpack加載變得緩慢

//css-loader 0.16.0
Hash: 8d3652a9b4988c8ad221
Version: webpack 1.11.0
Time: 51612ms

//以下是css-loader 0.14.5
Hash: bd471e6f4aa10b195feb
Version: webpack 1.11.0
Time: 6121ms

對(duì)于ant-design模塊,使用babel-plugin-import插件來按需加載模塊

DedupePlugin插件可以在打包的時(shí)候刪除重復(fù)或者相似的文件,實(shí)際測(cè)試中應(yīng)該是文件級(jí)別的重復(fù)的文件

結(jié)尾

雖然上面的做法減少了文件體積,加快了編譯速度,整體構(gòu)建(initial build)從最初的三分多鐘到一分鐘,rebuild十多秒,優(yōu)化效果明顯。但對(duì)于Webpack + React項(xiàng)目來說,性能優(yōu)化方面遠(yuǎn)不止于此,還有很多的優(yōu)化空間,比如服務(wù)端渲染,首屏優(yōu)化,異步加載模塊,按需加載,代碼分割等等

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/81565.html

相關(guān)文章

  • 前端性能優(yōu)化上線

    摘要:看下狀態(tài)可以看到我已經(jīng)有一些鏡像了我已經(jīng)刪除了拉鏡像正常即可,中間那段是中國(guó)鏡像源,我們成功下來了的鏡像。攻破像我這樣屌絲的服務(wù)器一般都買的,大的資源文件不住,一個(gè)動(dòng)輒的文件這很蛋疼,不上很難受。 4000字長(zhǎng)文,多圖預(yù)警?。。×髁可魅耄?! 性能優(yōu)化 - 屌絲前端性能優(yōu)化、上線一條龍 大家好我又來了,本章給大家?guī)淼膬?nèi)容是:上線和上線后的性能優(yōu)化 項(xiàng)目地址 實(shí)戰(zhàn)預(yù)覽地址 實(shí)戰(zhàn)項(xiàng)目地址...

    wupengyu 評(píng)論0 收藏0
  • 提升90%加載速度——vuecli下的首屏性能優(yōu)化

    摘要:如果我們能把不同路由對(duì)應(yīng)的組件分割成不同的代碼塊,然后當(dāng)路由被訪問的時(shí)候才加載對(duì)應(yīng)組件,這樣就更加高效了。 前言 之前用vuecli做了個(gè)博客,是一個(gè)單頁面項(xiàng)目,大概有十個(gè)路由直接npm run build打包出來,有一個(gè)1M的巨大js文件 showImg(https://segmentfault.com/img/bVbtXVk?w=1516&h=218); 先掛載到服務(wù)器上試試好家伙...

    dreamtecher 評(píng)論0 收藏0
  • 淺談webpack4.0 性能優(yōu)化

    摘要:中在性能優(yōu)化所做的努力,也大抵圍繞著這兩個(gè)大方向展開。因此,將依賴模塊從業(yè)務(wù)代碼中分離是性能優(yōu)化重要的一環(huán)。大型庫是否可以通過定制功能的方式減少體積。這又違背了性能優(yōu)化的基礎(chǔ)。接下來可以抓住一些細(xì)節(jié)做更細(xì)的優(yōu)化。中,為默認(rèn)啟動(dòng)這一優(yōu)化。 前言:在現(xiàn)實(shí)項(xiàng)目中,我們可能很少需要從頭開始去配置一個(gè)webpack 項(xiàng)目,特別是webpack4.0發(fā)布以后,零配置啟動(dòng)一個(gè)項(xiàng)目成為一種標(biāo)配。正因?yàn)?..

    leanxi 評(píng)論0 收藏0
  • 前端進(jìn)階(14) - 如何提升前端性能和響應(yīng)速度

    摘要:一般建議文件最大不超過。按需加載可以減小首屏加載文件的體積,達(dá)到提高響應(yīng)速度的目的。如果你的項(xiàng)目不需要處理靜態(tài)資源如圖片,也不需要按需加載,并追求前端高性能的話,可以嘗試。 如何提升前端性能和響應(yīng)速度 下面大多是從前端工程化的角度給出的優(yōu)化建議,如果需要了解語法上的優(yōu)化,可以參考: 如何提高頁面加載速度 編寫高效的JavaScript Web前端性能優(yōu)化進(jìn)階 - 完結(jié)篇 1. 原生...

    lylwyy2016 評(píng)論0 收藏0
  • 前端進(jìn)階(14) - 如何提升前端性能和響應(yīng)速度

    摘要:一般建議文件最大不超過。按需加載可以減小首屏加載文件的體積,達(dá)到提高響應(yīng)速度的目的。如果你的項(xiàng)目不需要處理靜態(tài)資源如圖片,也不需要按需加載,并追求前端高性能的話,可以嘗試。 如何提升前端性能和響應(yīng)速度 下面大多是從前端工程化的角度給出的優(yōu)化建議,如果需要了解語法上的優(yōu)化,可以參考: 如何提高頁面加載速度 編寫高效的JavaScript Web前端性能優(yōu)化進(jìn)階 - 完結(jié)篇 1. 原生...

    Airy 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<