日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
webpack2終極優(yōu)化

webpack是當下***的js打包工具,這得益于網頁應用日益復雜和js模塊化的流行。webpack2增加了一些新特性也正式發(fā)布了一段時間,是時候告訴大家如何用webpack2優(yōu)化你的構建讓它構建出更小的文件尺寸和更好的開發(fā)體驗。

創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供康縣網站建設、康縣做網站、康縣網站設計、康縣網站制作等企業(yè)網站建設、網頁設計與制作、康縣企業(yè)網站模板建站服務,10余年康縣做網站經驗,不只是建網站,更提供有價值的思路和整體網絡服務。

優(yōu)化輸出

打包結果更小可以讓網頁打開速度更快以及簡約寬帶??梢酝ㄟ^這以下幾點做到

壓縮css

css-loader 在webpack2里默認是沒有開啟壓縮的,***生成的css文件里有很多空格和tab,通過配置

css-loader?minimize參數可以開啟壓縮輸出最小的css。css的壓縮實際是是通過cssnano實現(xiàn)的。

tree-shaking

tree-shaking 是指借助es6 import export 語法靜態(tài)性的特點來刪掉export但是沒有import過的東西。要讓tree-shaking工作需要注意以下幾點:

  • 配置babel讓它在編譯轉化es6代碼時不把import export轉換為cmd的module.export,配置如下:
 
 
 
  1. "presets": [
  2.     [
  3.       "es2015",
  4.       {
  5.         "modules": false
  6.       }
  7.     ]
  • 大多數分布到npm的庫里的代碼都是es5的,但是也有部分庫(redux,react-router等等)開始支持tree-shaking。這些庫發(fā)布到npm里的代碼即包含es5的又包含全采用了es6 import export 語法的代碼。

拿redux庫來說,npm下載到的目錄結構如下:

 
 
 
  1. ├── es
  2. │   └── utils
  3. ├── lib
  4. │   └── utils 

其中l(wèi)ib目錄里是編譯出的es5代碼,es目錄里是編譯出的采用import export 語法的es5代碼,在redux的package.json文件里有這兩個配置:

 
 
 
  1. main": "lib/index.js",
  2. "jsnext:main": "es/index.js", 

這是指這個庫的入口文件的位置,所以要讓webpack去讀取es目錄下的代碼需要使用jsnext:main字段配置的入口,要做到這點webpack需要這樣配置:

 
 
 
  1. module.exports = {
  2. resolve: {
  3.             mainFields: ['jsnext:main','main'],
  4.         }
  5. }; 

這會讓webpack先使用jsnext:main字段,在沒有時使用main字段。這樣就可以優(yōu)化支持tree-shaking的庫。

優(yōu)化 UglifyJsPlugin

webpack --optimize-minimize 選項會開啟 UglifyJsPlugin來壓縮輸出的js,但是默認的UglifyJsPlugin配置并沒有把代碼壓縮到最小輸出的js里還是有注釋和空格,需要覆蓋默認的配置:

 
 
 
  1. new UglifyJsPlugin({
  2.     // 最緊湊的輸出
  3.     beautify: false,
  4.     // 刪除所有的注釋
  5.     comments: false,
  6.     compress: {
  7.       // 在UglifyJs刪除沒有用到的代碼時不輸出警告  
  8.       warnings: false,
  9.       // 刪除所有的 `console` 語句
  10.       // 還可以兼容ie瀏覽器
  11.       drop_console: true,
  12.       // 內嵌定義了但是只用到一次的變量
  13.       collapse_vars: true,
  14.       // 提取出出現(xiàn)多次但是沒有定義成變量去引用的靜態(tài)值
  15.       reduce_vars: true,
  16.     }
  17. }) 

定義環(huán)境變量 NODE_ENV=production

很多庫里(比如react)有部分代碼是這樣的:

 
 
 
  1. if(process.env.NODE_ENV !== 'production'){
  2. // 不是生產環(huán)境才需要用到的代碼,比如控制臺里看到的警告    

在環(huán)境變量 NODE_ENV 等于 production 的時候UglifyJs會認為if語句里的是死代碼在壓縮代碼時刪掉。

使用 CommonsChunkPlugin 抽取公共代碼

CommonsChunkPlugin可以提取出多個代碼塊都依賴的模塊形成一個單獨的模塊。要發(fā)揮CommonsChunkPlugin的作用還需要瀏覽器緩存機制的配合。在應用有多個頁面的場景下提取出所有頁面公共的代碼減少單個頁面的代碼,在不同頁面之間切換時所有頁面公共的代碼之前被加載過而不必重新加載。這個方法可以非常有效的提升應用性能。

在生產環(huán)境按照文件內容md5打hash

webpack編譯在生產環(huán)境出來的js、css、圖片、字體這些文件應該放到CDN上,再根據文件內容的md5命名文件,利用緩存機制用戶只需要加載一次,第二次加載時就直接訪問緩存。如果你之后有修改就會為對應的文件生產新的md5值。做到以上你需要這樣配置:

 
 
 
  1. {
  2.   output: {
  3.     publicPath: CND_URL,
  4.     filename: '[name]_[chunkhash].js',
  5.   },

知道以上原理后我們還可以進一步優(yōu)化:利用CommonsChunkPlugin提取出使用頁面都依賴的基礎運行環(huán)境。比如對于最常見的react體系你可以抽出基礎庫react react-dom redux react-redux到一個單獨的文件而不是和其它文件放在一起打包為一個文件,這樣做的好處是只要你不升級他們的版本這個文件永遠不會被刷新。如果你把這些基礎庫和業(yè)務代碼打包在一個文件里每次改動業(yè)務代碼都會導致瀏覽器重復下載這些包含基礎庫的代碼。以上的配置為:

 
 
 
  1. // vender.js 文件抽離基礎庫到單獨的一個文件里防止跟隨業(yè)務代碼被刷新
  2. // 所有頁面都依賴的第三方庫
  3. // react基礎
  4. import 'react';
  5. import 'react-dom';
  6. import 'react-redux';
  7. // redux基礎
  8. import 'redux';
  9. import 'redux-thunk'; 
 
 
 
  1. // webpack配置
  2. {
  3.   entry: {
  4.     vendor: './path/to/vendor.js',
  5.   },

DedupePlugin 和 OccurrenceOrderPlugin

在webpack1里經常會使用 DedupePlugin 插件來消除重復的模塊以及使用 OccurrenceOrderPlugin 插件讓被依賴次數更高的模塊靠前分到更小的id 來達到輸出更少的代碼,在webpack2里這些已經這兩個插件已經被移除了因為這些功能已經被內置了。

除了壓縮文本代碼外還可以:

  • 用imagemin-webpack-plugin 壓縮圖片
  • 用webpack-spritesmith 合并雪碧圖
  • 對于支持es6的js運行環(huán)境使用babili

以上優(yōu)化點只需要在構建用于生產環(huán)境代碼的時候才使用,在開發(fā)環(huán)境時***關閉因為它們很耗時。

優(yōu)化開發(fā)體驗

優(yōu)化開發(fā)體驗主要從更快的構建和更方便的功能入手。

更快的構建

縮小文件搜索范圍

webpack的resolve.modules配置模塊庫(通常是指node_modules)所在的位置,在js里出現(xiàn)import 'redux'這樣不是相對也不是絕對路徑的寫法時會去node_modules目錄下找。但是默認的配置會采用向上遞歸搜索的方式去尋找node_modules,但通常項目目錄里只有一個node_modules在項目根目錄,為了減少搜索我們直接寫明node_modules的全路徑:

 
 
 
  1. module.exports = {
  2.     resolve: {
  3.         modules: [path.resolve(__dirname, 'node_modules')]
  4.     }
  5. }; 

除此之外webpack配置loader時也可以縮小文件搜索范圍。

  • loader的test正則表達式也應該盡可能的簡單,比如在你的項目里只有.js文件時就不要把test寫成/\.jsx?$/
  • loader使用include***只需要處理的文件,比如babel-loader的這兩個配置:

只對項目目錄下src目錄里的代碼進行babel編譯

 
 
 
  1. {
  2.     test: /\.js$/,
  3.     loader: 'babel-loader',
  4.     include: path.resolve(__dirname, 'src')

項目目錄下的所有js都會進行babel編譯,包括龐大的node_modules下的js

 
 
 
  1. {
  2.     test: /\.js$/,
  3.     loader: 'babel-loader'

開啟 babel-loader 緩存

babel編譯過程很耗時,好在babel-loader提供緩存編譯結果選項,在重啟webpack時不需要創(chuàng)新編譯而是復用緩存結果減少編譯流程。babel-loader緩存機制默認是關閉的,打開的配置如下:

 
 
 
  1. module.exports = {
  2.     module: {
  3.          loaders: [{
  4.                 test: /\.js$/,
  5.                 loader: 'babel-loader?cacheDirectory',
  6.          }]
  7.   }
  8. }; 

使用 alias

resolve.alias 配置路徑映射。

發(fā)布到npm的庫大多數都包含兩個目錄,一個是放著cmd模塊化的lib目錄,一個是把所有文件合成一個文件的dist目錄,多數的入口文件是指向lib里面下的。

默認情況下webpack會去讀lib目錄下的入口文件再去遞歸加載其它依賴的文件這個過程很耗時,alias配置可以讓webpack直接使用dist目錄的整體文件減少文件遞歸解析。配置如下:

 
 
 
  1. module.exports = {
  2.   resolve: {
  3.     alias: {
  4.       'moment': 'moment/min/moment.min.js',
  5.       'react': 'react/dist/react.js',
  6.       'react-dom': 'react-dom/dist/react-dom.js'
  7.     }
  8.   }
  9. }; 

使用 noParse

module.noParse 配置哪些文件可以脫離webpack的解析。

有些庫是自成一體不依賴其他庫的沒有使用模塊化的,比如jquey、momentjs、chart.js,要使用它們必須整體全部引入。

webpack是模塊化打包工具完全沒有必要去解析這些文件的依賴,因為它們都不依賴其它文件體積也很龐大,要忽略它們配置如下:

 
 
 
  1. module.exports = {
  2.   module: {
  3.     noParse: /node_modules\/(jquey|moment|chart\.js)/
  4.   }
  5. }; 

除此以外還有很多可以加速的方法:

  • 使用happypack多進程并行構建
  • 使用DllPlugin復用模塊

更方便的功能

模塊熱替換

模塊熱替換是指在開發(fā)的過程中修改代碼后不用刷新頁面直接把變化的模塊替換到老模塊讓頁面呈現(xiàn)出***的效果。

webpack-dev-server內置模塊熱替換,配置起來也很方便,下面以react應用為例,步驟如下:

  • 在啟動webpack-dev-server的時候帶上--hot參數開啟模塊熱替換,在開啟--hot后針對css的變化是會自動熱替換的,但是js涉及到復雜的邏輯還需要進一步配置。
  • 配置頁面入口文件
 
 
 
  1. import App from './app';
  2.  
  3. function run(){
  4. render(,document.getElementById('app'));
  5. }
  6. run();
  7.  
  8. // 只在開發(fā)模式下配置模塊熱替換
  9. if (process.env.NODE_ENV !== 'production') {
  10.   module.hot.accept('./app', run);

當./app發(fā)生變化或者當./app依賴的文件發(fā)生變化時會把./app編譯成一個模塊去替換老的,替換完畢后重新執(zhí)行run函數渲染出***的效果。

自動生成html

webpack只做了資源打包的工作還缺少把這些加載到html里運行的功能,在龐大的app里手寫html去加載這些資源是很繁瑣易錯的,我們需要自動正確的加載打包出的資源。

webpack原生不支持這個功能于是我做了一個插件 web-webpack-plugin

具體使用點開鏈接看詳細文檔,使用大概如下:

demo(https://github.com/gwuhaolin/web-webpack-plugin/tree/master/demo/out-html)

webpack配置

 
 
 
  1. module.exports = {
  2.     entry: {
  3.         A: './a',
  4.         B: './b',
  5.     },
  6.     plugins: [
  7.         new WebPlugin({
  8.             // 輸出的html文件名稱,必填,注意不要重名,重名會覆蓋相互文件。
  9.             filename: 'index.html',
  10.             // 該html文件依賴的entry,必須是一個數組。依賴的資源的注入順序按照數組的順序。
  11.             requires: ['A', 'B'],
  12.         }),
  13.     ]
  14. }; 

將會輸出一個index.html文件,這個文件將會自動引入 entry A 和 B 生成的js文件,

輸出的html:

 
 
 
  1.     
  2.  

輸出的目錄結構

 
 
 
  1. ├── A.js
  2. ├── B.js
  3. └── index.html 

管理多頁面

雖然webpack適用于單頁應用,但復雜的系統(tǒng)經常是由多個單頁應用組成,每個頁面一個功能模塊。webpack給出了js打包方案但缺少管理多個頁面的功能。 web-webpack-plugin的AutoWebPlugin會自動的為你的系統(tǒng)里每個單頁應用生成一個html入口頁,這個入口會自動的注入當前單頁應用依賴的資源,使用它你只需如下幾行代碼:

 
 
 
  1. plugins: [
  2.     // ./src/pages/ 代表存放所有頁面的根目錄,這個目錄下的每一個目錄被看著是一個單頁應用
  3.     // 會為里面的每一個目錄生成一個html入口
  4.     new AutoWebPlugin('./src/pages/', {
  5.       //使用單頁應用的html模版文件,這里你可以自定義配置
  6.       template: './src/assets/template.html',
  7.     }),
  8.   ], 

查看web-webpack-plugin的文檔了解更多

分析輸出結果

如果你對當前的配置輸出或者構建速度不滿意,webpack有一個工具叫做webpack analyze 以可視化的方式直觀的分析構建,來進一步優(yōu)化構建結果和速度。要使用它你需要在執(zhí)行webpack的時候帶上--json --profile2個參數,這代表讓webpack把構建結果以json輸出并帶上構建性能信息,使用如下:

 
 
 
  1. webpack --json --profile > stats.json

會生產一個stats.json文件,再打開webpack analyze 上傳這個文件開始分析。

***附上這篇文章所講到的webpack整體的配置,分為開發(fā)環(huán)境的webpack.config.js和生產環(huán)境的webpack-dist.config.js


當前題目:webpack2終極優(yōu)化
分享鏈接:http://www.dlmjj.cn/article/djdchcp.html