91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

webpack代碼拆分的示例分析

發布時間:2021-08-02 11:41:19 來源:億速云 閱讀:92 作者:小新 欄目:web開發

這篇文章主要介紹webpack代碼拆分的示例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

如果利用 webpack 將項目中的所有代碼打包在一起,很多時候是不適用的,因為代碼中有些東西我們總是希望將其拆分出來。比如:

  1. 樣式表,希望利用 link 標簽引入

  2. 使用概率較低的模塊,希望后期需要的時候異步加載

  3. 框架代碼,希望能利用瀏覽器緩存下部分不易變動的代碼

下面是我在閱讀 webpack 的官方文檔時候,記錄的一些筆記,部分地方使用了自己的話來講,力圖讓它顯得更易懂。

按需加載拆分

webpack 可以幫助我們將代碼分成不同的邏輯塊,在需要的時候加載這些代碼。

使用 require.ensure() 來拆分代碼

require.ensure() 是一種使用 CommonJS 的形式來異步加載模塊的策略。在代碼中通過 require.ensure([<fileurl>]) 引用模塊,其使用方法如下:

require.ensure(dependencies: String[], callback: function(require), chunkName: String)

第一個參數指定依賴的模塊,第二個參數是一個函數,在這個函數里面你可以使用 require 來加載其他的模塊,webpack 會收集 ensure 中的依賴,將其打包在一個單獨的文件中,在后續用到的時候使用 jsonp 異步地加載進去。

require.ensure(['./a'], function(require){
  let b = require('./b');
  let a = require('./a');
  console.log(a+b)
});

以上代碼,a 和 b 會被打包在一起,在代碼中執行到這段代碼的時候,會異步地去加載,加載完成后執行函數里面的邏輯。

let a = require('./a');
require.ensure(['./a'], function(require){
  let b = require('./b');
  console.log(a+b)
});

如果這樣寫,那么 a 不會和 b 打包在一起,因為 a 已經被打包在主代碼中了。

require.ensure(['./c'], function(require){
  let a = require('./a');
  console.log(a)
});

require.ensure(['./c'], function(require){
  let b = require('./b');
  console.log(b)
});

以上代碼中兩個模塊都依賴了 c 模塊,這個時候會拆分出兩個模塊,其中都包含了 c 模塊,因為在實際運用中,以上兩個 require.ensure 的執行順序不確定,執行與否也不確定,因此需要將 c 模塊都打包進去。

require.ensure 還可以傳入第三個參數,這個參數用來指定打包的包名,對于上面這種情況,c 模塊被打包入了兩個包中,如果事先明確這兩個包都會被使用,那么不妨將這兩個包合并為一個,這樣就不會有 c 模塊被打包兩次的問題了,所以可以將 chunkName 指定為同一個名字。

require.ensure(['./c'], function(require){
  let a = require('./a');
  console.log(a)
}, 'd');

require.ensure(['./c'], function(require){
  let b = require('./b');
  console.log(b)
}, 'd');

ok,這樣以上兩個 require.ensure 拆出來的包就合并為同一個了。

CSS 拆分

開發者,可能希望能將工程中的所有引入的 CSS 拆分為單個文件,這樣可以利用緩存,且利用 CSS 和 JavaScript 并行加載,來加速 web 應用。

使用 css-loader

為了加載 css,這里需要用到 css-loader,配置方法如下:

module: {
  loaders: [{
    test: /\.css$/,
    exclude: /node_modules/,
    loader: 'css-loader'
  }]
}

這樣在代碼中就可以寫如下代碼:

let css = require('./main.css');
console.log('' + css);

通過 require 一個 css 得到其內容,當然了這里 require('./main.css') 實際得到的是一個對象,需要調用其 toString 方法將其轉換為字符串。在代碼中引用一段 css,這常常不是我們想要的。為此可以使用 style-loader 在代碼執行起來的時候,會將這些 css 插入到 style 標簽中,只是這里 css 還是存在于 js 中的,是后來動態插入到頁面中的:

module: {
  loaders: [{
    test: /\.css$/,
    exclude: /node_modules/,
    loader: 'style-loader!css-loader'
  }]
}

更多時候,是希望將 css 拆分為單個文件,然后使用 link 標簽嵌入到 html 中,CSS 和 JavaScript 可以并行加載,css 還可以被緩存下來。

使用 extract-text-webpack-plugin 來拆分 css

為了使用這個插件首先需要通過 npm 來安裝它:

npm i --save-dev extract-text-webpack-plugin

然后在 webpack 的配置文件中使用該插件:

var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = function () {
  return {
    entry: './index.js',
    output: {
      path: './build',
      filename: 'bundle.js'
    },
    module: {
      loaders: [{
        test: /\.css$/,
        exclude: /node_modules/,
        // 在 loader 中使用該插件
        loader: ExtractTextPlugin.extract('style-loader', 'css-loader')
      }]
    },
    plugins: [
      // 將其添加在插件中
      new ExtractTextPlugin({ filename: 'bundle.css', disable: false, allChunks: true })
    ]
  }
}

需要注意的是,對于 webpack1 和 webpack2 這個插件的配置方法是不同的,差別比較細微,詳情請看官方文檔 extract text plugin for webpack 2

