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

資訊專欄INFORMATION COLUMN

前端性能優(yōu)化—js代碼打包

Rango / 971人閱讀

摘要:注意使用的版本不同,可能會導(dǎo)致打包出的結(jié)果不一樣。完整的優(yōu)化代碼見有用的文章分離第三方庫及公用文件

現(xiàn)在的 web 應(yīng)用,內(nèi)容一般都很豐富,站點需要加載的資源也特別多,尤其要加載很多 js 文件。js 文件從服務(wù)端獲取,體積大小決定了傳輸?shù)目炻?;瀏覽器端拿到 js 文件之后,還需要經(jīng)過解壓縮、解析、編譯、執(zhí)行操作,所以,控制 js 代碼的體積以及按需加載對前端性能以及用戶體驗是十分的重要。

本文從 Tree Shaking代碼分割 兩部分介紹 js 打包優(yōu)化,有興趣的可以跟著一起實踐。
clone 以下項目 https://github.com/jasonintju...,就是個簡單的 React SPA,一看就懂。

Tree Shaking

Tree Shaking 簡單理解就是:打包時把一些沒有用到的代碼刪除掉,保證打包后的代碼體積最小化。其詳細的介紹可以參考 Tree-Shaking性能優(yōu)化實踐 - 原理篇。

項目 clone、安裝依賴后,先 npm run build 打包初始代碼,大小及分布如下(其中 src/utils/utils.js 這個文件打包后大小為11.72Kb):

src/containers/About/test.js只引用但是沒有使用到,src/utils/utils.js 這個文件是個工具函數(shù)集,有很多很多函數(shù),而我們只用到了其中的一個。默認情況下,整個文件都被打包進 main.js 了,顯然,這是很大的冗余,正好可以使用 Tree Shaking 優(yōu)化。

修改 .babelrc
{
  "presets": [["env", { "modules": false }], "react", "stage-0"]
}
修改 package.json
{
  "name": "optimizing-js",
  "version": "1.0.0",
  "sideEffects": false
}

這樣設(shè)置之后,表示所有的 module 都是無副作用的,沒有使用到的 module 都可以刪掉,此時打包結(jié)果如下:

import React from "react";
// 只引入了 arraySum, utils.js 中的其他方法不會被打包
import { arraySum } from "@utils/utils";
import "./test"; // 引用,“未使用”,不會被打包
import "./About.scss"; // 引用,“未使用”,不會被打包

class About extends React.Component {
  render() {
    const sum = arraySum([12, 3]);
    return (
      

About Page

12 plus 3 equals {sum}
); } } export default About;

如上面注釋所說,Tree Shaking 認為這些是沒有被使用的代碼,所以可以刪掉。但事實上我們知道不是這樣的,test.js 可以刪掉,但是 css、scss 是有用的代碼,我們只需引入即可。因此,需要修改一下 sideEffects 的值:

{
  "sideEffects": [
    "*.css", "*.scss", "*.sass"
  ]
}

表示,除了[]中的文件(類型),其他文件都是無副作用的,可以放心刪掉。此時打包結(jié)果:

可以看到,css 等樣式文件現(xiàn)在如期打包進去了。如果有其他類型的文件有副作用,但是也希望打包進去,在 sideEffects: [] 中添加即可,可以是具體的某個文件或者某種文件類型。

關(guān)于為什么修改這兩個地方就可以實現(xiàn) Tree Shaking 的效果了,可以參考一下https://developers.google.com... 或者其他文章,這里不做詳細解釋了。

代碼分割

單頁應(yīng)用,如果所有的資源都打包在一個 js 里面,毫無疑問,體積會非常龐大,首屏加載會有很長時間白屏,用戶體驗極差。所以,要代碼分割,分成一個一個小的 js,優(yōu)化加載時間。

分離第三方庫代碼

第三方庫代碼多帶帶提取出來,和業(yè)務(wù)代碼分離,減少 js 文件體積。在 webpack.base.conf.js 中增加:

module: {...},
optimization: {
  splitChunks: {
    cacheGroups: {
      venders: {
        test: /node_modules/,
        name: "vendors",
        chunks: "all"
      }
    }
  }
},
plugins: ...

動態(tài)導(dǎo)入

使用 ECMAScript 提案 的 dynamic import 語法可以異步加載業(yè)務(wù)中的組件。使用方法如下:

// src/containers/App/App.js

// 注釋掉此行代碼
// import About from "@containers/About/About";

// 修改模塊為動態(tài)導(dǎo)入形式
 import(/* webpackChunkName: "about" */ "@containers/About/About").then(module => module.default)}/>

此時打包結(jié)果:

