亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

webpack 填坑之路--提取獨(dú)立文件(模塊)

ZweiZhao / 1287人閱讀

摘要:前言最近重新看了一遍提取公共文件的配置。這篇文章將以解決實(shí)際開發(fā)遇到的問題為核心,悉數(shù)利用提取獨(dú)立文件模塊的應(yīng)用。利用插件是專門用來提取獨(dú)立文件的,它主要是提取多個(gè)入口的公共模塊。插入標(biāo)簽的這一步可以在打包好獨(dú)立文件之前,就在模板中插入。

前言

最近重新看了一遍 webpack 提取公共文件的配置。原來覺得這東西是個(gè)玄學(xué),都是 “憑感覺” 配置。這篇文章將以解決實(shí)際開發(fā)遇到的問題為核心,悉數(shù)利用 webpack 提取獨(dú)立文件(模塊)的應(yīng)用。

獨(dú)立文件在實(shí)際開發(fā)中一般有兩種:

第三方模塊 如 Vue React jQuery 等

項(xiàng)目開發(fā)編寫的獨(dú)立模塊(模塊),對于 MPA 多頁面開發(fā)來說是封裝出的一些方法庫比如 utils.getQueryString() 或者是每個(gè)頁面的共同操作;對于SPA 應(yīng)用來說沒有特別的需要分離出模塊,但是針對首屏渲染速度的提升,可以將 某些獨(dú)立模塊分離出來實(shí)現(xiàn)按需加載。

分離出獨(dú)立文件的目的:

獨(dú)立文件一般很少更改或者不會(huì)更改,webpack 沒必要每次打包進(jìn)一個(gè)文件中,獨(dú)立文件提取出可以長期緩存。

提升 webpack 打包速度

提取第三方模塊

配置externals
Webpack 可以配置 externals 來將依賴的庫指向全局變量,從而不再打包這個(gè)庫。

// webpack.config.js 中
module.exports = {
  entry: {
    app: __direname +"/app/index.js"
  }
  externals: {
    jquery: "window.jQuery"
  }
  ...
}

// 模板 html 中
...

...

// 入口文件  index.js
import $ from "jquery"

其實(shí)就是 script 標(biāo)簽引入的jquery 掛載在window下 其他類型 externals 的配置可以去官網(wǎng)查看,這種方法不算是打包提取第三方模塊,只是一個(gè)變量引入,不是本文討論的重點(diǎn)。

利用CommonsChunkPlugin
CommonsChunkPlugin 插件是專門用來提取獨(dú)立文件的,它主要是提取多個(gè)入口 chunk 的公共模塊。他的配置介紹如下:

配置屬性 配置介紹
name 或者 names chunk 的名稱 如果是names數(shù)組 相當(dāng)于對每個(gè)name進(jìn)行插件實(shí)例化
filename 這個(gè)common chunk 的文件輸出名
minChunks 通常情況為一個(gè)整數(shù),至少有minChunks個(gè)chunk使用了該模塊,該模塊才會(huì)被移入[common chunk]里 minChunks 還可以是Infinity意思為沒有任何模塊被移入,只是創(chuàng)建當(dāng)前這個(gè) chunk,這通常用來生成 jquery 等第三方代碼庫。minChunks還可以是一個(gè)返回布爾值的函數(shù),返回 true 該模塊會(huì)被移入 common chunk,否則不會(huì)。默認(rèn)值是 chunks 的長度。
chunks 元素為chunk名稱的數(shù)組,插件將從該數(shù)組中提取common chunk 可見 minChunks 應(yīng)該小予chunks的長度,且大于1。如果沒有 所有的入口chunks 會(huì)被選中
children 默認(rèn)為false 如果為true 相當(dāng)于為上一項(xiàng)chunks配置為chunk的子chunk 用于代碼分割code split
async 默認(rèn)為false 如果為true 生成的common chunk 為異步加載,這個(gè)異步的 common chunk 是 name 這個(gè) chunk 的子 chunk,而且跟 chunks 一起并行加載
minSize 如果有指定大小,那么 common chunk 的文件大小至少有 minSize 才會(huì)被創(chuàng)建。非必填項(xiàng)。

創(chuàng)建一個(gè)如下圖的目錄

package.json 如下