拆分業務代碼與框架代碼

通常一個 web 應用都會引用若干第三方庫,這些第三方庫通常比較穩定不會經常變動,但是如果將業務代碼和框架代碼打包在了一起,這樣業務代碼每次變動打包得到的結果都會變動,及時只改變了一個字符,瀏覽器也無法利用緩存,必須全部重新加載。因此,何不將第三方庫單獨打包在一起呢?

這里舉個案例,一個 react 項目中使用了 react react-dom 這兩個包,我希望將他們打包在一起,將業務代碼打包在一起。

下面一步一步來:

1. 安裝 react 和 react-dom:

npm i react react-dom --save

2. 配置 entry,output 和 loader

先使用單入口,讓代碼工作起來。另外因為使用了 react 所以要使用 babel-loader 來加載 js

// webpack.config.js

module.exports = {
  entry: 'index.js',
  output: {
    path: 'build/',
    filname: '[name]@[chunkhash].js'
  },
  module:{
    loaders:[{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel'
    }]
  }
}

3. 編寫業務代碼

index.js:

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


var Hello = React.createClass({
  render: function() {
    return <div>Hello {this.props.name}</div>;
  }
});

ReactDOM.render(<Hello name={'world'} />, document.getElementById('app'));

index.html:

<div id="app"></div>
<!--entry 為一個字符串,這個 chunk 的名字會是 main, 因此這里引入 main.js -->
<script src="build/main.js"></script>

啟動 webpack-dev-server,打開瀏覽器這個時候應該能在頁面上看到 hello world,這說明工作正常。

4. 拆分框架代碼

為了拆分框架代碼,我們需要增加一個入口,在這個入口中要包含 react react-dom

module.exports = {
  entry: {
    main: 'index.js',
    vendor: ['react', 'react-dom']
  }
  //...
}

單單像上面這樣配置,打包后會得到 main.js 和 vendor.js,但會發現在 main.js 中依然包含了 react 和 react-dom 的代碼,這是因為指定了入口后,webpack 就會從入口文件開始講整個依賴打包進來,index.js 中引用了 react 和 react-dom 自然會被打包進去。要想達到之前所說的那個效果,還需要借助一個插件 —— CommonsChunkPlugin

5. 使用 CommonsChunkPlugin

這個插件的功能是將多個打包結果中公共的部分抽取出來,作為一個單獨的文件。它符合目前的場景,因為 main.js vendor.js 中存在一份公共的代碼,那就是 vendor.js 中的內容。(這個說法并不準確,這里只是指 react 和 react-dom 都被打包進了這兩個文件)

let webpack = require('webpack');

module.exports = {
  entry: {
    main: 'index.js',
    vendor: ['react', 'react-dom']
  },
  //...

  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor' // 指定一個希望作為公共包的入口
    })
  ]
}

再進行打包,這個時候會發現 main.js 中的代碼不在包含 react 的代碼了。看似實現了我們的需求,但真實應用下并沒有這么簡單,在實際項目中 js 腳本通常都會給添加一個 MD5 的 hash 在后面,形如 app@709d9850745a4c8ba1d4.js 這樣每次打包后,如果文件內容變了,后面的 hash 也會變動。就以上場景,會發現當我們修改了業務代碼后,得到的 hash 是不同的,因此每次都會得到兩個不同的打包結果。業務代碼改變了,拆分出來的框架包也變了,這顯然不符合初衷 —— 利用瀏覽器緩存。

這是因為 webpack 在打包的時候會產生一些運行時代碼,比如 __webpack_require__ webpackJsonp 等等,這些函數是用來幫助 webpack 完成模塊加載等功能的,業務代碼的改變會導致業務代碼打包后的 hash 值改變,而在 webpack 的運行時代碼中實際上是保存了打包后的結果的文件名的,因為它在異步加載模塊的時候需要用到。因此,下面需要做的是將 webpack 的運行時代碼拆分出來。

修改 plugins 如下,將 name 修改為 names,并增加一個 init 的包名,執行打包,會發現 webpack 的運行時代碼都被入該包內。

plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    names: ['vendor', 'init']
  })
]

這樣以來,修改了業務代碼后,vendor 因為只引用了 react 和 react-dom 因此,業務代碼的改變不會改變 vendor 這個包的內容,hash 也保持不變。但,也僅僅如此 如果你引用了其他模塊,webpack 收集依賴的時候會給每個模塊編一個號,引入其他模塊會導致模塊數改變,也就會導致編號改變,這個時候打包出來的 vendor 還是會改變。

以上是“webpack代碼拆分的示例分析”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

中山市| 社会| 随州市| 滨海县| 桓台县| 郧西县| 洪泽县| 图片| 偏关县| 宁远县| 林西县| 贞丰县| 泊头市| 红安县| 宁南县| 东至县| 桃园市| 齐齐哈尔市| 谷城县| 金堂县| 宁南县| 黄大仙区| 乡宁县| 阳泉市| 宿迁市| 陇川县| 科尔| 水城县| 三门峡市| 信阳市| 哈尔滨市| 建昌县| 两当县| 南召县| 文水县| 保亭| 滕州市| 日喀则市| 青州市| 田东县| 平凉市|