關(guān)于webpack的react項(xiàng)目優(yōu)化

這幾天有空給自己寫的一個(gè)react小項(xiàng)目的webpack配置進(jìn)行優(yōu)化,在這里進(jìn)行一下總結(jié)。
項(xiàng)目地址:https://github.com/beiweiqiang/myh5

我把這個(gè)項(xiàng)目的開發(fā)環(huán)境和生產(chǎn)環(huán)境各寫了一份webpack.config舍肠,用一個(gè)總的 webpack.config.js 進(jìn)行switch:

// webpack.config.js
const webpackProduction = require('./webpack.prod.js');
const webpackDevelopment = require('./webpack.dev.js');


const isProduction = process.env.NODE_ENV === 'production';

process.noDeprecation = true;

module.exports = isProduction ? webpackProduction : webpackDevelopment;

對開發(fā)環(huán)境進(jìn)行判斷严衬,switch合適的webpack配置周瞎。

我們先說開發(fā)環(huán)境,因?yàn)槭莚eact項(xiàng)目崭参,開發(fā)環(huán)境用到了hmr,要用hmr款咖,在項(xiàng)目入口處的代碼還要進(jìn)行一定的配置何暮,下面是官方例子:

import React from 'react';
import ReactDOM from 'react-dom';

import { AppContainer } from 'react-hot-loader';
// AppContainer 是一個(gè) HMR 必須的包裹(wrapper)組件

import App from './components/App';

const render = (Component) => {
  ReactDOM.render(
    <AppContainer>
      <Component/>
    </AppContainer>,
    document.getElementById('root')
  );
};

render(App);

// 模塊熱替換的 API
if (module.hot) {
  module.hot.accept('./components/App', () => {
    render(App)
  });
}

這里我在開發(fā)過程中有一個(gè)bug,就是console上雖然說了 app up to date铐殃,但是chrome瀏覽器自身不會(huì)進(jìn)行自動(dòng)刷新海洼,經(jīng)過google以后得到解決方案。
把最后部分改成下面這樣就行:

// 模塊熱替換的 API
if (module.hot) {
  module.hot.accept();
}

說回開發(fā)環(huán)境下的webpack配置富腊,因?yàn)榇a有點(diǎn)長坏逢,所以就不貼在這里,可以參考我的項(xiàng)目webpack.dev.js 文件。
說幾個(gè)地方:

1

output: {
    path: path.resolve(__dirname, 'client', 'dist'),
    // filename: '[name].[chunkhash].js',
    filename: '[name].js',
    publicPath: '/',
  }

這里并沒有像生產(chǎn)環(huán)境下的webpack配置 (下面會(huì)介紹) 一樣給文件加上hash值是整,因?yàn)橛?jì)算這個(gè)hash會(huì)耗費(fèi)時(shí)間俯树,開發(fā)環(huán)境講究構(gòu)建速度要快,所以不需要這個(gè)hash值贰盗。

2
devtool: 'inline-source-map' 開啟 source-map

3

devServer: {
    historyApiFallback: true,

    // Inline mode is recommended when using Hot Module Replacement.
    inline: true,
    open: true,
    hot: true,
    overlay: {
      errors: true,
      warnings: true,
    },
    watchOptions: {
      aggregateTimeout: 300,
      poll: 1000,
    },
    // contentBase: path.resolve(__dirname, 'client', 'dist'),
    contentBase: '/',
    // match the output path

    publicPath: '/',
    // match the output `publicPath`

    port: 8080,
    proxy: {
      '/**': {
        target: 'http://localhost:3000',
        secure: false,
        changeOrigin: true,
      },
    },
  },

