欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談Webpack打包優(yōu)化技巧

 更新時(shí)間:2018年06月12日 11:47:55   作者:arlendp2012  
這篇文章主要介紹了淺談Webpack打包優(yōu)化,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

前端的打包工具從之前的browserify、grunt、gulp到現(xiàn)如今的rollup、webpack,涌現(xiàn)出了很多優(yōu)秀的打包工具,而目前最火的無(wú)疑是webpack,無(wú)論是當(dāng)前熱門(mén)的框架還是工具庫(kù)很多都選擇了它作為打包工具,因此在開(kāi)發(fā)中webpack作為打包工具是一個(gè)很好的選擇。在最近的項(xiàng)目開(kāi)發(fā)中我也用到了webpack,其中也碰到了不少優(yōu)化方面的問(wèn)題,這里總結(jié)一下webpack打包優(yōu)化的一些細(xì)節(jié)和方法。

首先,這次項(xiàng)目用到的是vue的全家桶,在webpack的配置方面直接用的是 vue-cli 生成的默認(rèn)配置,項(xiàng)目打包完成后發(fā)現(xiàn)生成的 vendor.js 文件體積特別大,其次打包過(guò)程相當(dāng)緩慢,因此想嘗試各種方式對(duì)其進(jìn)行優(yōu)化。

定位體積大的模塊

要想對(duì)打包體積進(jìn)行優(yōu)化,首先得找到體積大的模塊,在這里我們可以使用webpack插件 webpack-bundle-analyzer 來(lái)查看整個(gè)項(xiàng)目的體積結(jié)構(gòu)對(duì)比,它是以treemap的形式展現(xiàn)出來(lái),很形象直觀,還有一些具體的交互形式。既可以查看你項(xiàng)目中用到的所有依賴,也可以直觀看到各個(gè)模塊體積在整個(gè)項(xiàng)目中的占比。

該插件的使用方法可以直接通過(guò) npm install webpack-bundle-analyzer --save-dev 安裝,并在webpack的配置信息中的 plugins: [new BundleAnalyzerPlugin()] 中添加即可。對(duì)于 vue-cli 中的配置方式,默認(rèn)是安裝了該插件,但是沒(méi)有啟用,找到 config/index.js 文件在 build 下面會(huì)有 bundleAnalyzerReport 的配置,默認(rèn)是 process.env.npm_config_report ,這里建議在 package.json 的 scripts 中添加一行 "analyz": "npm_config_report=true npm run build" ,這樣每次想啟用該插件時(shí)只需要 npm run analyze 即可。

提取公共模塊

對(duì)于webpack,它在模塊化打包上有兩點(diǎn)是其核心功能,一是它支持大量的模塊類型,無(wú)論是 TypeScript 、 CoffeeScript 還是 sass 、 stylus 等語(yǔ)言它都支持,二是它可以通過(guò)配置來(lái)控制打包文件的粒度,這個(gè)下面會(huì)講到。

在開(kāi)發(fā)中我們往往會(huì)將所有的依賴庫(kù)單獨(dú)提取出來(lái),而不與我們的項(xiàng)目代碼混在一起,這時(shí)我們會(huì)用到一個(gè)webpack自帶的插件 CommonsChunkPlugin ,從名字上就可以看出它是一個(gè)提取公共模塊的插件。從它的文檔中可以看出可以傳入一個(gè)對(duì)象最為參數(shù),在使用中常用的三個(gè)參數(shù)分別為:

  1. name(names)
  2. minChunks
  3. chunks

name 好理解,指的就是最后打包文件的名字,而如果使用的是 names 的話,傳入的必須是一個(gè)字符串?dāng)?shù)組。 minChunks 如果傳入的是一個(gè)數(shù)字的話,指的是如果該模塊被其他模塊的引用次數(shù)達(dá)到了這個(gè)數(shù)值的話該模塊就會(huì)被打包。如果傳入的是一個(gè)函數(shù)的話,其返回值必須是布爾類型來(lái)指明這個(gè)模塊是否應(yīng)該被打包進(jìn)公共模塊。而 chunks 則會(huì)指定一個(gè)字符串?dāng)?shù)組,如果設(shè)置了該參數(shù),則打包的時(shí)候只會(huì)從其中指定的模塊中提取公共子模塊。

下面通過(guò)幾個(gè)實(shí)例來(lái)說(shuō)明這個(gè)插件是如何工作的。

假設(shè)有兩個(gè)模塊 chunk1.js 和 chunk2.js 以及兩個(gè)項(xiàng)目文件 a.js 和 b.js ,結(jié)構(gòu)大致如下:

