摘要:編寫良好的模塊提供了可靠的抽象和封裝邊界,構成了一致的設計和明確的目的。塊此特定術語在內部用于管理捆綁過程。捆綁包由塊組成,其中有幾種類型例如入口和子。總結一個塊是進程中的一組模塊,一個是一個發出的塊或一組塊。
我們先看一下 compilation是什么?
是一個很大的對象
打印key值
[ "_pluginCompat", "hooks", "name", "compiler", "resolverFactory", "inputFileSystem", "requestShortener", "options", "outputOptions", "bail", "profile", "performance", "mainTemplate", "chunkTemplate", "hotUpdateChunkTemplate", "runtimeTemplate", "moduleTemplates", "semaphore", "entries", "_preparedEntrypoints", "entrypoints", "chunks", "chunkGroups", "namedChunkGroups", "namedChunks", "modules", "_modules", "cache", "records", "additionalChunkAssets", "assets", "errors", "warnings", "children", "dependencyFactories", "dependencyTemplates", "childrenCounters", "usedChunkIds", "usedModuleIds", "fileTimestamps", "contextTimestamps", "compilationDependencies", "_buildingModules", "_rebuildingModules"
我們看有熟悉的chunks,entries,options,
這些是Compilation定義的屬性
const EntryModuleNotFoundError = require("./EntryModuleNotFoundError"); const ModuleNotFoundError = require("./ModuleNotFoundError"); const ModuleDependencyWarning = require("./ModuleDependencyWarning"); const ModuleDependencyError = require("./ModuleDependencyError"); const ChunkGroup = require("./ChunkGroup"); const Chunk = require("./Chunk"); const Entrypoint = require("./Entrypoint"); const MainTemplate = require("./MainTemplate"); const ChunkTemplate = require("./ChunkTemplate"); const HotUpdateChunkTemplate = require("./HotUpdateChunkTemplate"); const ModuleTemplate = require("./ModuleTemplate"); const RuntimeTemplate = require("./RuntimeTemplate"); const ChunkRenderError = require("./ChunkRenderError"); const AsyncDependencyToInitialChunkError = require("./AsyncDependencyToInitialChunkError"); const Stats = require("./Stats"); const Semaphore = require("./util/Semaphore"); const createHash = require("./util/createHash"); const Queue = require("./util/Queue"); const SortableSet = require("./util/SortableSet"); const GraphHelpers = require("./GraphHelpers"); const ModuleDependency = require("./dependencies/ModuleDependency"); const compareLocations = require("./compareLocations");
從這一堆的模塊引入里,也可以猜出Compilation主要做了Modules變成Chunks編譯的過程
里面有一些方法
1.對模塊的處理,創建搜索添加構建/模塊依賴處理,添加模塊依賴,分類模塊等
addModule/getModule/ findModule/buildModule/sortModules
2.對Chunk的處理,創建Chunk
3.哈希值
Compilation.prototype.applyPlugins
在原型上添加了applyPlugins方法
Compilation.js也是對Tapable 的拓展
主要處理Chunk、Module等
我們學習一下
webpack術語表定義模塊:離散的功能塊,提供比完整程序更小的表面積。編寫良好的模塊提供了可靠的抽象和封裝邊界,構成了一致的設計和明確的目的。
塊:此Webpack特定術語在內部用于管理捆綁過程。捆綁包由塊組成,其中有幾種類型(例如入口和子)。通常,塊直接與輸出束相對應,但是,有些配置不會產生一對一的關系。
Bundle:由許多不同的模塊生成,bundle包含已經過加載和編譯過程的源文件的最終版本。
總結
a chunk is a group of modules within the webpack process, a bundle is an emitted chunk or set of chunks.
一個塊是webpack進程中的一組模塊,一個bundle是一個發出的塊或一組塊。
{ entry: { foo: ["webpack/hot/only-dev-server.js","./src/foo.js"], bar: ["./src/bar.js"] }, output: { path: "./dist", filename: "[name].js" } } Modules: "webpack/hot/only-dev-server.js", "./src/foo.js", "./src/bar.js" ( + any other modules that are dependencies of these entry points!) Chunks: foo, bar Bundles: foo, bar
通俗的解釋一下,Modules是引入的模塊,Chunks就是編譯的模塊,Bundles是提交的Chunks ,Chunks和Bundles是1:1的關系,配置map會有例外
總結Compilation主要做了Modules變成Chunks編譯的過程
chunks不細看邏輯,好像太虛了,我們看一下this.chunks
它是一個數組,目前Chunk的長度是1,因為只是引入了一個模塊
[ Chunk { id: "main", ids: [ "main" ], debugId: 1000, name: "main", preventIntegration: false, entryModule: NormalModule { dependencies: [], blocks: [], variables: [], type: "javascript/auto", context: "/Users/orion/Desktop/react-beauty-highcharts/src", debugId: 1000, hash: "a6388d29fa15bd58c6cffb10246992a5", renderedHash: "a6388d29fa15bd58c6cf", resolveOptions: {}, factoryMeta: {}, warnings: [], errors: [], buildMeta: [Object], buildInfo: [Object], reasons: [Array], _chunks: [SortableSet], id: "./src/index.js", index: 0, index2: 0, depth: 0, issuer: null, profile: undefined, prefetched: false, built: true, used: null, usedExports: null, optimizationBailout: [], _rewriteChunkInReasons: undefined, useSourceMap: true, _source: [SourceMapSource], request: "/Users/orion/Desktop/react-beauty-highcharts/node_modules/babel-loader/lib/index.js!/Users/orion/Desktop/react-beauty-highcharts/src/index.js", userRequest: "/Users/orion/Desktop/react-beauty-highcharts/src/index.js", rawRequest: "./src/index.js", binary: false, parser: [Parser], generator: JavascriptGenerator {}, resource: "/Users/orion/Desktop/react-beauty-highcharts/src/index.js", matchResource: undefined, loaders: [Array], error: null, _buildHash: "488efbd43aa05371d3f44d94c89abd57", buildTimestamp: 1547884969828, _cachedSources: Map {}, lineToLine: false, _lastSuccessfulBuildMeta: [Object], _ast: null }, _modules: SortableSet [Set] { [NormalModule], _sortFn: [Function: sortByIdentifier], _lastActiveSortFn: null, _cache: undefined, _cacheOrderIndependent: undefined }, filenameTemplate: undefined, _groups: SortableSet [Set] { [Entrypoint], _sortFn: [Function: sortChunkGroupById], _lastActiveSortFn: null, _cache: undefined, _cacheOrderIndependent: undefined }, files: [], rendered: false, hash: "0988e8454f1915ec05fee482db8d0a6f", contentHash: { javascript: "4b8695ca3c1d42e76c52" }, renderedHash: "0988e8454f1915ec05fe", chunkReason: undefined, extraAsync: false, removedModules: undefined } ]
我們看到在entryModule下,記錄了入口的絕對地址,相對地址,編譯的hash,文件類型等信息
//文件寫入,文件輸出,文件緩存,里面具體的template.getRenderManifest,chunk.hasRuntime(),CachedSource具體的邏輯不能夠一一的去研究詳解,但是從名字能知道這個函數是做什么的 createChunkAssets() { const outputOptions = this.outputOptions; const cachedSourceMap = new Map(); /** @type {Map} */ const alreadyWrittenFiles = new Map(); for (let i = 0; i < this.chunks.length; i++) { const chunk = this.chunks[i]; chunk.files = []; let source; let file; let filenameTemplate; try { const template = chunk.hasRuntime() ? this.mainTemplate : this.chunkTemplate; const manifest = template.getRenderManifest({ chunk, hash: this.hash, fullHash: this.fullHash, outputOptions, moduleTemplates: this.moduleTemplates, dependencyTemplates: this.dependencyTemplates }); // [{ render(), filenameTemplate, pathOptions, identifier, hash }] for (const fileManifest of manifest) { const cacheName = fileManifest.identifier; const usedHash = fileManifest.hash; filenameTemplate = fileManifest.filenameTemplate; file = this.getPath(filenameTemplate, fileManifest.pathOptions); // check if the same filename was already written by another chunk const alreadyWritten = alreadyWrittenFiles.get(file); if (alreadyWritten !== undefined) { if (alreadyWritten.hash === usedHash) { if (this.cache) { this.cache[cacheName] = { hash: usedHash, source: alreadyWritten.source }; } chunk.files.push(file); this.hooks.chunkAsset.call(chunk, file); continue; } else { throw new Error( `Conflict: Multiple chunks emit assets to the same filename ${file}` + ` (chunks ${alreadyWritten.chunk.id} and ${chunk.id})` ); } } if ( this.cache && this.cache[cacheName] && this.cache[cacheName].hash === usedHash ) { source = this.cache[cacheName].source; } else { source = fileManifest.render(); // Ensure that source is a cached source to avoid additional cost because of repeated access if (!(source instanceof CachedSource)) { const cacheEntry = cachedSourceMap.get(source); if (cacheEntry) { source = cacheEntry; } else { const cachedSource = new CachedSource(source); cachedSourceMap.set(source, cachedSource); source = cachedSource; } } if (this.cache) { this.cache[cacheName] = { hash: usedHash, source }; } } if (this.assets[file] && this.assets[file] !== source) { throw new Error( `Conflict: Multiple assets emit to the same filename ${file}` ); } this.assets[file] = source; chunk.files.push(file); this.hooks.chunkAsset.call(chunk, file); alreadyWrittenFiles.set(file, { hash: usedHash, source, chunk }); } } catch (err) { this.errors.push( new ChunkRenderError(chunk, file || filenameTemplate, err) ); } } }
[ {
dependencies: [],
blocks: [],
variables: [],
type: "javascript/auto",
context: "/Users/orion/Desktop/react-beauty-highcharts/src",
debugId: 1000,
hash: "a6388d29fa15bd58c6cffb10246992a5",
renderedHash: "a6388d29fa15bd58c6cf",
resolveOptions: {},
factoryMeta: {},
warnings: [],
errors: [],
buildMeta: { providedExports: true },
buildInfo:
{ cacheable: true,
fileDependencies: [Set],
contextDependencies: Set {},
temporaryProvidedExports: false },
reasons: [ [ModuleReason] ],
_chunks:{
[Chunk],
_sortFn: [Function: sortById],
_lastActiveSortFn: null,
_cache: undefined,
_cacheOrderIndependent: undefined },
id: "./src/index.js",
index: 0,
index2: 0,
depth: 0,
issuer: null,
profile: undefined,
prefetched: false,
built: true,
used: null,
usedExports: null,
optimizationBailout: [],
_rewriteChunkInReasons: undefined,
useSourceMap: true,
_source:{
_value:
"module.exports = {
doubleLine: function doubleLine(arr) {
if (arr && !Array.isArray(arr)) {
console.error("the first params type must be Array");
return;
}
return {
credits: {
enabled: false // 禁用版權信息
},
chart: {
width: "400",
height: "400",
type: "area",
backgroundColor: {
linearGradient: [0, 0, 500, 500],
stops: [[0, "rgba(14, 8, 55,1)"], [1, "rgba(14, 8, 55,1)"]]
}
},
title: {
text: "",
style: {
color: "#a6aed2",
font: "bold 16px "Trebuchet MS", Verdana, sans-serif"
}
},
xAxis: {
categories: ["10:00", "10:30", "11:00", "11:30", "12:00", "12:30", "13:00", "13:30", "14:00", "14:30", "15:00", "15:30", "16:00", "16:30", "16:30", "17:00", "17:30", "18:00", "18:30", "19:00"],
labels: {
format: "{value} ",
style: {
color: "#746f95",
fontSize: "12px",
fontFamily: "微軟雅黑"
}
},
maxPadding: 0.05,
showLastLabel: true,
// tickmarkPlacement:"on",
tickColor: "#746f95",
lineWidth: 1,
lineColor: "#746f95",
tickLength: 5,
minRange: 5,
tickInterval: 1 // 坐標軸刻度間隔為一星期
},
yAxis: {
gridLineWidth: "0px",
startOnTick: true,
endOnTick: false,
maxPadding: 0.35,
title: {
text: null
},
labels: {
// format: "{value}?m",
style: {
color: "#746f95",
fontSize: "12px",
fontFamily: "微軟雅黑"
}
},
lineWidth: 1,
lineColor: "#746f95"
},
legend: {
itemStyle: {
font: "9pt Trebuchet MS, Verdana, sans-serif",
color: "#a6aed2"
},
itemHoverStyle: {
color: "#fff"
}
},
tooltip: {
pointFormat: "{series.name}: {point.y:,.0f}人"
},
plotOptions: {
area: {
// pointStart: 1920,
marker: {
enabled: false,
symbol: "circle",
radius: 2,
states: {
hover: {
enabled: true
}
}
}
}
},
series: arr && arr[0] === "pink" ? [{
// data: [ 110, 235, 369, 640,
// 1005, 1436, 2063, 3057, 4618, 6444, 9822, 15468, 20434, 24126,
// 27387, 29459, 31056, 31982, 32040, 31233, 29224, 27342, 26662,
// 26956, 27912, 28999, 28965, 27826, 25579, 25722, 24826, 24605,
// 24304, 23464, 23708, 24099, 24357, 24237, 24401, 24344, 23586,
// 22380, 21004, 17287, 14747, 13076, 12555, 12144, 11009, 10950,
// 10871, 10824, 10577, 10527, 10475, 10421, 10358, 10295, 10104],
lineColor: "#e88eb3",
color: {
linearGradient: {
x1: 0,
x2: 0,
y1: 0,
y2: 1
},
stops: [[0, "rgba(231,142,179,0.8)"], [1, "rgba(135,56,89,0.5)"]]
},
fillOpacity: 0.5,
name: "進",
marker: {
enabled: false
} // threshold: null // 是否顯示負數
}, {
// data: ,
lineColor: "#b946ff",
color: {
linearGradient: {
x1: 0,
x2: 0,
y1: 0,
y2: 1
},
stops: [[0, "rgba(152,60,210,0.8)"], [1, "rgba(65,25,90,0.35)"]]
},
fillOpacity: 0.5,
name: "出",
marker: {
enabled: false
},
threshold: null
}] : [{
// data: [ 110, 235, 369, 640,
// 1005, 1436, 2063, 3057, 4618, 6444, 9822, 15468, 20434, 24126,
// 27387, 29459, 31056, 31982, 32040, 31233, 29224, 27342, 26662,
// 26956, 27912, 28999, 28965, 27826, 25579, 25722, 24826, 24605,
// 24304, 23464, 23708, 24099, 24357, 24237, 24401, 24344, 23586,
// 22380, 21004, 17287, 14747, 13076, 12555, 12144, 11009, 10950,
// 10871, 10824, 10577, 10527, 10475, 10421, 10358, 10295, 10104],
lineColor: "#b946ff",
color: {
linearGradient: {
x1: 0,
x2: 0,
y1: 0,
y2: 1
},
stops: [[0, "rgba(152,60,210,0.8)"], [1, "rgba(65,25,90,0.35)"]]
},
fillOpacity: 0.5,
name: "進",
marker: {
enabled: false
} // threshold: null // 是否顯示負數
}, {
// data: ,
lineColor: "#68d5ee",
color: {
linearGradient: {
x1: 0,
x2: 0,
y1: 0,
y2: 1
},
stops: [[0, "rgba(104,213,238,0.8)"], [1, "rgba(7,44,96,0.5)"]]
},
fillOpacity: 0.5,
name: "出",
marker: {
enabled: false
},
threshold: null
}]
};
},
columns: function columns() {
return {
credits: {
enabled: false
},
chart: {
type: "column",
backgroundColor: {
linearGradient: [0, 0, 500, 500],
stops: [[0, "rgb(14, 8, 55)"], [1, "rgb(14, 8, 55)"]]
}
},
title: {
text: "月平均降雨量",
style: {
color: "#a6aed2",
font: "bold 16px "Trebuchet MS", Verdana, sans-serif"
}
},
xAxis: {
gridLineWidth: "0px",
startOnTick: true,
endOnTick: false,
maxPadding: 0.35,
categories: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
labels: {
format: "{value} ",
style: {
color: "#746f95",
fontSize: "12px",
fontFamily: "微軟雅黑"
}
},
crosshair: true,
lineWidth: 1,
lineColor: "#746f95",
tickLength: 5,
tickColor: "#746f95"
},
yAxis: {
gridLineWidth: "0px",
startOnTick: true,
endOnTick: false,
maxPadding: 0.35,
min: 0,
labels: {
format: "{value} ",
style: {
color: "#746f95",
fontSize: "12px",
fontFamily: "微軟雅黑"
}
},
title: {
// 平均時長 (min)
text: "",
style: {
color: "#746f95",
fontSize: "12px",
fontFamily: "微軟雅黑"
}
},
lineWidth: 1,
lineColor: "#746f95"
},
tooltip: {
// head + 每個 point + footer 拼接成完整的 table
headerFormat: "{point.key}
{series.name}: | " + "{point.y} |
我們看到module的長度也是一個,一樣有類型,路徑,hash
其中
_source的_value下的module.exports,已經是略微壓縮版的了,里面還有n
里面值得分析的還有很多,關于怎么壓縮,壓縮算法是怎么處理的,二次讀源碼再詳解
周六快樂,剛剛抓娃娃機一個都沒抓上,哈哈哈哈,但是我抓的激動開心啊
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101227.html
摘要:打開是個構造函數,定義了一些靜態屬性和方法我們先看在插件下地址上面寫的解釋就跟沒寫一樣在文件下我們看到輸出的一些對象方法每一個對應一個模塊而在下引入的下面,我們先研究引入的對象的英文單詞解釋,除了最常用的點擊手勢之外,還有一個意思是水龍頭進 打開compile class Compiler extends Tapable { constructor(context) { ...
摘要:從出來接著我們看大法,打印一下感覺之前所以的對象都放在了一個合集里,給人而全的感覺里面主要含有一個對象,,輸出的,等給每次打包一個值,代表唯一性天啊 從compilation出來接著我們看 const stats = new Stats(compilation); Stats.js log大法,打印一下 stats let Stats = { compilation:{ ...
摘要:本篇的主要目標是通過實際問題來介紹中容易被人忽略的細節以及源碼分析以最新發布的版本的源碼為例并且提供幾種解決方案。探究原因及源碼分析這里以最新發布的版本的源碼作為分析。解決方案加參數基于上面簡要的分析,我們來嘗試下參數的作用。 注:本篇不是入門教程,入門請直接查看官方文檔。本篇的主要目標是通過實際問題來介紹 webpack 中容易被人忽略的細節, 以及源碼分析(以最新發布的 relea...
摘要:舉例這個方案還有些小缺點,就是用模塊文件路徑作為哈希輸入還不是百分百完美,如果文件名改了,那么模塊就不穩定了。其實,可以用模塊文件內容作為哈希輸入,考慮到效率問題,權衡之下還是用路徑好了。 來自 http://zhenyong.site/2016/10/... 使用 webpack 構建輸出文件時,通常會給文件名加上 hash,該 hash 值根據文件內容計算得到,只要文件內容不變,h...
為什么讀webpack源碼 因為前端框架離不開webpack,天天都在用的東西啊,怎能不研究 讀源碼能學到很多做項目看書學不到的東西,比如說架構,構造函數,es6很邊緣的用法,甚至給函數命名也會潛移默化的影響等 想寫源碼,不看源碼怎么行,雖然現在還不知道寫什么,就算不寫什么,看看別人寫的總可以吧 知道世界的廣闊,那么多插件,那么多軟件開發師,他們在做什么,同樣是寫js的,怎么他們能這么偉大 好奇...
閱讀 785·2023-04-26 00:30
閱讀 2690·2021-11-23 09:51
閱讀 1045·2021-11-02 14:38
閱讀 2560·2021-09-07 10:23
閱讀 2243·2021-08-21 14:09
閱讀 1363·2019-08-30 10:57
閱讀 1603·2019-08-29 11:20
閱讀 1149·2019-08-26 13:53