open: true 會(huì)在命令執(zhí)行時(shí)自動(dòng)打開頁面许饿,contentBase: '/' 資源文件放置處,這里講一下 proxy:
因?yàn)槲业捻?xiàng)目有自己的后臺(tái)舵盈,用nodejs寫的陋率,運(yùn)行在3000端口,但是webpack-dev-server也有一個(gè)自己的運(yùn)行后臺(tái)秽晚,運(yùn)行在 port: 8080 端口瓦糟,那該怎么辦?
這時(shí)我們就需要進(jìn)行代理proxy:
host 默認(rèn)是 localhost赴蝇,對8080端口下的服務(wù)器進(jìn)行請求菩浙,會(huì)自動(dòng)把相同的請求轉(zhuǎn)到3000下,比如我們請求 localhost:8080/api句伶,代理以后會(huì)自動(dòng)請求 localhost:3000/api劲蜻,我這里是把所以請求都轉(zhuǎn)到端口3000下,也可以只進(jìn)行 /api 代理:

'/api': {
    target: 'http://localhost:3000/api',
    secure: false,
    changeOrigin: true,
  },

4
關(guān)于 plugins:

plugins: [
  // 除了自己寫的代碼考余,將其他的modules都bundle成一個(gè)vendor文件
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    minChunks(module) {
      // 該配置假定你引入的 vendor 存在于 node_modules 目錄中
      return module.context && module.context.indexOf('node_modules') !== -1;
    },
  }),
  // 生產(chǎn)manifest文件先嬉,用于在html模板中插入script
  new webpack.optimize.CommonsChunkPlugin({
    name: 'manifest',
    minChunks: Infinity,
  }),
  // 生成插入script后的 html 文件
  new HtmlWebpackPlugin({
    template: path.resolve(__dirname, 'server', 'static', 'index_template.html'),
    chunksSortMode: 'dependency',
    minify: {
      collapseWhitespace: true,
      removeComments: true,
    },
  }),

  // HMR
  new webpack.HotModuleReplacementPlugin(),
  // enable HMR globally

  new webpack.NamedModulesPlugin(),
  // prints more readable module names in the browser console on HMR updates
],

說到生成環(huán)境的webpack配置,可以參考我的項(xiàng)目webpack.prod.js 文件楚堤。

生產(chǎn)環(huán)境下我們就要兼顧很多方面疫蔓,比如服務(wù)端發(fā)送到前端的文件要小,保證加載速度快身冬;關(guān)于modules方面的代碼我們很少會(huì)去修改衅胀,所以可以在前端進(jìn)行緩存起來。

1

output: {
  path: path.resolve(__dirname, 'client', 'dist'),
  filename: '[name].[chunkhash].js',
  publicPath: '/',
},

這里對文件名進(jìn)行了hash處理酥筝,瀏覽器會(huì)自動(dòng)緩存js文件滚躯,如果收到的文件的文件名是一樣的,瀏覽器可能不會(huì)進(jìn)行自動(dòng)更新樱哼,所以我們加上hash值哀九,保證每一次更新以后的文件名不同,從而讓瀏覽器再次請求資源搅幅。
而那些modules代碼基本是不會(huì)變的阅束,所以保證它們的hash值不變,在瀏覽器處緩存起來茄唐。

2
plugins

plugins: [
  // 將node_modules里的依賴整合成一個(gè)vendor
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    minChunks(module) {
      // 該配置假定你引入的 vendor 存在于 node_modules 目錄中
      return module.context && module.context.indexOf('node_modules') !== -1;
    },
  }),

  new webpack.optimize.CommonsChunkPlugin({
    name: 'manifest',
  }),

  // 根據(jù)manifest生成插入script后的html
  new HtmlWebpackPlugin({
    template: path.resolve(__dirname, 'server', 'static', 'index_template.html'),
    chunksSortMode: 'dependency',
    minify: {
      collapseWhitespace: true,
      removeComments: true,
    },
  }),

  // 將js文件壓縮成gz
  new CompressionPlugin(),

  // 允許創(chuàng)建一個(gè)在編譯時(shí)可以配置的全局常量
  new webpack.DefinePlugin({
    'process.env': {
      NODE_ENV: '"production"',
    },
  }),

  // 壓縮
  new webpack.optimize.UglifyJsPlugin({
    compress: {
      warnings: false,
    },
    // sourceMap: true,
  }),
  new WebpackMd5Hash(),
  new webpack.NoEmitOnErrorsPlugin(),
],

除了將文件進(jìn)行 uglify 以外息裸,這里還將文件進(jìn)行g(shù)z壓縮 new CompressionPlugin()蝇更。
在后端部分還要加上一些代碼:

// 獲取js文件時(shí)選擇gz壓縮文件
app.get('*.js', (req, res, next) => {
  req.url = req.url + '.gz';
  res.set('Content-Encoding', 'gzip');
  next();
});

以上。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呼盆,一起剝皮案震驚了整個(gè)濱河市年扩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌访圃,老刑警劉巖厨幻,帶你破解...
    沈念sama閱讀 212,599評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異腿时,居然都是意外死亡况脆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評論 3 385
  • 文/潘曉璐 我一進(jìn)店門批糟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來格了,“玉大人,你說我怎么就攤上這事徽鼎∈⒛” “怎么了?”我有些...
    開封第一講書人閱讀 158,084評論 0 348
  • 文/不壞的土叔 我叫張陵否淤,是天一觀的道長悄但。 經(jīng)常有香客問我,道長叹括,這世上最難降的妖魔是什么算墨? 我笑而不...
    開封第一講書人閱讀 56,708評論 1 284
  • 正文 為了忘掉前任宵荒,我火速辦了婚禮汁雷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘报咳。我一直安慰自己侠讯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評論 6 386
  • 文/花漫 我一把揭開白布暑刃。 她就那樣靜靜地躺著厢漩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪岩臣。 梳的紋絲不亂的頭發(fā)上溜嗜,一...
    開封第一講書人閱讀 50,021評論 1 291
  • 那天,我揣著相機(jī)與錄音架谎,去河邊找鬼炸宵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛谷扣,可吹牛的內(nèi)容都是我干的土全。 我是一名探鬼主播,決...
    沈念sama閱讀 39,120評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼裹匙!你這毒婦竟也來了瑞凑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,866評論 0 268
  • 序言:老撾萬榮一對情侶失蹤概页,失蹤者是張志新(化名)和其女友劉穎籽御,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惰匙,經(jīng)...
    沈念sama閱讀 44,308評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡篱蝇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了徽曲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片零截。...
    茶點(diǎn)故事閱讀 38,768評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖秃臣,靈堂內(nèi)的尸體忽然破棺而出涧衙,到底是詐尸還是另有隱情,我是刑警寧澤奥此,帶...
    沈念sama閱讀 34,461評論 4 333
  • 正文 年R本政府宣布弧哎,位于F島的核電站,受9級特大地震影響稚虎,放射性物質(zhì)發(fā)生泄漏撤嫩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評論 3 317
  • 文/蒙蒙 一蠢终、第九天 我趴在偏房一處隱蔽的房頂上張望序攘。 院中可真熱鬧,春花似錦寻拂、人聲如沸程奠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瞄沙。三九已至,卻和暖如春慌核,著一層夾襖步出監(jiān)牢的瞬間距境,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評論 1 267
  • 我被黑心中介騙來泰國打工垮卓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留垫桂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,571評論 2 362
  • 正文 我出身青樓扒接,卻偏偏與公主長得像伪货,于是被迫代替她去往敵國和親们衙。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 在現(xiàn)在的前端開發(fā)中碱呼,前后端分離蒙挑、模塊化開發(fā)、版本控制愚臀、文件合并與壓縮忆蚀、mock數(shù)據(jù)等等一些原本后端的思想開始...
    Charlot閱讀 5,433評論 1 32
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)姑裂,斷路器馋袜,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • 構(gòu)建一個(gè)小項(xiàng)目——FlyBird,學(xué)習(xí)webpack和react舶斧。(本文成文于2017/2/25) 從webpac...
    布蕾布蕾閱讀 16,810評論 31 98
  • 最近在學(xué)習(xí) Webpack,網(wǎng)上大多數(shù)入門教程都是基于 Webpack 1.x 版本的,我學(xué)習(xí) Webpack 的...
    My_Oh_My閱讀 8,173評論 40 247
  • 寫在開頭 先說說為什么要寫這篇文章, 最初的原因是組里的小朋友們看了webpack文檔后, 表情都是這樣的: (摘...
    Lefter閱讀 5,279評論 4 31