Webpack 代碼分離

Webpack 代碼分離

:pushpin: 提示:

  1. 版本問題

    本文基于 webpack 2.x 版本孽查。webpack 2.x 相比 webpack 1.x 有重大改變。所以缔恳,如果你的項目中已使用了 webpack 1.x ,本教程的示例將不適用,請慎重典勇。

    如果鐵了心要升級 webpack ,請參考 webpack 官方文檔 - 從 v1 遷移到 v2

  1. 閱讀建議

    閱讀本文前叮趴,建議先閱讀 Webpack 概念 割笙。

代碼分離是 webpack 中最引人注目的特性之一。

你可以把你的代碼分離到不同的 bundle 中,然后你就可以去按需加載這些文件伤溉。

總的來說般码, webpack 分離可以分為兩類:

  • 資源分離
  • 代碼分離

資源分離(Resource Splitting)

對第三方庫(vendor) 和 CSS 進(jìn)行代碼分離,這些方式有助于實現(xiàn)緩存和并行加載乱顾。

分離 CSS(CSS Splitting)

你可能也想將你的樣式代碼分離到單獨(dú)的 bundle 中板祝,以此使其獨(dú)立于應(yīng)用程序邏輯。這加強(qiáng)了樣式的可緩存性走净,并且使得瀏覽器能夠并行加載應(yīng)用程序代碼中的樣式文件券时,避免 FOUC 問題 (無樣式內(nèi)容造成的閃爍)。

安裝 ExtractTextWebpackPlugin 如下

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

webpack.config.js 中需要按下面進(jìn)行配置:

const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {

  // 關(guān)于模塊配置
  module: {

    // 模塊規(guī)則(配置 loader伏伯、解析器等選項)
    rules: [
      {
        // css 加載
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          use: "css-loader"
        })
      }
    ]
  },

  // 附加插件列表
  plugins: [
    // 將樣式文件獨(dú)立打包
    new ExtractTextPlugin("styles.css")
  ]
};

?:flashlight: 示例DEMO09: (DEMO / SOURCE)

分離第三方庫(Vendor Code Splitting)

一個典型的應(yīng)用程序橘洞,由于框架/功能性需求,會依賴于許多第三方庫的代碼舵鳞。不同于應(yīng)用程序代碼震檩,這些第三方庫代碼不會頻繁修改。

如果我們將這些庫(library)中的代碼蜓堕,保留在與應(yīng)用程序代碼相獨(dú)立的 bundle 中抛虏,我們就可以利用瀏覽器緩存機(jī)制,把這些文件長時間地緩存在用戶機(jī)器上套才。

為了完成這個目標(biāo)迂猴,不管應(yīng)用程序代碼如何變化,vendor 文件名中的 hash 部分必須保持不變背伴。學(xué)習(xí)如何使用 CommonsChunkPlugin 分離 vendor/library 代碼沸毁。

webpack.config.js

const webpack = require('webpack');

module.exports = {
  // 這里應(yīng)用程序開始執(zhí)行
  // webpack 開始打包
  // 本例中 entry 為多入口
  entry: {
    main: "./app/index",
    vendor: "react"
  },
  
  // webpack 如何輸出結(jié)果的相關(guān)選項
  output: {
    // 所有輸出文件的目標(biāo)路徑
    // 必須是絕對路徑(使用 Node.js 的 path 模塊)
    path: path.resolve(__dirname, "dist"),

    // 「入口分塊(entry chunk)」的文件名模板(出口分塊?)
    // filename: "bundle.min.js",
    // filename: "[name].js", // 用于多個入口點(diǎn)(entry point)(出口點(diǎn)傻寂?)
    // filename: "[chunkhash].js", // 用于長效緩存
    filename: "[name].[chunkhash:8].js", // 用于長效緩存
  },

  // 附加插件列表
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor" // 指定公共 bundle 的名字息尺。
    })
  ]
};

在上面的配置中,

  1. entry 屬性中疾掰,將 react 指定為一個獨(dú)立的入口 vendor搂誉;
  2. 然后,在 output 屬性中静檬,將 filename 指定為 [name].[chunkhash:8].js炭懊,這表示輸出文件的文件名樣式。
  3. 最后在 plugins 列表中引入 CommonsChunkPlugin 插件拂檩,用來指定 bundle 侮腹。

執(zhí)行 webpack 命令后,webpack 會生成 2 個 bundle 文件稻励,形式如:

main.bef8f974.js
vendor.2f1bd4c8.js

?:flashlight: 示例DEMO10: (DEMO / SOURCE)

代碼按需分離(On Demand Code Splitting)

雖然前面幾類資源分離父阻,需要用戶預(yù)先在配置中指定分離模塊,但也可以在應(yīng)用程序代碼中創(chuàng)建動態(tài)分離模塊。

這可以用于更細(xì)粒度的代碼塊加矛,例如钠署,根據(jù)我們的應(yīng)用程序路由,或根據(jù)用戶行為預(yù)測荒椭。這可以使用戶按照實際需要加載非必要資源谐鼎。

前一節(jié),我們了解了 webpack 可以將資源拆分為bundle趣惠。接下來狸棍,我們要學(xué)習(xí)如何異步加載。例如味悄,這允許首先提供最低限度的引導(dǎo) bundle草戈,并在稍后再異步地加載其他功能。

