1. 程式人生 > >webpack + react 優化:縮小js包體積

webpack + react 優化:縮小js包體積

一,前言

學校這邊的專案剛組建好開發團隊,前一段時間都在考慮如何前後端分離,如何多人協作開發的問題,恰好上一週陪女朋友去承德寫生,能暫時放下工作和學校的事物,有了更多的思考時間。假期期間學習了webpack,並將前端程式碼進行了遷移,實現了前後端分離。

最近上線的時候發現打包壓縮後的js包達到了477k,首屏渲染時間高達4s,首屏渲染時間超過1.5s都是不能忍的,於是開始嘗試研究一下webpack,畢竟只看了幾個小時就拿來用了。

劇透,劇透,後面優化到284k,首屏渲染1.5s-2s。

這個時候想起以前boss和我聊職業規劃的時候說過,“會用一項技術的人有很多,而出了問題懂得最大程度優化處理的人卻沒幾個”

,雖然他舉的例子是搜尋引擎優化,要高大上得多,但深入學習,積極對待的心態是一樣的。謝謝他的引導。

二,思路

前面囉嗦有點多,下面簡單說說這次優化的思路。要想解決問題,必先了解問題,我去看了打包後的js,發現了一些問題及優化點。

  1. js確實混淆壓縮了,可是裡面含有大量的開源庫的copyright資訊,可以去掉。

    (開源大牛們要相信我是尊重以及無敵崇拜你們的,為了效能暫時去掉這些資訊,後期會在產品上單開一個頁面說明自己用了哪些庫以及給出連結(Facebook和Instagram都這樣)

  2. 引入的React沒有切換到產品版本,React給出了下面的提示,良心!

    Warning: It looks like you’re using a minified copy of the development build of React. When deploying React apps to production, make sure to use the production build which skips development warnings and is faster. See

    http://facebook.github.io/react/downloads.html for more details.

  3. 之前將css也打包進js裡面了,因為css和js並行載入,所以可以將css分離出來,因為js遠大於css,所以首屏渲染時間絕大部分只受js下載時間影響,看圖:

    css,js下載時間

三,動手

①壓縮時去掉js所有註釋,包括copyright資訊。
在webpack.config.js檔案的plugins數組裡面新增及配置外掛即可。
關於uglify的更多配置,請點選這裡.

    new webpack.optimize.UglifyJsPlugin({
      output: {
        comments: false
, // remove all comments }, compress: { warnings: false } })

從477k 縮小到了408k,go ahead.

②將React切換到產品環境,參考如下:

同樣在plugins裡面新增:

    new webpack.DefinePlugin({
      'process.env': {
          NODE_ENV: JSON.stringify(process.env.NODE_ENV),
      },
    }),

這時候注意打包的時候要帶上node的環境設定,例如:

NODE_ENV=production webpack --config webpack.production.config.js --progress

從408k縮小到326k,還可以更進一步。

③分離css

先安裝webpack外掛:

npm install extract-text-webpack-plugin --save

在webpack配置檔案中使用外掛:

var ExtractTextPlugin = require("extract-text-webpack-plugin");

...

    loaders:[
      {
          test: /\.css$/,
          loader: ExtractTextPlugin.extract("style-loader", "css-loader")
      },
      {
          test: /\.less$/,
          loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")
      },

      ...

...

plugins: [
    ...

    new ExtractTextPlugin("bundle.css")
]

最後326k = 284k(js) + 37.6k(css).

附上完整的webpage配置檔案:

var webpack = require('webpack');
var path = require('path');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  entry: [
    path.resolve(__dirname, 'app/main.jsx')
  ],
  output: {
    path: __dirname + '/server/public',
    publicPath: '/',
    filename: './bundle.js'
  },
  module: {
    loaders:[
      {
          test: /\.css$/,
          loader: ExtractTextPlugin.extract("style-loader", "css-loader")
      },
      {
          test: /\.less$/,
          loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")
      },
      { test: /\.(jpg|png)$/, loader: "url" },
      { test: /\.js[x]?$/, include: path.resolve(__dirname, 'app'), exclude:/node_modules/,loader: 'babel-loader' },
    ]
  },
  resolve: {
    extensions: ['', '.js', '.jsx'],
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      output: {
        comments: false,
      },
      compress: {
        warnings: false
      }
    }),
    new webpack.DefinePlugin({
      'process.env': {
          NODE_ENV: JSON.stringify(process.env.NODE_ENV),
      },
    }),
    new ExtractTextPlugin("bundle.css")
  ]
};

四,更進一步

1.5s-2s的首屏渲染時間還不理想,但學校的專案要求也不高,不過對自己的要求應該一如既往,後期會嘗試從下面幾個方向去優化,希望能有更多的實踐經驗和大家分享。

  1. 將js分離,不同頁面載入不同的js;
  2. 將React剝離出去,使用cdn;
  3. 既然用了React,可以嘗試後端渲染;

雖然還不完美,但是進步總是值得肯定的,一步步來吧。

2016-09-16更新

進一步優化: