webpack 把咱們全部的文件都打包成一個 JS 文件,這樣即便你是小項目,打包後的文件也會很是大。下面就來說下如何從多個方面進行優化。css
剛開始用 webpack 的時候,開發環境和生產環境用的是同一個 webpack 配置文件,致使生產環境打包的 JS 文件包含了一大堆不必的插件,好比 HotModuleReplacementPlugin
, NoErrorsPlugin
... 這時候無論用什麼優化方式,都沒多大效果。因此,若是你打包後的文件很是大的話,先檢查下是否是包含了這些插件。html
像 react 這個庫的核心代碼就有 627 KB,這樣和咱們的源代碼放在一塊兒打包,體積確定會很大。因此能夠在 webpack 中設置前端
{ entry: { bundle: 'app' vendor: ['react'] } plugins: { new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js') } }
這樣打包以後就會多出一個 vendor.js
文件,以後在引入咱們本身的代碼以前,都要先引入這個文件。好比在 index.html
中react
<script src="/build/vendor.js"></script> <script src="/build/bundle.js"></script>
除了這種方式以外,還能夠經過引用外部文件的方式引入第三方庫,好比像下面的配置webpack
{ externals: { 'react': 'React' } }
externals
對象的 key 是給 require
時用的,好比 require('react')
,對象的 value 表示的是如何在 global 中訪問到該對象,這裏是 window.React
。這時候 index.html
就變成下面這樣git
<script src="//cdn.bootcss.com/react/0.14.7/react.min.js"></script> <script src="/build/bundle.js"></script>
webpack 自帶了一個壓縮插件 UglifyJsPlugin,只須要在配置文件中引入便可。es6
{ plugins: [ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) ] }
加入了這個插件以後,編譯的速度會明顯變慢,因此通常只在生產環境啓用。github
另外,服務器端還能夠開啓 gzip 壓縮,優化的效果更明顯。web
什麼是代碼分割呢?咱們知道,通常加載一個網頁都會把所有的 js 代碼都加載下來。可是對於 web app 來講,咱們更想要的是隻加載當前 UI 的代碼,沒有點擊的部分不加載。瀏覽器
看起來好像挺麻煩,可是經過 webpack 的 code split 以及配合 react router 就能夠方便實現。具體的例子能夠看下 react router 的官方示例 huge apps。不過這裏仍是講下以前配置踩過的坑。
code split
是不支持 ES6 的模塊系統的,因此在導入和導出的時候千萬要注意,特別是導出。若是你導出組件的時候用 ES6 的方式,這時候無論導入是用 CommomJs 仍是 AMD,都會失敗,並且還不會報錯!
固然會踩到這個坑也是由於我剛剛纔用 NodeJS,並且一入門就是用 ES6 的風格。除了這個以外,還有一點也要注意,在生產環境的 webpack 配置文件中,要加上 publicPath
output: { path: xxx, publicPath: yyy, filename: 'bundle.js' }
否則的話,webpack 在加載 chunk 的時候,路徑會出錯。
開始這個小節以前,能夠先看下大神的一篇文章:大公司裏怎樣開發和部署前端代碼。
對於靜態文件,第一次獲取以後,文件內容沒改變的話,瀏覽器直接讀取緩存文件便可。那若是緩存設置過長,文件要更新怎麼辦呢?嗯,以文件內容的 MD5 做爲文件名就是一個不錯的解決方案。來看下用 webpack 應該怎樣實現
output: { path: xxx, publicPath: yyy, filename: '[name]-[chunkhash:6].js' }
打包後的文件名加入了 hash 值
const bundler = webpack(config) bundler.run((err, stats) => { let assets = stats.toJson().assets let name for (let i = 0; i < assets.length; i++) { if (assets[i].name.startsWith('main')) { name = assets[i].name break } } fs.stat(config.buildTemplatePath, (err, stats) => { if (err) { fs.mkdirSync(config.buildTemplatePath) } writeTemplate(name) }) })
手動調用 webpack 的 API,獲取打包後的文件名,經過 writeTemplate
更新 html 代碼。完整代碼猛戳 gitst。
這樣子,咱們就能夠把文件的緩存設置得很長,而不用擔憂更新問題。
轉載自:http://www.jianshu.com/p/a64735eb0e2b