{
  "name": "webpacktest",
  "version": "1.0.0",
  "description": "",
  "directories": {
    "doc": "doc"
  },
  "scripts": {
    "start": "webpack"
  },
  "author": "abzerolee",
  "license": "ISC",
  "devDependencies": {
    "html-webpack-plugin": "^2.30.1",
    "webpack": "^3.8.1"
  },
  "dependencies": {
    "underscore": "^1.8.3",
  }
}

a.js 引入了 underscore 需要進(jìn)行了數(shù)組去重操作,現(xiàn)在需要將underscore分離為獨(dú)立文件。

// webpack.config.js
entry: {
  a: __dirname +"/app/a.js",
  vendor: ["underscore"]
},
output: {
  path: __dirname +"/dist",
  filename: "[name].[chunkhash:6].js",       
  chunkFilename: "[name].[id].[chunkhash:6].js"
},
plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    name: "vendor",
  }),
  new HtmlWebpackPlugin({
    template: __dirname +"/app/index.html"
  })
]
// a.js
let _ = require("underscore");

let arr = _.filter([1,2,3,2,3,3,5,5], (v, i, self) => self.indexOf(v) === i);
console.log("unique:" +arr);

這樣underscore就分離進(jìn)了 vendor 塊,注意的是需要在入口定義 要輸出的 [ 獨(dú)立文件名 ]: [ 需要分離的模塊數(shù)組 ], 然后在CommonsChunkPlugin中配置 name : [獨(dú)立文件名]。

當(dāng)然也可以不用在入口定義,如vue-cli 就是在 在CommonsChunk中配置了minChunks。我們的第三方模塊都是通過npm 安裝在node_modules 目錄下,我們可以通過minChunks 判斷模塊路徑是否含有node_module 來返回true 或 false,前文有介紹minChunks的含義。配置如下:

entry: {
    a: __dirname +"/app/a.js", // **注意** 入口沒定義vendor 
  },
  output: {
    path: __dirname +"/dist",
    filename: "[name].[chunkhash:6].js",
    chunkFilename: "[name].[id].[chunkhash:6].js"
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor",
      minChunks: function(module) {
        let flag =  module.context && module.context.indexOf("node_modules") !== -1;
        console.log(module.context, flag);
        return flag;
      }
    }),
    new HtmlWebpackPlugin({
      template: __dirname +"/app/index.html"
    })
  ]

上述兩種方式,對于多頁面還是單頁面都是可應(yīng)用的。但是現(xiàn)在的問題是每次入口文件 a.js 修改之后都會(huì)造成 vendor重新打包。那么如何解決這個(gè)問題呢。

manifest 處理第三方模塊應(yīng)用

我們將 a.js 做一個(gè)簡單修改:

// 原來
-  console.log("unique:" +arr);
// 修改后
+   console.log(arr);

重新打包發(fā)現(xiàn)vendor的hash變化了相當(dāng)于重新打包了underscore,解決的方法是利用一個(gè) manifest 來記錄 vendor 的 id ,如果vendor沒改變,則不需要重新打包。這就有兩種解決方式 :

1. 利用manifest.js

利用CommonsChunkPlugin的chunks特性,提取出 webpack定義的異步加載代碼,配置如下:

entry: {
  a: __dirname +"/app/a.js",
},
output: {
  path: __dirname +"/dist",
  filename: "[name].[chunkhash:6].js",
  chunkFilename: "[name].[id].[chunkhash:6].js"
},
plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    name: "vendor",
    minChunks: function(module) {
      let flag =  module.context && module.context.indexOf("node_modules") !== -1;
      console.log(module.context, flag);
      return flag;
    }
  }),
  new webpack.optimize.CommonsChunkPlugin({
    name: "manifest",
    chunks: ["vendor"],
  }),
  new HtmlWebpackPlugin({
    template: __dirname +"/app/index.html"
  })
]

還是修改了 a.js 之后發(fā)現(xiàn) vendor的 hash 值沒有變化,如下圖:

這里要注意的是chunks: [ 獨(dú)立文件名 ]。但是,又有但是,要是這么就配置沒問題了,就不能叫做玄學(xué)了,修改 a.js 的內(nèi)部代碼沒問題,如果修改了 require 的模塊引入,vendor的hash又有變化了,當(dāng)然我們可以盡量避免修改文件的依賴引入,但是終歸不是最完美的方式。那么終極解決方法是什么呢?DllReferencePlugin,DllPlugin。

2. 利用DllReferencePlugin,DllPlugin

既然動(dòng)態(tài)打包的時(shí)候建立 manifest 不行,那么能不能直接把他打包成一個(gè)純凈的依賴庫,本身無法運(yùn)行,只是讓我們的app 來引入。

那么我們需要完成兩步,先webpack.DllPlugin打包dll(純凈的第三方獨(dú)立文件),然后用DllReferencePlugin 在我們的應(yīng)用中引用,這樣的好處是如果下一個(gè)項(xiàng)目還是使用一樣的依賴比如react react-dom react-router,可以直接引入這個(gè)dll。

配置文件如下:

  entry: {
    vendor: ["underscore"]
  },
  output: {
    path: __dirname +"/dist",
    filename: "[name].js",
    library: "[name]",
  },
  plugins: [
    new webpack.DllPlugin({
      path: __dirname +"/dist/manifest.json",
      name: "[name]",
      context: __dirname,
    }),
  ],

根據(jù)上述配置打包結(jié)果如上圖,dist目錄下現(xiàn)在有一個(gè)vender.js 和 manifest.json 注意這里輸出的路徑配置。DllPlugin配置介紹如下:

配置項(xiàng) 介紹
path path 是 manifest.json 文件的輸出路徑,這個(gè)文件會(huì)用于后續(xù)的業(yè)務(wù)代碼打包;
name name 是 dll 暴露的對象名,要跟 output.library 保持一致;
context context 是解析包路徑的上下文,這個(gè)要跟接下來配置的 webpack.config.js 一致。

之后在我們的應(yīng)用中引入中,配置如下:

  entry: {
    a: __dirname +"/app/a.js",
  },
  output: {
    path: __dirname +"/dist",
    filename: "[name].[chunkhash:6].js",
    chunkFilename: "[name].[id].[chunkhash:6].js"
  },
  plugins: [
    new webpack.DllReferencePlugin({
      context: __dirname,
      manifest: require("./dist/manifest.json"),
    }),
    new HtmlWebpackPlugin({
      template: __dirname +"/app/index.html"
    })
  ]

根據(jù)上述配置打包得到a.3e6285.js index.html 如上圖,瀏覽器中打開index.html會(huì)顯示
Uncaught ReferenceError: vendor is not defined

這里需要在 index.html 中 a.3e6285.js 插入 script 標(biāo)簽


再打開index.html 可以控制臺(tái)打印出了數(shù)組去重的結(jié)果。插入標(biāo)簽的這一步可以在打包好獨(dú)立文件之前,就在模板html 中插入。

到了這里,提取第三方模塊的方法,避免重復(fù)打包的方法都介紹完畢了。接下來是配置提取自己編寫的公共模塊方法。

提取項(xiàng)目公共模塊

單頁面應(yīng)用的公共模塊沒有必要提取出多帶帶的文件,因?yàn)椴槐乜紤]復(fù)用的情況。但是對于打包生成的文件過大,我們又想分離出幾個(gè)模塊有需要的時(shí)候才加載,其實(shí)這并不是提取公共模塊,而是代碼分割,通過:

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

在callback中定義的 require的模塊將會(huì)獨(dú)立打包,并且插入在 html 的head標(biāo)簽,這里就不做更多介紹了。

多頁面應(yīng)用是有必要抽取公共模塊的,比如a.js 引用了lib1, b.js 也引用了 lib1 那么lib1,那么我們肯定希望在提取出 lib1 同時(shí)還可以提取出第三方庫,配置文件如下:

// a.js 
let _ = require("underscore");
let lib1 = require("./lib1");
console.log("this is entry_a import lib1");

let arr = _.filter([1,2,3,2,3,3,5,5], (v, i, self) => self.indexOf(v) === i);
console.log(arr);

// b.js
require("./lib1");
var b = "b";

console.log("this is entry_b import lib1");

// webpack.config.js
  entry: {
    a: __dirname +"/app/a.js",
    b: __dirname +"/app/b.js",
    vendor: ["underscore"],
  },
  output: {
    path: __dirname +"/dist",
    filename: "[name].[chunkhash:6].js",
    chunkFilename: "[name].[id].[chunkhash:6].js"
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: ["chunk", "vendor"],
      minChunks: 2,
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: "manifest",
      chunks: ["vendor"]
    }),
    new HtmlWebpackPlugin({
      template: __dirname +"/app/index.html",
      filename: __dirname +"/dist/a.html",
      chunks: ["a", "chunk", "vendor", "manifest"],
    }),
    new HtmlWebpackPlugin({
      template: __dirname +"/app/index.html",
      filename: __dirname +"/dist/b.html",
      chunks: ["b", "chunk", "vendor", "manifest"],
    }),
  ]
}

通過打包后發(fā)現(xiàn)生成了如下文件:

可以明確看出生成了chunk.d09623.js 而且 其中就是我們的lib1.js 的庫的代碼。這里要注意的是Commons.ChunkPlugin的配置 當(dāng)name 給定數(shù)組之后從入口文件中選取 共同引用超過 minChunks 次數(shù)的模塊打包進(jìn)name 數(shù)組的第一個(gè)模塊,然后name 數(shù)組后面的塊 "vendor" 依次打包(查找entry里的key,沒有找到相關(guān)的key就生成一個(gè)空的塊),最后一個(gè)塊包含webpack生成的在瀏覽器上使用各個(gè)塊的加載代碼,所以插入到頁面中最后一個(gè)塊要最先加載,加載順序由name數(shù)組自右向左。

這里我們使用manifest 去提取了 webpackJsonp 的加載代碼,為了防止重復(fù)打包庫文件,這在前文已經(jīng)提到過。所以vendor中的加載代碼在mainfest.js 中,修改a.js 的console.log, 重新打包后的文件可以發(fā)現(xiàn)chunk.d0962e.js, vendor.98054b.js都沒有重新打包

所以總結(jié)來講就是多入口配置CommonsChunk

    new webpack.optimize.CommonsChunkPlugin({
      name: ["生成的項(xiàng)目公共模塊文件名", "第三方模塊文件名"],
      minChunks: 2,
    }),

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/89601.html

相關(guān)文章

  • webpack4配置之分享幾個(gè)常用插件

    摘要:去做想做的事,去愛值得的人去成為自己喜歡的模樣,去讓自己發(fā)光渾身充滿力量,充實(shí)的日子最美好各位早安,這里是平頭哥聯(lián)盟,我是首席填坑官蘇南,用心分享一起成長做有溫度的攻城獅。 showImg(https://segmentfault.com/img/bVbjIcs?w=1008&h=298); 前言   繼上一次webpack的基礎(chǔ)配置分享之后,本次將分享一些工作中項(xiàng)目常用的配置插件、也...

    Jackwoo 評論0 收藏0
  • React 歷史項(xiàng)目維護(hù)與優(yōu)化實(shí)踐

    摘要:本文介紹了作者接手維護(hù)一個(gè)中型歷史項(xiàng)目時(shí)的一系列改進(jìn)實(shí)踐,包括模塊結(jié)構(gòu)拆分業(yè)務(wù)邏輯梳理打包優(yōu)化等。代碼中如菜單名稱結(jié)構(gòu)表單字段名等的各種硬編碼配置分散在各處。最后,在提升面向開發(fā)者的打包體驗(yàn)方面,本次優(yōu)化中主要實(shí)現(xiàn)的是與的解耦。 本文介紹了作者接手維護(hù)一個(gè)中型 React 歷史項(xiàng)目時(shí)的一系列改進(jìn)實(shí)踐,包括模塊結(jié)構(gòu)拆分、業(yè)務(wù)邏輯梳理、Webpack 打包優(yōu)化等。 背景 這是一個(gè) PC 的...

    toddmark 評論0 收藏0
  • webpack4配置詳解之逐行分析

    摘要:今天就嘗試著一起來聊聊吧,旨在幫大家加深理解新手更容易上路,都能從到搭建配置自定屬于自己的腳手架,或?qū)σ逊庋b好的腳手架有進(jìn)一步的鞏固,接下來蘇南會(huì)詳細(xì)講解中的每一個(gè)配置字段的作用部分為新增。 showImg(https://segmentfault.com/img/bVbjmMV?w=1008&h=298); 前言   經(jīng)常會(huì)有群友問起webpack、react、redux、甚至cre...

    dkzwm 評論0 收藏0
  • Reactjs、redux的從入門到放棄、刪庫跑路示例

    摘要:我的入門到放棄之路最近看到很多相關(guān)的問題跟討論,越來越多的小伙伴喜歡這個(gè)框架了,同時(shí)也在看到了有些入門的小伙伴遇到了各種各樣的問題,本人也是框架使用都一枚,公司是騰訊阿里平安三巨頭合資的一家公司,分別上海深圳杭州北京廣州等多個(gè)分部,前端人員 showImg(https://segmentfault.com/img/bVbhonB?w=1278&h=722); 我的react入門到放棄之...

    Miracle 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<