談及現在欣欣向榮的前端圈,不只有各種框架百花齊放,如Vue, React, Angular等等,就打包工具而言,發展也是如火如荼,百家爭鳴;從早期的王者Browserify, Grunt,到後來贏得寶座的 Gulp, 以及獨樹一幟的 fis3, 以及下一代打包器 Rollup ;在 browserify,grunt,gulp,rollup,webpack 能夠一窺其中部分對比。在本文要探究的是,當前打包工具絕對霸者 Webpack。 javascript
cnpm install --save-dev webpack-bundle-analyzer
複製代碼
(2)webpack.config.js文件css
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
plugins: [new BundleAnalyzerPlugin()]
複製代碼
#####將node-modules模塊單獨打包前端
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, './node_modules')
) === 0
)
}
})
]
複製代碼
#####引入 DllPlugin 和 DllReferencePlugin DllPlugin 和 DllReferencePlugin 提供了以大幅度提升構建時間性能的方式拆分軟件包的方法。其中原理是,將特定的第三方NPM包模塊提早構建👌,而後經過頁面引入。這不只可以使得 vendor 文件能夠大幅度減少,同時,也極大的提升了構件速度。鑑於篇幅,具體用法可參見:webpack.dll.conf.js。 #####外部引入模塊(CDN) 現在前端開發,天然是使用ES6甚至更高版本,擼將起來才更嗨。但因爲瀏覽器兼容問題,仍得使用 babel 轉換。而這 babel-polyfill 也得引入以確保兼容;還好比項目開發中經常使用到的 moment, lodash等,都是挺大的存在,若是必須引入的話,即考慮外部引入之,再借助 externals 予以指定, webpack能夠處理使之不參與打包,而依舊能夠在代碼中經過CMD、AMD或者window/global全局的方式訪問。vue
// webpack 中予以指定,須要補充的是 externals 中:key 是 require 的包名,value 是全局的變量。
externals: {
// 'vue': 'Vue',
// 'lodash': '_',
'babel-polyfill': 'window'
}
//
<script src="//cdn.bootcss.com/autotrack/2.4.1/autotrack.js"></script>
<script src="//cdn.bootcss.com/babel-polyfill/7.0.0-alpha.15/polyfill.min.js"></script>
複製代碼
#####讓每一個第三包「引有所值」 肯定引入的必要性 前端發展到現在時期,假若項目採用了 MVVM 模式框架,數據雙向綁定,那麼像 jQuery 這般類庫,不能說沒有絲毫引入的必要,至少能夠說確實沒有引入的必要。對此,若是還有些顧慮,徹底能夠參考下 YOU MIGHT NOT NEED JQUERY;用原生寫幾行代碼就能夠解決的事兒,實在不易引入這麼個龐然大物,平添煩惱。 #####避免類庫引而不用 假若這類狀況發生,對整個打包體積,不只大並且虧。項目一旦大了,很難人爲保證每一個引入的類庫,都被有用到,尤爲是二次開發。因此工具的利用十分必要,強烈推薦類如 Eslint 這般工具,而且注入對應規則,對聲明卻未使用的代碼,給予強制提醒;這不只能夠有效的規避相似情形發生(也適用於普通變量的檢測),並且還能使得團隊代碼風格,儘量地保持類似;要知道代碼足夠遵照規則,也可以讓壓縮工具更有效壓縮代碼,一舉多得,何樂不爲? #####儘可能使用模塊化引入 若是說 jQuery 確實沒有引入必要,不少人會贊成;但對於 lodash 這類依賴的工具,並非全部人都會去造一發輪子的。然而全包引入 400kb 的體量,能否有讓你心肝一顫?幸虧的是,lodash 提供了模塊化的引入方式;可按需引入,快哉快哉:java
import { debounce } from 'lodash'
import { throttle } from 'lodash'
// 改爲以下寫法
import debounce from 'lodash/debounce'
import throttle from 'lodash/throttle'
複製代碼
擅懶如你的優秀程序員,是否也發現這樣寫頗爲麻煩?那麼恭喜你,這個問題已經被解決;lodash-webpack-plugin 和 babel-plugin-lodash 的存在(組合使用),便是解決這問題的。它可將全路徑引用的 lodash , 自動轉變爲模塊化按使用引入(以下例示);而且所需配置也十分簡單,就不在此贅述(舒適提示:當涉及些特殊方法時,尚需些留意)。node
// 引入組件,自動轉換
import _ from 'lodash'
_.debounce()
_.throttle()
複製代碼
額外補充的是,即使採用如上寫法,仍是不夠快捷,每一個用到的文件,都寫一遍 import,實在多有不便。更可取的是,將項目所需的方法,統一引入,按需添加,組建出本地 lodash 類庫,而後 export 給框架層(好比 Vue.prototype ),以便全局使用;詳情可參見:vue-modular-import-lodash。jquery
// helper 文件夾下 lodash,統一引入你須要的方法
import _ from 'lodash'
export default {
cloneDeep: _.cloneDeep,
debounce: _.debounce,
throttle: _.throttle,
size: _.size,
pick: _.pick,
isEmpty: _.isEmpty
}
// 注入到全局
import _ from '@helper/lodash.js'
Vue.prototype.$_ = _
複製代碼
####儘量引入更合適的包 做爲前端開發的你,想必知道有 momentjs 的存在(Parse, validate, manipulate, and display dates in javascript.);更多的是,你想必知道它很好用,然而它的體態卻十分豐滿(豐盈),沒念及此,是否有從新造輪子的衝動?SpaceTime: A lightweight way to manipulate, traverse, compare, and format dates and times across planet Earth。 具備與 monent 類似 api 的新類庫,其體積又相對小不少(固然,據觀察其靈活度略遜一籌);date-fns:現代JavaScript日期實用程序庫( Modern JavaScript date utility library ),如 lodash 同樣,可支持模塊化;知道這些或者更多的你,會如何選擇? #####按需異步加載模塊 關於前端開發優化,重要的一條是,儘量合併請求及資源,如經常使用的請求數據合併,壓縮合並 js,構造雪碧圖諸此等等(固然得適當,注意體積,過大不宜);但,同時也當因需制宜,根據須要去異步加載,避免無故就引入早成的浪費。webpack 也是內置對這方面的支持; 假如,你使用的是 Vue,將一個組件(以及其全部依賴)改成異步加載,所須要的只是把:webpack
import Foo from './Foo.vue'
複製代碼
改成以下寫法:git
const Foo = () => import('./Foo.vue')
複製代碼
#####生產環境,壓縮混淆並移除console 如此分割之時,該組件所依賴的其餘組件或其餘模塊,都會自動被分割進對應的 chunk 裏,實現異步加載,固然也支持把組件按組分塊,將同組中組件,打包在同個異步 chunk 中。如此可以很是有效的抑制 Javascript 包過大,同時也使得資源的利用更加合理化。 現代化中等規模以上的開發中,區分開發環境、測試環境和生產環境,並根據須要予以區別對待,已然成爲行業共識;可能的話,還會有預發佈環境。對待生產環境,壓縮混淆能夠頗有效的減少包的體積;同時,若是可以移除使用比較頻繁的 console,而不是簡單的替換爲空方法,也是精彩的一筆小優化。若是使用 UglifyJsPlugin 插件來壓縮代碼,加入以下配置,便可移除掉代碼中的 console:程序員
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_console: true,
pure_funcs: ['console.log']
},
sourceMap: false
})
複製代碼
#####Webpack3 新功能: Scope Hoisting 截止目前(17-08-06), Webpack 最新版本是 3.4.1;Webpack在 3.0 版本,提供了一個新的功能:Scope Hoisting,又譯做「做用域提高」。只需在配置文件中添加一個新的插件,就可讓 Webpack 打包出來的代碼文件更小、運行的更快:
module.exports = {
plugins: [
new webpack.optimize.ModuleConcatenationPlugin()
]
}
複製代碼
據悉這個 Scope Hoisting 與 Tree Shaking ,最初都是由 Rollup 實現的。在我的中實踐中,這個功能的注入,對打包體積雖有影響,卻不甚明顯,有興趣的盆友能夠試下;更對關於此功能訊息,可參見 Webpack 3 的新功能:Scope Hoisting。