webpack 支持兩種相似的技術(shù)實現(xiàn)此目的:使用 import() (推薦侍瑟,ECMAScript 提案) 和 require.ensure() (遺留唐片,webpack 特定)。本文只介紹官方推薦的 import() 方式涨颜。

ES2015 loader 規(guī)范定義了 import() 作為一種在運(yùn)行時(runtime)動態(tài)載入 ES2015 模塊的方法费韭。

webpack 把 import() 作為一個分離點(diǎn)(split-point),并把引入的模塊作為一個單獨(dú)的 chunk庭瑰。 import() 將模塊名字作為參數(shù)并返回一個 Promoise 對象星持,即 import(name) -> Promise

配合 Babel 使用

如果你想要在 Babel 中使用 import,但是由于 import() 還是屬于 Stage 3 的特性弹灭,所以你需要安裝/添加 syntax-dynamic-import 插件來避免 parser 報錯督暂。在草案正式成為規(guī)范后,就不再需要這個插件了穷吮。

例:

我們來定義一個 Clock 組件逻翁,動態(tài)引入 moment 庫。

首先捡鱼,安裝 moment 庫八回。

$ npm install --save-dev moment

JavaScript 代碼:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = { date: new Date().toLocaleDateString() };
    this.click = this.click.bind(this);
  }

  click() {
    // 動態(tài)引入import()
    import('moment')
      .then(moment => moment().format("MMMM Do YYYY, h:mm:ss a"))
      .then(str => this.setState({date:str}))
      .catch(err => console.log("Failed to load moment", err));
  }

  render() {
    return (
      <div>
        <h2>It is {this.state.date}.</h2>
        <p onClick={this.click}>Click here to changing the time.</p>
      </div>
    );
  }
}

webpack.config.js

// 關(guān)于模塊配置
module: {

  // 模塊規(guī)則(配置 loader、解析器等選項)
  rules: [
    {
      // 語義解釋器堰汉,將 js/jsx 文件中的 es2015/react 語法自動轉(zhuǎn)為瀏覽器可識別的 Javascript 語法
      test: /\.jsx?$/,
      include: path.resolve(__dirname, "app"),

      // 應(yīng)該應(yīng)用的 loader辽社,它相對上下文解析
      // 為了更清晰伟墙,`-loader` 后綴在 webpack 2 中不再是可選的
      // 查看 webpack 1 升級指南翘鸭。
      loader: "babel-loader",

      // loader 的可選項
      options: {
        presets: ["es2015", "react"],
        plugins: ['syntax-dynamic-import']
      },
    },
  ]
},

?:flashlight: 示例DEMO11: (DEMO / SOURCE)

Webpack 系列教程

歡迎閱讀其它內(nèi)容:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市戳葵,隨后出現(xiàn)的幾起案子就乓,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件生蚁,死亡現(xiàn)場離奇詭異噩翠,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)邦投,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門伤锚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人志衣,你說我怎么就攤上這事屯援。” “怎么了念脯?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵狞洋,是天一觀的道長。 經(jīng)常有香客問我绿店,道長吉懊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任假勿,我火速辦了婚禮借嗽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘转培。我一直安慰自己淹魄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布堡距。 她就那樣靜靜地躺著甲锡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪羽戒。 梳的紋絲不亂的頭發(fā)上缤沦,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機(jī)與錄音易稠,去河邊找鬼缸废。 笑死,一個胖子當(dāng)著我的面吹牛驶社,可吹牛的內(nèi)容都是我干的企量。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼亡电,長吁一口氣:“原來是場噩夢啊……” “哼届巩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起份乒,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤恕汇,失蹤者是張志新(化名)和其女友劉穎腕唧,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘾英,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡枣接,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了缺谴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片但惶。...
    茶點(diǎn)故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖湿蛔,靈堂內(nèi)的尸體忽然破棺而出榆骚,到底是詐尸還是另有隱情,我是刑警寧澤煌集,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布妓肢,位于F島的核電站,受9級特大地震影響苫纤,放射性物質(zhì)發(fā)生泄漏碉钠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一卷拘、第九天 我趴在偏房一處隱蔽的房頂上張望喊废。 院中可真熱鬧,春花似錦栗弟、人聲如沸污筷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓣蛀。三九已至,卻和暖如春雷厂,著一層夾襖步出監(jiān)牢的瞬間惋增,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工改鲫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诈皿,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓像棘,卻偏偏與公主長得像稽亏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子缕题,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評論 2 354

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

  • 目錄第1章 webpack簡介 11.1 webpack是什么截歉? 11.2 官網(wǎng)地址 21.3 為什么使用 web...
    lemonzoey閱讀 1,734評論 0 1
  • 一、明確概念 ◆ Code Splitting(代碼分離) Code Splitting 是 webpack 作為...
    一個笑點(diǎn)低的妹紙閱讀 1,875評論 0 0
  • 什么是webpack webpack是模塊打包機(jī)避除,是前端資源模塊化管理和打包工具怎披。可以將許多松散的模塊按照依賴和規(guī)...
    209bd3bc6844閱讀 1,370評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理瓶摆,服務(wù)發(fā)現(xiàn)凉逛,斷路器,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • 不久前我對星爺?shù)恼J(rèn)知依然停留在兒時群井,每當(dāng)想起他的電影總會忍不住哈哈大笑状飞,內(nèi)心好似有股清泉流過,洗凈所有的煩惱...
    隱形的葉子閱讀 207評論 0 0