// a.js
require('./chunk1');
require('./chunk2');
require('jquery');
// b.js
require('./chunk1');
require('./chunk2');
require('vue');
// webpack配置如下
module.exports = {
 entry: {
  main: './main.js', 
  main1: './main1.js',    
  jquery:["jquery"],   
  vue:["vue"]  
 },  
 output: {   
  path: __dirname + '/dist',  
  filename: '[name].js' 
 },  
 plugins: [ 
  new CommonsChunkPlugin({  
   name: ["common","jquery","vue","load"],  
   minChunks:2 
  })  
 ] };

最終的打包結(jié)果是: jquery 被打包到 jquery.js , vue 被打包到 vue.js , common.js 打包的是公共模塊(chunk1和chunk2)。使用該插件打包時(shí),會(huì)將滿足 minChunks 的模塊打包到 name 數(shù)組的第一個(gè)塊里,然后數(shù)組后面的依次打包,首先從 entry 中找,如果沒(méi)有則產(chǎn)生一個(gè)空塊。 name 數(shù)組中最后一個(gè)塊打包的是webpack的runtime代碼,在使用的時(shí)候必須先加載該塊。

現(xiàn)在看一看 vue-cli 對(duì)于該插件的配置文件:

new webpack.optimize.CommonsChunkPlugin({
 name: 'vendor',
 minChunks: function (module, count) {
  // 將node_modules中的依賴模塊全部提取到vendor文件中
  return (
   module.resource &&
   /\.js$/.test(module.resource) &&
   module.resource.indexOf(
    path.join(__dirname, '../node_modules')
   ) === 0
  )
 }
}),
// webpack在使用CommonsChunkPlugin時(shí)會(huì)生成一段runtime代碼,并且打包進(jìn)vendor中。
// 這樣即使不改變vendor代碼,每次打包時(shí)runtime會(huì)變化導(dǎo)致vendor的hash變化,這里
// 把獨(dú)立的runtime代碼抽離出來(lái)來(lái)解決這個(gè)問(wèn)題
new webpack.optimize.CommonsChunkPlugin({
 name: 'manifest',
 chunks: ['vendor']
}),

移除不必要的文件

在項(xiàng)目中我通過(guò)方法一定位到幾處體積占用較大的庫(kù),其中一個(gè)便是 moment.js 這個(gè)日期處理庫(kù)。對(duì)于一個(gè)日期處理的功能,為何這個(gè)庫(kù)會(huì)占用如此大的體積,仔細(xì)查看發(fā)現(xiàn)當(dāng)引用這個(gè)庫(kù)的時(shí)候,所有的 locale 文件都被引入,而這些文件甚至在整個(gè)庫(kù)的體積中占了大部分,因此當(dāng)webpack打包時(shí)移除這部分內(nèi)容會(huì)讓打包文件的體積有所減小。

webpack自帶的兩個(gè)庫(kù)可以實(shí)現(xiàn)這個(gè)功能:

  1. IgnorePlugin
  2. ContextReplacementPlugin

IgnorePlugin 的使用方法如下:

// 插件配置
plugins: [
 // 忽略moment.js中所有的locale文件
 new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
],
// 使用方式
const moment = require('moment');
// 引入zh-cn locale文件
require('moment/locale/zh-cn');
moment.locale('zh-cn');

ContextReplacementPlugin 的使用方法如下:

// 插件配置
plugins: [
 // 只加載locale zh-cn文件
 new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /zh-cn/),
],
// 使用方式
const moment = require('moment');
moment.locale('zh-cn');

通過(guò)以上兩種方式, moment.js 的體積大致能縮減為原來(lái)的四分之一。

模塊化引入

在項(xiàng)目中我使用了 lodash 這個(gè)很常用的工具庫(kù),然而在代碼定位的時(shí)候發(fā)現(xiàn)這個(gè)庫(kù)也占了不少的體積。仔細(xì)想想,我們?cè)谑褂眠@類工具庫(kù)的時(shí)候往往只使用到了其中的很少的一部分功能,但卻把整個(gè)庫(kù)都引入了。因此這里也可以進(jìn)一步優(yōu)化,只引用需要的部分。

import {chain, cloneDeep} from 'lodash';
// 可以改寫(xiě)為
import chain from 'lodash/chain';
import cloneDeep from 'lodash/cloneDeep';

這樣就可以只打包我們需要的部分功能。

通過(guò)CDN引用

對(duì)于一些必要的庫(kù),但又無(wú)法對(duì)該庫(kù)進(jìn)行更好的體積優(yōu)化的話,可以嘗試通過(guò)外部引入的方式來(lái)減小打包文件的體積。采用該方法只需要在cdn站點(diǎn)找到需要引用的庫(kù)的外部鏈接,以及對(duì)webpack進(jìn)行簡(jiǎn)單配置即可。