能看到, 組件已經(jīng)被 webpack 多帶帶打包出對應(yīng)的 js 文件了。同時,結(jié)合 react-router,分離 組件的同時也做到了按需加載:當(dāng)訪問 About 頁面時,about.js 才會被瀏覽器加載。

注意,我們現(xiàn)在只是簡單地使用了 dynamic import,很多邊界情況沒考慮進去,比如:加載進度、加載失敗、超時等處理??梢蚤_發(fā)一個高階組件,把這些異常處理都包含進去。社區(qū)有個很棒的 react-loadable,大樹底下好乘涼~

npm i react-loadable

// src/containers/App/App.js
import Loadable from "react-loadable";

// 代碼分割 & 異步加載
const LoadableAbout = Loadable({
  loader: () => import(/* webpackChunkName: "about" */ "@containers/About/About"),
  loading() {
    return 
Loading...
; } }); class App extends React.Component { render() { return (
); } }

react-loadable 還提供了 preload 功能。假如有統(tǒng)計數(shù)據(jù)顯示,用戶在進入首頁之后大概率會進入 About 頁面,那我們就在首頁加載完成的時候去加載 about.js,這樣等用戶跳到 About 頁面的時候,js 資源都已經(jīng)加載好了,用戶體驗會更好。

// src/containers/App/App.js
componentDidMount() {
  LoadableAbout.preload();
}

如果有同學(xué)對Network面板不是很熟悉,可以看一下 Chrome DevTools — Network。

提取復(fù)用的業(yè)務(wù)代碼

第三方庫代碼已經(jīng)多帶帶提取出來了,但是業(yè)務(wù)代碼中也會有一些復(fù)用的代碼,典型的比如一些工具函數(shù)庫 utils.js?,F(xiàn)在,About 組件Docs 組件都引用了 utils.js,webpack 只打包了一份 utils.jsmain.js 里面,main.js 在首頁就被加載了,其他頁面有使用到 utils.js 自然可以正常引用到,符合我們的預(yù)期。但是目前我們只是把 About 頁面異步加載了,如果把 Docs 頁面也異步加載了會怎么樣呢?

// src/containers/App/App.js
// 注釋掉此行代碼
// import Docs from "@containers/Docs/Docs";

const LoadableDocs = Loadable({
  loader: () => import(/* webpackChunkName: "docs" */ "@containers/Docs/Docs"),
  loading() {
    return 
Loading...
; } }); class App extends React.Component { render() { return (
); } }

此時打包結(jié)果:

能夠看到,about.js 和 docs.js 里面都打包了 utils.js,重復(fù)了!
webpack.base.conf.js 中增加:

module: {...},
optimization: {
  splitChunks: {
    cacheGroups: {
      venders: {
        test: /node_modules/,
        name: "vendors",
        chunks: "all"
      },
      default: {
        minSize: 0,
        minChunks: 2,
        reuseExistingChunk: true,
        name: "utils"
      }
    }
  }
},
plugins: ...

再打包看結(jié)果:

utils.js 也被多帶帶打包出來了,達到了預(yù)期。

分離非首頁使用且復(fù)用程度小的第三方庫

假如,現(xiàn)在 Docs.js 引用了 lodash 這個三方庫:

import React from "react";
import _ from "lodash";
import { arraySum } from "@utils/utils";
import "./Docs.scss";

class Docs extends React.Component {
  render() {
    const sum = arraySum([1, 3]);
    const b = _.sum([1, 3]);
    return (
      

Docs Page

1 plus 3 equals {sum}

use _.sum, 1 plus 3 equals  too.
); } } export default Docs;

打包結(jié)果:

lodash.js 只在 Docs 頁面使用,而且可能 Docs 頁面訪問量很少,把 lodash.js 打包在首頁就會加載的 venders.js 里面,實在不是明智之舉。

修改 webpack.base.conf.js

...
venders: {
  test: /node_modules/(?!(lodash)/)/, // 去除 lodash,剩余的第三方庫打成一個包,命名為 vendors-common
  name: "vendors-common",
  chunks: "all"
},
lodash: {
  test: /node_modules/lodash//, // lodash 庫多帶帶打包,并命名為 vender-lodash
  name: "vender-lodash"
},
default: {
  minSize: 0,
  minChunks: 2,
  reuseExistingChunk: true,
  name: "utils"
}
...

此時把 lodash 多帶帶打成了一個包,且配合 Docs 頁面的按需加載,達到了理想的加載效果。

緩存

項目打包后,資源部署在服務(wù)器端,客戶端需要向服務(wù)器請求下載這些資源,用戶才能看到內(nèi)容。使用緩存,客戶端可以大大減少不必要的請求和時間耽擱,只有當(dāng)資源有更新時,再去下載。區(qū)分一個文件是否有更新,使用 文件名 + hash 可以達到目的。本案例中,已經(jīng)使用了 "[name].[contenthash:8].js"。