// 在html中添加script引用
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
// 這里externals的key指的是使用時(shí)需要require的包名,value指的是該庫(kù)通過(guò)script引入后在全局注冊(cè)的變量名
externals: {
 jquery: 'jQuery'
}
// 使用方法
require('jquery')

通過(guò) DLLPlugin 和 DLLReferencePlugin 拆分文件

如果項(xiàng)目過(guò)大,打包的時(shí)間會(huì)相當(dāng)?shù)拈L(zhǎng),如果頻繁更新上線則會(huì)不斷對(duì)代碼進(jìn)行編譯打包,浪費(fèi)很多時(shí)間。這時(shí)我們便可以將那些不常更新的框架和庫(kù)(如vue.js等)進(jìn)行單獨(dú)的編譯打包,這樣每次開(kāi)發(fā)上線就只需要對(duì)我們的開(kāi)發(fā)文件進(jìn)行編譯打包,這樣可以極大地省去不必要的打包時(shí)間。而這種方法需要 DLLPlugin DLLReferencePlugin 兩個(gè)插件的配合來(lái)完成。

DLLPlugin

在使用這個(gè)插件時(shí),我們需要單獨(dú)創(chuàng)建一個(gè)配置文件,這里命名為 webpack.dll.config.js ,配置如下:

module.exports = {
 entry: {
  lib: ['vue', 'vuex', 'vue-resource', 'vue-router']
 },
 output: {
  path: path.resolve(__dirname, '../dist', 'dll'),
  filename: '[name].js',
  publicPath: process.env.NODE_ENV === 'production'
   ? config.build.assetsPublicPath
   : config.dev.assetsPublicPath,
  library: '[name]_library'
 },
 plugins: [
  new webpack.DefinePlugin({
   'process.env': '"production"'
  }),
  /**
   * path: manifest.json輸出文件路徑
   * name: dll對(duì)象名,跟output.library保持一致
   */ 
  new webpack.DllPlugin({
   context: __dirname,
   path: path.resolve(__dirname, '../dist/dll', 'lib.manifest.json'),
   name: '[name]_library'
  })
 ]
}

這里要注意幾點(diǎn):

  1. entry 中寫(xiě)明所有要單獨(dú)打包的模塊
  2. output 的 library 屬性可以將dll包暴露出來(lái)
  3. DLLPlugin 的配置中, path 指明 manifest.json 文件的生成路徑, name 暴露出dll的函數(shù)名

運(yùn)行該配置文件便可生成打包文件和 manifest.json 文件。

DLLReferencePlugin

對(duì)于該插件的配置,不需要像上面一樣單獨(dú)寫(xiě)配置文件,只需要在生產(chǎn)配置文件中添加如下代碼:

new webpack.DllReferencePlugin({    
 context: __dirname,         // 同dll配置的路徑保持一致
 manifest: require('../dist/dll/lib.manifest.json') // manifest的位置
}),

然后運(yùn)行webpack,發(fā)現(xiàn)打包的速度得到了極大地提升,也不用每次更新代碼的時(shí)候重復(fù)編譯打包這些依賴庫(kù)了。

其他

對(duì)于webpack的打包優(yōu)化我大致就總結(jié)了上面的一些方法,而為了讓頁(yè)面更快的加載,有更好的用戶體驗(yàn),我們并不只是從打包上優(yōu)化,也可以有其他方面的優(yōu)化,這里我也簡(jiǎn)單提一下我使用過(guò)的方法。

開(kāi)啟Gzip壓縮

開(kāi)啟gzip壓縮可以減少HTTP傳輸?shù)臄?shù)據(jù)量和時(shí)間,從而減少客戶端請(qǐng)求的響應(yīng)時(shí)間,由于降低了請(qǐng)求時(shí)間,頁(yè)面的加載速度也會(huì)得到提升,會(huì)有更快的渲染速度,極大地改善了用戶體驗(yàn)。由于現(xiàn)在基本上所有的主流瀏覽器都支持Gzip的壓縮方式,只需要對(duì)服務(wù)器進(jìn)行相關(guān)設(shè)置即可,這里就不具體講如何配置服務(wù)器。

壓縮混淆代碼

我們平常也會(huì)對(duì)代碼進(jìn)行壓縮混淆,可以通過(guò) UglifyJS 等工具來(lái)對(duì)js代碼進(jìn)行壓縮,同時(shí)可以去掉不必要的空格、注釋、console信息等,也可以有效的減小代碼體積。

總結(jié)