然而,在打包的時候,webpack的運行時代碼有時候會導(dǎo)致某些情況出現(xiàn),如:什么內(nèi)容都沒改,兩次 build 代碼的 hash 不一樣;或者是,修改了 a 文件的代碼,卻導(dǎo)致了某些未修改代碼文件的 hash 也發(fā)生了變化。This is caused by the injection of the runtime and manifest which changes every build.

注意:使用的 webpack 版本不同,可能會導(dǎo)致打包出的結(jié)果不一樣。較新的版本或許沒有這種 hash 問題,但為了安全起見,還是建議按照下面的步驟處理一下。
分離 webpack runtimeChunk code
// webpack.base.conf.js
optimization: {
  runtimeChunk: {
    name: "manifest"
  },
  splitChunks: {...}
}

此時,能達到:修改某個文件,只有這個文件和 manifest.js 文件的 hash 會發(fā)生變化,其他文件的 hash 不變。
打包前:

// About.scss
.page-about {
  padding-left: 30px;
  color: #545880; // 修改字體顏色
}

修改后:

HashedModuleIdsPlugin

增加、刪除一些模塊,可能會導(dǎo)致不相關(guān)文件的 hash 發(fā)生變化,這是因為 webpack 打包時,按照導(dǎo)入模塊的順序,module.id 自增,會導(dǎo)致某些模塊的 module.id 發(fā)生變化,進而導(dǎo)致文件的 hash 變化。

解決方式: 使用 webpack 內(nèi)置的 HashedModuleIdsPlugin,該插件基于導(dǎo)入模塊的相對路徑生成相應(yīng)的 module.id,這樣如果內(nèi)容沒有變化加上 module.id 也沒變化,則生成的 hash 也就不會變化了。

// webpack.prod.conf.js
const webpack = require("webpack");
...
plugins: [new webpack.HashedModuleIdsPlugin(), new BundleAnalyzerPlugin()]

完整的優(yōu)化代碼見 https://github.com/jasonintju...

有用的文章:
webpack分離第三方庫及公用文件
https://developers.google.com...

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

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

相關(guān)文章

  • 前端進階(14) - 如何提升前端性能和響應(yīng)速度

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

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

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

    Airy 評論0 收藏0
  • 如何構(gòu)建前端代碼

    摘要:首先散文件是有害處的,第一是,散文件可能沒有版本號的區(qū)分,這樣因為緩存導(dǎo)致第二是散文件會嚴重拖慢性能,因為很多散文件不僅消耗請求資源,而且是在串行消耗。 基本認識 開發(fā)環(huán)境和線上環(huán)境的區(qū)別 在很久以前,前端的部署其實比較簡單,開發(fā)環(huán)境下,靜態(tài)資源往服務(wù)器上面一扔就ok了,如果考慮下優(yōu)化或者代碼保護,也只是加一個代碼壓縮和混淆。沒錯,剛?cè)胄械臅r候我就是這么干的。。。 但是隨著前...

    jhhfft 評論0 收藏0
  • 前端進階(9) - js 性能優(yōu)化利器:prepack

    摘要:性能優(yōu)化利器性能優(yōu)化性能優(yōu)化不外乎從三個角度入手開發(fā)者在編寫程序時,盡量避免不必要的冗余代碼,包括冗余的第三方庫首先要避免不必要的冗余代碼,包括不必要的閉包不必要的變量與函數(shù)聲明不必要的模塊分割等。 js 性能優(yōu)化利器:prepack 1. js 性能優(yōu)化 js 性能優(yōu)化不外乎從三個角度入手: 1.1 開發(fā)者在編寫程序時,盡量避免不必要的冗余代碼,包括冗余的第三方庫 首先要避免不必要的...

    JouyPub 評論0 收藏0
  • 前端構(gòu)建】WebPack實例與前端性能優(yōu)化

    摘要:感受構(gòu)建工具給前端優(yōu)化工作帶來的便利。多多益處邏輯清晰,程序注重數(shù)據(jù)與表現(xiàn)分離,可讀性強,利于規(guī)避和排查問題構(gòu)建工具層出不窮。其實工具都能滿足需求,關(guān)鍵是看怎么用,工具的使用背后是對前端性能優(yōu)化的理解程度。 這篇主要介紹一下我在玩Webpack過程中的心得。通過實例介紹WebPack的安裝,插件使用及加載策略。感受構(gòu)建工具給前端優(yōu)化工作帶來的便利。 showImg(https://se...

    QiShare 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<