本文到這里就結(jié)束了,主要是對(duì)webpack的打包優(yōu)化部分做了些講解,當(dāng)然能力和時(shí)間有限,只研究了部分方法,可能會(huì)有其他更多的優(yōu)化方法,無(wú)論是從編譯打包的體積還是速度上都能有更好的優(yōu)化。接觸了一段時(shí)間的webpack發(fā)現(xiàn)作為一個(gè)打包工具實(shí)在是過(guò)于復(fù)雜,無(wú)論從開(kāi)始的官方文檔還是到新的高級(jí)特性,都很難去完全掌握,還得需要自己不斷去實(shí)踐去深入研究才行。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • JS正則表達(dá)式驗(yàn)證數(shù)字代碼

    JS正則表達(dá)式驗(yàn)證數(shù)字代碼

    本篇文章主要是對(duì)JS正則表達(dá)式驗(yàn)證數(shù)字的代碼進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2014-01-01
  • JS對(duì)象類型之Error錯(cuò)誤對(duì)象的用法詳解

    JS對(duì)象類型之Error錯(cuò)誤對(duì)象的用法詳解

    error對(duì)象是JavaScript的原生對(duì)象,當(dāng)程序解析和運(yùn)行過(guò)程中發(fā)生了錯(cuò)誤,JS引擎就會(huì)自動(dòng)產(chǎn)生并拋出一個(gè)error對(duì)象的實(shí)例,并且程序會(huì)終止在錯(cuò)誤發(fā)生的地方,本文給大家介紹了JS Error錯(cuò)誤對(duì)象的用法,需要的朋友可以參考下
    2024-04-04
  • js如何將多個(gè)json結(jié)構(gòu)組成的字符串轉(zhuǎn)換為數(shù)組?

    js如何將多個(gè)json結(jié)構(gòu)組成的字符串轉(zhuǎn)換為數(shù)組?

    接口返回的EventStream結(jié)構(gòu)的數(shù)據(jù),由于http流式傳輸時(shí),可能會(huì)分段,所以導(dǎo)致本該每次返回一段json數(shù)據(jù)結(jié)構(gòu)的字符串,變成了多個(gè)json數(shù)據(jù)結(jié)構(gòu)的字符串拼接在了一起,本文講述js如何將多個(gè)json結(jié)構(gòu)組成的字符串轉(zhuǎn)換為數(shù)組
    2024-08-08
  • javascript獲取元素偏移量的方法有哪些

    javascript獲取元素偏移量的方法有哪些

    javascript中可以通過(guò)四個(gè)屬性獲得元素的偏移量,offsetHeight、offsetWidth、offsetLeft、offsetTop,下面為大家解釋下各屬性的含義
    2014-06-06
  • 詳細(xì)聊聊閉包在js中充當(dāng)著什么角色

    詳細(xì)聊聊閉包在js中充當(dāng)著什么角色

    在js中,閉包是一個(gè)很重要又相當(dāng)不容易完全理解的要點(diǎn),下面這篇文章主要給大家介紹了關(guān)于閉包在js中充當(dāng)著什么角色的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-01-01
  • BootStrap便簽頁(yè)的簡(jiǎn)單應(yīng)用

    BootStrap便簽頁(yè)的簡(jiǎn)單應(yīng)用

    本文通過(guò)實(shí)例代碼給大家簡(jiǎn)單介紹了bootstrap便簽頁(yè)的簡(jiǎn)單應(yīng)用,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下
    2017-01-01
  • JavaScript之class繼承_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    JavaScript之class繼承_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了JavaScript之class繼承,新的關(guān)鍵字class從ES6開(kāi)始正式被引入到JavaScript中。class的目的就是讓定義類更簡(jiǎn)單,有興趣的可以了解一下
    2017-07-07
  • JS實(shí)戰(zhàn)篇之收縮菜單表單布局

    JS實(shí)戰(zhàn)篇之收縮菜單表單布局

    這篇文章主要介紹了JS實(shí)戰(zhàn)篇之收縮菜單表單布局的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-12-12
  • 基于代數(shù)方程庫(kù)Algebra.js解二元一次方程功能示例

    基于代數(shù)方程庫(kù)Algebra.js解二元一次方程功能示例

    這篇文章主要介紹了基于代數(shù)方程庫(kù)Algebra.js解二元一次方程功能,結(jié)合具體實(shí)例形式分析了方程庫(kù)Algebra.js計(jì)算方程的具體使用技巧,需要的朋友可以參考下
    2017-06-06
  • javascript 易錯(cuò)知識(shí)點(diǎn)實(shí)例小結(jié)

    javascript 易錯(cuò)知識(shí)點(diǎn)實(shí)例小結(jié)

    這篇文章主要介紹了javascript 易錯(cuò)知識(shí)點(diǎn),結(jié)合實(shí)例形式總結(jié)分析了javascript 對(duì)象屬性、繼承常見(jiàn)易錯(cuò)知識(shí)點(diǎn)與注意事項(xiàng),需要的朋友可以參考下
    2020-04-04

最新評(píng)論