成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

手把手深入理解 webpack dev middleware 原理與相關(guān) plugins

gitmilk / 2109人閱讀

摘要:的架構(gòu)設(shè)計促使第三方開發(fā)者讓核心發(fā)揮出無限的潛力。當然建置比起開發(fā)是較進階的議題,因為我們必須要理解內(nèi)部的一些事件。這個編譯結(jié)果包含的訊息包含模組的狀態(tài),編譯後的資源檔,發(fā)生異動的檔案,被觀察的相依套件等。

本文將對 webpack 周邊的 middleware 與 plugin 套件等作些介紹,若您對於 webpack 還不了解可以參考這篇彙整的翻譯。

webpack dev server 是什麼?

webpack dev server 是一個開發(fā)伺服器,內(nèi)建 webpack 使用的 live reloading 功能。

那 webpack dev middleware 是啥?

它就是一個用來組織包裝 webpack 使其可以變成中介軟體,或稱中間件的容器?;叵胍幌?express 你大概可以明白關(guān)於 middleware 的用途,就是在輸入到輸出的過程中 加工 的一種手段。單純說 middleware 的話我們可以想成一系列任務(wù), 動作(actions stack),不只 express 有,在 Ruby 中的 rake 也具備這種機制。

先看看web dev server的說明

The webpack-dev-server is a little node.js Express server, which uses the webpack-dev-middleware to serve a webpack bundle.

從頭說起的話就是 webpack 本身只負責打包編譯的功能 bundle, webpack-dev-server 當然就是協(xié)助我們開發(fā)的伺服器,這個伺服器底層是靠 express 來實作的,接著思考一下我們要如何更新(live reload)呢? 當然是需要取得 webpack 編好的資料啊,於是就需要在從 requestresponse 的過程中透過 express 的 middleware 取得資料,而方法就是透過 webpack-dev-middleware 。

比起直接編譯成檔案,webpack-dev-middleware 這個套件還多了一些好處:

不需要一直寫入磁碟,所有產(chǎn)生的結(jié)果會直接存在記憶體

在監(jiān)視模式(watch mode)下如果檔案發(fā)生異動,middleware 會馬上停止提供舊版的 bundle 並且會延遲請求的回應(yīng)直到編譯完成,如此一來我們就不需要去觀察編譯是否結(jié)束了

webpack hot middleware 是什麼?

我們都知道 webpack dev server 有提供一種Hot Module Replacement/Hot Reloading 熱替換的功能。在一般 webpack-dev-server 的時候我們會在 webpack.config.js 加入 new webpack.HotModuleReplacementPlugin() 或設(shè)定來啟用。

webpack hot middleware 是給 webpack-dev-middleware 用的。就是讓我們在一般的 server 上加上熱替換的功能,總結(jié)來說就是 webpack-dev-middleware + webpack-hot-middleware 即可讓我們用 express 客製一個有熱替換功能的 webpack 開發(fā)伺服器。

使用 webpack-dev-server 當中介軟體

webpack 提供了 express 的 middleware 讓我們可以處理一些靜態(tài)資源檔而不是使用 express.static。要達成這項功能,我們需要安裝 webpack-dev-middlewarewebpack-hot-middleware

$ npm i webpack express webpack-dev-middleware webpack-hot-middleware -D

安裝完成套件之後,首先我們需要設(shè)定一個 webpack.dev.config.js 檔案,並且在 entry 中加上 webpack/hot/dev-serverwebpack-hot-middleware/client

entry: [
  "webpack/hot/dev-server",
  "webpack-hot-middleware/client",
  "client/index.js"
]

這個 webpack.config 主要是給開發(fā)伺服器用的,由於這時的匯出都會存在記憶體中,因此 path 可以直接設(shè)為根

output: {
  path: "/",
  publicPath: "http://localhost:8080/scripts/",
  filename: "bundle.js"
}

最後補上任何您所需要的 loaders,最重要的是記得。

plugins: [
  new webpack.HotModuleReplacementPlugin()
]

接著下來我們開始來撰寫這個開發(fā)環(huán)境的設(shè)定檔和 express 程式。

我們會匯入 webpack,webpack-dev-middleware, webpack-hot-middleware 和 express。

若需要搭配樣板引擎請自行安裝 ejs 或 jade

var express = require("express")
var webpack = require("webpack")
var WebpackDevMiddleware = require("webpack-dev-middleware")
var WebpackHotMiddleware = require("webpack-hot-middleware")

載入套件之後,使用 express 建立一個 http 應(yīng)用程式與路由

app = express()
router = express.Router()

router.get("/", MainController)
app.use(router)

上面只是一個一般的 Server 應(yīng)用,為了達成 webpack 的神奇黑魔法我們需要匯入 webpack 的設(shè)定

var config = require("./webpack.dev.config")

webpack 的角色就是我們的編譯器,透過下面的程式碼建立編譯器的 instance

var compiler = webpack(config)

重點來了,我們有了伺服器 express,有了編譯核心 webpack,接著我們需要 wrapper 來打包 webpack 將其合進 express 的 middleware stack 中。

app.use(WebpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath,
  stats: { colors: true }
}))

publicPath 就是我們想要存取前端 bundle 的網(wǎng)址,路徑,位置。然後我們要再加上 webpack-hot-middleware 使其具備熱替換的功能。

app.use(WebpackHotMiddleware(compiler, {
  log: console.log
}))

最後則是 express 的監(jiān)聽事件

app.listen(8080, function () {
  console.log("Listening on 8080")
})

完整的 server 程式碼如下

var express = require("express")
var webpack = require("webpack")
var WebpackDevMiddleware = require("webpack-dev-middleware")
var WebpackHotMiddleware = require("webpack-hot-middleware")
var config = require("./config/webpack.dev.config")
var compiler = webpack(config)

app = express()
app.set("views", "./views")
app.set("view engine", "ejs")
app.use(express.static("public"));

app.use(WebpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath,
  stats: { colors: true }
}))
app.use(WebpackHotMiddleware(compiler))

var router = express.Router()
router.get("/", function (req, res, next) {
  res.render("index", { message: "Hey there!"});
})
app.use(router)

app.listen(8080, function () {
  console.log("Listening on 8080")
})
換個思路

假設(shè)我們並不是要實作一個全站 SPA 的站,實務(wù)上我們的確會遇到需要拆分為許多 view .html 的狀況,這種情況下我們會希望自己客製的這個 server 就像 webpack-dev-server 一樣,當然,這邊只是要指出做法,如果一樣您當然就直接用 webpack-dev-server 就好了。

根據(jù)上面這個需求最簡單的方式就是透過 express.static(__dirname) 讓 express 直接 return raw 檔案。

html-webpack-plugin

小弟認為在學習的過程中,最重要的就是搞懂動機,而這個 html-webpack-plugin 插件,其用途就是簡化建立 html 的過程。

先回頭看看上一小節(jié),很直覺的,我們會依據(jù)需求建立不同的頁面(.html),因為在開發(fā)過程中很多時候前端只需要注重那些互動介面的邏輯,樣式,樣板,標籤結(jié)構(gòu) ,那我們的重點只有 client 端的 html, js, css 就不在話下了吧!再如果我們又以元件為思路中心來設(shè)計實踐的話,那麼 html 裡面大部分的東西都會往元件的 template 搬。依據(jù) SPA 的思路,html 的責任就只是把我們的 bundle 載入並掛載 root component

如果照著這樣的想法,不斷的新增 html 結(jié)果大部分的內(nèi)容都是重複的那就不太靠譜啦。我們就需要一種簡化工作的方式。

這個套件如上面所說就是簡化建立載入 bundle 的 html的步驟,用在 webpack 打包的檔案包含每次編譯都會更新的 hash 時特方便。

我們可以讓套件幫我們產(chǎn)生 html 或者搭配 loaders 與其他樣版引擎。

基本的用法

第一種最簡單的用途就是為我們的 bundle 包上一層 html

plugins: [
  new HtmlWebpackPlugin({
    filename: "i_love_this_file.html"
  })
]

如果我們有多個 entry 進入點,那麼所有的 bundle 都會被加進這個自動產(chǎn)生的 HTML 中。
如果我們透過 webpack 匯出了 css 資源檔(例如 extract-text-plugin) 那麼這些檔案也會透過 被加入 HTML 中。

html-webpack-plugin 的設(shè)定

當然這個套件也有一些參數(shù),讓我們可以透過設(shè)定提供其他的功能。

title: 設(shè)定該 html 的 </b> 標籤</p></p> <p><p><b>filename</b>: html 檔名,也當作路徑存取。預(yù)設(shè)是 <b>index.html</b></p></p> <p><p><b>template</b>: 樣板的路徑,也就是說我們可以先組織 HTML 在載入讓 <b>html-webpack-plugin</b> 幫我們注入(inject) bundle。此部分要注意相對路徑是從 server 程式檔案出發(fā)。</p></p> <p> <p><b>inject</b>: 將所有的資源檔注入 <b>template</b> 或 <b>templateContent</b>,當值是 <b>true</b>, <b>"body"</b> 的時候所有的 js 資源檔都會被注入 <b></body></b> 之前,<b>"head"</b> 則是 <b><head></b> 之間,<b>false</b> 自然就是關(guān)閉</p> <p><p>true: Boolean</p></p> <p><p>false: Boolean</p></p> <p><p>head: String</p></p> <p><p>body: String</p></p> </p> <p><p><b>favicon</b>: 替 HTML 加上 favicon 路徑</p></p> <p> <p><b>minify</b>: 傳入 html-minifier 參數(shù)物件,壓縮輸出。</p> <p><p>options: Object</p></p> <p><p>false: Boolean</p></p> </p> <p> <p><b>hash</b>: <b>true</b> 時替 webpack 編譯的檔案或結(jié)果路徑結(jié)尾補上 hash,這麼做的用意是在開發(fā)時期當檔案有異動時可以避免瀏覽器快取</p> <p><p>true: Boolean</p></p> <p><p>false: Boolean</p></p> </p> <p> <p><b>cache</b>: 預(yù)設(shè)是 <b>true</b> 快取檔案,除非檔案有異動</p> <p><p>true: Boolean</p></p> <p><p>false: Boolean</p></p> </p> <p> <p><b>showErrors</b>: 預(yù)設(shè) <b>true</b> 例外或錯誤資訊會寫入 html 頁面</p> <p><p>true: Boolean</p></p> <p><p>false: Boolean</p></p> </p> <p><p><b>chunks</b>: 允許我們加入一些程式碼片段,例如單元測試</p></p> <p> <p><b>chunksSortMode</b>: 控制 chunks 排序</p> <p><p>none: String</p></p> <p><p>auto: String</p></p> <p><p>dependency: String</p></p> <p><p>{}: Function</p></p> </p> <p><p><b>excludeChunks</b>: 略過部分 chunk 程式碼片段</p></p> <p> <p><b>xhtml</b>: 設(shè)定為 <b>true</b> 的話 <b>link</b> 標籤會是 self-closing ,預(yù)設(shè)是 <b>false</b></p> <p><p>true: Boolean</p></p> <p><p>false: Boolean</p></p> </p> <b>腦力激盪 - 如果要多個頁面搭配各自的 bundle?</b> <p>webapck 難就難在其靈活之中伴隨著複雜,不同的思路有著不同的做法。這一小節(jié)目的是為了不讓我們對 webpack 使用上僵化而提出的一個小題目。</p> <p>要達成這個需求,我們可以先使用 webpack.config 中 <b>[name]</b> 的功能拆分我們的 bundle</p> <pre>{ entry: { a: "./path/src/a", b: "./path/src/b", c: "./path/src/c" }, output: { filename: "[name].bundle.js" } }</pre> <p>接著透過 <b>html-webpack-plugin</b> 的參數(shù),把 <b>inject: false</b> 然後 <b>template</b> 在各自的 template 中使用 bundle。</p> <b> html-webpack-template - 更牛的方式</b> <p>照著上面的方式你可能又跟我抱怨,那不是又要產(chǎn)一堆 HTML 了嗎? 對啊!原本這個架構(gòu)就是針對 SPA 設(shè)計的嘛。不過透過這樣來來回回的思考動機與流程我相信對於您日後使用 webpack 與閱讀設(shè)定有很大的幫助?,F(xiàn)在的問題是 - 你覺得產(chǎn)一大堆 HTML 不是很靠譜,於是我們就有了 <b>html-webpack-template</b> 的產(chǎn)生啦。</p> <p>這個東西大略的用法就是</p> <pre>plugins: [ new HtmlWebpackPlugin({ title: "Sample", filename: "sample.html" }), new HtmlWebpackPlugin({ inject: false, // 必須 template: require("html-webpack-template"), // 必須 filename: "sp.html", // 存取的路徑 // 只需要特定 bundle 可以這樣設(shè)定 chunks: ["vender"], title: "OH My Gosh", // 可以參考 html-webpack-template 的參數(shù)設(shè)定 // 下面為提供 GA googleAnalytics: { trackingId: "UA-XXXX-XX", pageViewOnLoad: true } }) ]</pre> <b>html-webpack-plugin 事件</b> <p>特地介紹此套件的事件也是因為挺有可能會需要一些時間點對 html 動些手腳,有了事件的機制我們就可以讓<b>其他套件</b>修改產(chǎn)生的 html</p> <p>非同步事件:</p> <p><p><b>html-webpack-plugin-before-html-generation</b></p></p> <p><p><b>html-webpack-plugin-before-html-processing</b></p></p> <p><p><b>html-webpack-plugin-after-html-processing</b></p></p> <p><p><b>html-webpack-plugin-after-emit</b></p></p> <p>同步事件:</p> <p><p><b>html-webpack-plugin-alter-chunks</b></p></p> <p>大略的用法就是在透過 hook event 綁定的事件做些處理</p> <pre>compiler.plugin("compilation", function(compilation) { console.log("The compiler is starting a new compilation..."); compilation.plugin("html-webpack-plugin-before-html-processing", function(htmlPluginData, callback) { htmlPluginData.html += "The magic footer"; callback(null, htmlPluginData); }); });</pre> <b>webpack-hot-middleware</b> <p><b>webpack-hot-middleware</b> 這個套件只能搭配 <b>webpack-dev-middleware</b> 使用,其實就是把熱替換的功能加到一般 server 應(yīng)用。</p> <p>這個模組只專注在處理 webpack 和瀏覽器溝通的機制。這個中介軟體會去訂閱監(jiān)聽開發(fā)伺服器,當更新或異動發(fā)生的時候它就透過 webpack 的 HMR API 來更新。實際上讓您的程式能無縫的使用熱替換已超過本文範圍,在這部分通常會靠其他模組來處理。</p> <p>安裝完套件與在伺服器 app 中套用之外,要記得 webpack.config 的 plugin 也要加上 <b>HotModuleReplacementPlugin</b></p> <pre>plugins: [ // Webpack 1.0 new webpack.optimize.OccurenceOrderPlugin(), // Webpack 2.0 fixed this mispelling // new webpack.optimize.OccurrenceOrderPlugin(), new webpack.HotModuleReplacementPlugin(), new webpack.NoErrorsPlugin() ]</pre> <p>簡短地介紹一下 <b>OccurrenceOrderPlugin</b> 部份,您應(yīng)該知道 webapck 會給編譯好的程式碼片段一個 id 以用來辨別。</p> <p>透過上面的這個 plugin 可以讓 webpack 在 id 的分派上優(yōu)化並保持一致性。</p> <p>接著要在 entry point 加上 <b>webpack-hot-middleware/client</b> 這隻檔案會連到 server 目的是當 server 重新編譯好檔案時收到通知然後更新 client 的檔案。</p> <b>如何撰寫 plugin</b> <p>為什麼要了解怎麼寫 plugin 呢? 因為某些 plugin 可以擴展支援其他 plugin 相互傳遞資料或需要客製後續(xù)任務(wù),所以稍微明白 plugin 的寫法可以讓我們對於 plugin 的設(shè)定更加清楚。</p> <p>plugin 的架構(gòu)設(shè)計促使第三方開發(fā)者讓 webpack 核心發(fā)揮出無限的潛力。在不同建置階段執(zhí)行 callback ,開發(fā)者可以自訂出特有的行為。</p> <p>當然建置 plugin 比起開發(fā) loader 是較進階的議題,因為我們必須要理解 webpack 內(nèi)部的一些 hook 事件。</p> <h5>編譯器與編譯結(jié)果</h5> <p>要開發(fā) plugin 第一步就是先了解其中最重要的兩個角色 <b>compiler</b> 和 <b>compilation</b> 物件</p> <p><p><b>compiler</b> 編譯器物件代表一個完整設(shè)定的 webpack 環(huán)境。這個物件在 webpack 發(fā)動之後就會被建置,而且只會建置一次。然後它會配置所有可以操作的設(shè)定包含 <b>loaders</b>, <b>plugins</b>。當我們套用一個 plugin 這個 plugin 會收到 <b>compiler</b> 的參考透過存取這個<b>參考 reference</b>就可以取得 webpack 環(huán)境</p></p> <p><p><b>compilation</b> 編譯成果這個物件代表的是<b>某個版本的編譯後的資源檔</b>,在運行 webpack dev middleware 期間每當檔案發(fā)生異動就會產(chǎn)生一個新的 <b>compilation</b> 也就是產(chǎn)生新的編譯結(jié)果。這個<b>編譯結(jié)果</b>包含的訊息包含 module 模組的狀態(tài),編譯後的資源檔,發(fā)生異動的檔案,被觀察的相依套件等。這個編譯結(jié)果物件也提供一些執(zhí)行 callback 的機會讓我們可以在過程中客製一些自己想要的行為。</p></p> <p>任何 webpack plugin 都必須依靠這兩者來完成,所以有需要對其原始碼有些大概的了解</p> <p><p>Compiler Source</p></p> <p><p>Compilation Source</p></p> <b>基本 plugin 架構(gòu)</b> <p>本質(zhì)上來說 plugin 只是一個物件實例具有 apply 方法,這個 <b>apply</b> 會在安裝時期被 <b>webpack compiler</b> 執(zhí)行一次。</p> <p>透過這一次的執(zhí)行呢我們就可以繫結(jié)許多事件,直接來看看程式碼您就明白了。</p> <pre>function MyPlugin(options) { // 設(shè)定參數(shù) this.options = options } MyPlugin.prototype.apply = function(compiler) { compiler.plugin("done", function() { // 當 plugin 安裝完成就會... console.log("Hello World!"); }) // 我們自然需要拿到編譯的結(jié)果 compiler.plugin("compilation", function(compilation) { console.log(compilation.assets) compilation.plugin("optimize", function() { console.log("Assets are being optimized."); }); }); }</pre> <p>OK! 我們現(xiàn)在並不是要開發(fā)套件所以點到這邊我想就足夠了,剩下的您可以自行參考相關(guān)文件。</p> <p><p>詳細 plugin API</p></p> <b>extract-text-webpack-plugin</b> <p>顧名思義這個 plugin 的用途就是把 text 類型的結(jié)果匯出成一個檔案,先說這不是非常精確的描述,但概念來說 text 類型指的就是<b>不會</b>輸出成 <b>module.exports</b> 或 <b>json</b> 的資料。而像是 CSS 這類的資源檔 webpack 其實最終就是在 JS 中幫我們建個 style tag 的 dom 然後整包放進去。<b>file-loader</b>, <b>raw-loader</b> 等等這類內(nèi)容大略就屬於 text 類型。查閱各種 loaders 回傳資料類型</p> <p>於是乎以 entry point 為單位過程中解析的 text 內(nèi)容就會被抽出來匯出成一個檔案。最常見的用法就是把 css 抽出來:</p> <pre>var ExtractTextPlugin = require("extract-text-webpack-plugin") module.exports = { module: { loaders: [ { test: /.css$/, loader: ExtractTextPlugin.extract("style", "css") } ] }, plugins: [ // 注意: 這邊的副檔名如果亂下是會造成瀏覽器行為不符合預(yù)期的,例如不給副檔名那瀏覽器就會當作 binary 下載 new ExtractTextPlugin("styles.css") ] }</pre> <p>如果想要拆分多個檔案,那麼就先初始化 instance</p> <pre>let ExtractTextPlugin = require("extract-text-webpack-plugin"); // multiple extract instances let cssExtractor = new ExtractTextPlugin("stylesheets/[name].css"); let lessExtractor = new ExtractTextPlugin("stylesheets/[name].less"); module.exports = { module: { loaders: [ {test: /.scss$/i, loader: cssExtractor.extract(["css","sass"])}, {test: /.less$/i, loader: lessExtractor.extract(["css","less"])}, ... ] }, plugins: [ cssExtractor, lessExtractor ] }</pre> <b>HMR 熱替換</b> <p>Hot Module Replacement (HRM) 又稱熱替換,功能就是在程式運行中交換,移除,增加模組且不會使頁面重新載入。這跟我們伺服器的熱插拔差不多概念。</p> <h5>它是怎麼運作的?</h5> <p>webpack 在 bundle 中即我們的 js 裡加入了一個小型的 HMR 執(zhí)行環(huán)境,在編譯過程中這個 runtime 會在我們的 app 中運行。</p> <p>當建置完成時 webpack 也不會消失反而會持續(xù)存在,繼續(xù)監(jiān)控原始碼檔案是否發(fā)生修改。一旦 webpack 發(fā)現(xiàn)程式有改變他就會去重新編譯那些有修改的模組,不全部重建。根據(jù)設(shè)定要嘛就是 webpack 把訊號丟給 HRM runtime 要嘛就是 HRM 自己更新異動資訊。不管哪種方式反正重點就是 HRM runtime 會取得修改的模組,接著就試著在運行的狀態(tài)下更新模組。首先會先檢查更新的模組是否能 <b>self-accept</b>。</p> <p>關(guān)於 <b>self-accept</b> 先看看範例和原始碼,意思是要<b>支援熱替換的模組或說編譯結(jié)果</b>基本上是應(yīng)該要實作 <b>module.hot.accept</b> 和遵循其他熱替換的規(guī)則。</p> <p>如果沒有辦法自己確認自己可以直接被更新,那就往上傳,通知那些 require 匯入使用自己的模組更新,就這樣層層往上。直到有人可以 accept 或到頂,不過一旦到根就表示熱替換失敗。</p> <p>讀到這邊你可能通了,為什麼當我們要讓 React 支援 Hot Mode 的時候需要一個 <b>react-hot-loader</b>。以及因為要和 HRM 執(zhí)行環(huán)境溝通的關(guān)係我們需要在 bundle 的 entry point 加上 <b>webpack/hot/dev-server</b>, <b>webpack-hot-middleware/client</b> 之類的東西。</p> <h5>從 App 的角度</h5> <p><script type="text/javascript">showImg("https://segmentfault.com/img/remote/1460000006763873");</script></p> <p>當 App 程式開始執(zhí)行(就是載入 bundle) HMR runtime 執(zhí)行環(huán)境就會啟用,接下來程式就會要求 HMR runtime 幫我們檢查是否需要更新。HMR 會幫我們下載更新然後通知 App 程式有哪些更新可用。</p> <h5>從編譯器(webpack/compiler)的角度</h5> <p>除了一般的資源檔像是圖片,css,編譯器還需要觸發(fā)<b>更新事件</b>讓程式碼可以完成新舊替換。這個"更新"包含兩個部分</p> <p><p>更新的 Manifest 支援配置文件(json)</p></p> <p><p>一或多個更新的<b>chunks</b>程式片段(js)</p></p> <p>支援配置文件包含更新後編譯結(jié)果的 hash 和新的 chunks 程式碼片段的列表。而新的 chunks 則包含更新後模組的程式碼或 <b>flag</b>。</p> <p>編譯器同時也會確保模組和片段 ID 是一致的,透過一個 <b>records</b> 的 json 檔案來儲存相關(guān)資訊。</p> <h5>從模組角度</h5> <p>HMR 是選擇性的功能,所以只有在模組包含 HRM 程式碼才會被影響作用。也就是在模組中使用文件有提供的 API。一般來說模組的開發(fā)者 handler 會在模組相依的部分更新時被執(zhí)行。當然也可以寫一個 handler 在這個模組更新時被呼叫。</p> <p>在大部分的情況並不需要為每一個模組都撰寫<b>支援 HMR 的程式碼</b>,當一個模組沒有遵循處理規(guī)則時就會往上層傳遞事件,意味著只有上方有一個 handler 可以處理就好,但不要讓這個冒泡事件一路冒到頂喔。</p> <h5>從 HMR runtime 角度</h5> <p>模組系統(tǒng)的執(zhí)行環(huán)境其實是額外加入的程式,用來追蹤模組之間的父子關(guān)係。</p> <pre>if(module.hot) { ... }</pre> <p>從管理的角度,這個執(zhí)行環(huán)境 runtime 支援 <b>check</b> 和 <b>apply</b> 兩個方法。</p> <p><b>check</b> 的功能是發(fā)出 HTTP request 用來取得上面提到的 Manifest,當 request 失敗時就等於沒有任何更新。否則就會依照得到的<b>更新列表</b>去比對 chunks。</p> <p>對每個已載入的 chunk 都會有對應(yīng)更新的程式碼要被下載。所有模組更新會被存在 runtime 中準備拿來更新。當執(zhí)行環(huán)境切換成 <b>ready</b> 狀態(tài)就表示更新的程式碼都被下載完成了隨時可以套用。</p> <p>接著 <b>apply</b> 方法會將所有已更新的模組的 <b>flag</b> 標記為 <b>invalid</b> 無效,然後無效的模組需要 update 的 handler 處理函式,這個 handler 會在模組中或者父節(jié)點上。只要沒有這個 handler 就會持續(xù)往上曾傳遞並標註為 <b>invalid</b>,一旦冒泡機制冒到頂端即 <b>entry point</b> 就表示熱替換失敗。</p> <p>所有被標記為無效的模組都會透過 <b>module.hot.dispose</b> 卸載,然後更新 hash,再來所有 <b>module.hot.accept</b> 的 handlers 會被調(diào)用。</p> <p>執(zhí)行環(huán)境切回 <b>idle</b> 狀態(tài)表示所有更新都完成了。</p> <p>講這麼多其實簡單來說就是我們的模組要補一些 hot mode 的邏輯</p> <pre>var app = require("./app"); // 模擬每 5 秒更新一次 setInterval(function() { console.log(app(new Date())); }, 5000); if(module.hot) { module.hot.accept("./app", function() { app = require("./app"); }); }</pre> <h5>檔案的更新流程</h5> <p>左邊表示初始化時編譯器產(chǎn)生的結(jié)構(gòu),右邊則是當模組 4 和 9 更新時的流程。<br>方塊表示從 Entry 開始,webpack 幫我們編譯產(chǎn)生的部份從 Entry 然後轉(zhuǎn)換成 Chunk 0 - 4</p> <p><script type="text/javascript">showImg("https://segmentfault.com/img/remote/1460000004840685");</script></p> <b>資源參考</b> <p><p>html-webpack-plugin</p></p> <p><p>webpack dev middleware 說明</p></p> <b>備註</b> <p>部分內(nèi)容可能理解不夠精確若有錯誤歡迎指教留言</p> </div> <div id="qoyqs8suu2u" class="mt-64 tags-seach" > <div id="qoyqs8suu2u" class="tags-info"> <a style="width:120px;" title="云服務(wù)器" href="http://systransis.cn/site/active/kuaijiesale.html?ytag=seo">云服務(wù)器</a> <a style="width:120px;" title="GPU云服務(wù)器" href="http://systransis.cn/site/product/gpu.html">GPU云服務(wù)器</a> <a style="width:120px;" title="與相關(guān)" href="http://systransis.cn/yun/tag/??xiang??/">與相關(guān)</a> <a style="width:120px;" title="webpack-dev-server" href="http://systransis.cn/yun/tag/webpack-dev-server/">webpack-dev-server</a> <a style="width:120px;" title="深入淺出webpack" href="http://systransis.cn/yun/tag/shenruqianchuwebpack/">深入淺出webpack</a> <a style="width:120px;" title="深入理解系列" href="http://systransis.cn/yun/tag/shenrulijiexilie/">深入理解系列</a> </div> </div> <div id="qoyqs8suu2u" class="entry-copyright mb-30"> <p class="mb-15"> 文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。</p> <p>轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79623.html</p> </div> <ul class="pre-next-page"> <li id="qoyqs8suu2u" class="ellipsis"><a class="hpf" href="http://systransis.cn/yun/79622.html">上一篇:React開發(fā) 獲取不到當前觸發(fā)事件的元素</a></li> <li id="qoyqs8suu2u" class="ellipsis"><a class="hpf" href="http://systransis.cn/yun/79624.html">下一篇:zepto.cutphoto 頭像裁剪小工具</a></li> </ul> </div> <div id="qoyqs8suu2u" class="about_topicone-mid"> <h3 class="top-com-title mb-0"><span data-id="0">相關(guān)文章</span></h3> <ul class="com_white-left-mid atricle-list-box"> <li> <div id="qoyqs8suu2u" class="atricle-list-right"> <h2 class="ellipsis2"><a class="hpf" href="http://systransis.cn/yun/107860.html"><b>【敲黑板】<em>手<em>把手</em></em>教你vue-cli單頁到多頁應(yīng)用</b></a></h2> <p class="ellipsis2 good">摘要:到多頁應(yīng)用前言我有一個創(chuàng)建的項目,但是我想做成多頁應(yīng)用,怎么辦,廢話不多說,直接開擼約定新增代碼部分在和中間刪除注釋代碼部分在和中間,很多東西都寫在注釋里第一步一個項目新建一個項目官網(wǎng)默認使用的服務(wù),這個服務(wù)是做不了單頁的,需要手動建一 vue-cli到多頁應(yīng)用 前言:我有一個cli創(chuàng)建的vue項目,但是我想做成多頁應(yīng)用,怎么辦,廢話不多說,直接開擼~ 約定:新增代碼部分在//add和...</p> <div id="qoyqs8suu2u" class="com_white-left-info"> <div id="qoyqs8suu2u" class="com_white-left-infol"> <a href="http://systransis.cn/yun/u-215.html"><img src="http://systransis.cn/yun/data/avatar/000/00/02/small_000000215.jpg" alt=""><span id="qoyqs8suu2u" class="layui-hide64">DC_er</span></a> <time datetime="">2019-08-26 11:56</time> <span><i class="fa fa-commenting"></i>評論0</span> <span><i class="fa fa-star"></i>收藏0</span> </div> </div> </div> </li> <li> <div id="qoyqs8suu2u" class="atricle-list-right"> <h2 class="ellipsis2"><a class="hpf" href="http://systransis.cn/yun/90923.html"><b>前端臨床手札——<em>webpack</em>構(gòu)建逐步解構(gòu)(上)</b></a></h2> <p class="ellipsis2 good">摘要:前言由于博主最近又閑下來了,之前覺得的官方文檔比較難啃一直放到現(xiàn)在。文章會逐步分析每個處理的用意當然是博主自己的理解,不足之處歡迎指出溝通交流。后續(xù)將會補上構(gòu)建生產(chǎn)的配置分析,案例參考。前端臨床手札構(gòu)建逐步解構(gòu)下 前言 由于博主最近又閑下來了,之前覺得webpack的官方文檔比較難啃一直放到現(xiàn)在。細心閱讀多個webpack配置案例后覺得還是得自己寫個手腳架,當然這個案例是基于vue的,...</p> <div id="qoyqs8suu2u" class="com_white-left-info"> <div id="qoyqs8suu2u" class="com_white-left-infol"> <a href="http://systransis.cn/yun/u-1459.html"><img src="http://systransis.cn/yun/data/avatar/000/00/14/small_000001459.jpg" alt=""><span id="qoyqs8suu2u" class="layui-hide64">lowett</span></a> <time datetime="">2019-08-22 10:36</time> <span><i class="fa fa-commenting"></i>評論0</span> <span><i class="fa fa-star"></i>收藏0</span> </div> </div> </div> </li> <li> <div id="qoyqs8suu2u" class="atricle-list-right"> <h2 class="ellipsis2"><a class="hpf" href="http://systransis.cn/yun/99190.html"><b><em>webpack</em>4配置詳解之逐行分析</b></a></h2> <p class="ellipsis2 good">摘要:今天就嘗試著一起來聊聊吧,旨在幫大家加深理解新手更容易上路,都能從到搭建配置自定屬于自己的腳手架,或?qū)σ逊庋b好的腳手架有進一步的鞏固,接下來蘇南會詳細講解中的每一個配置字段的作用部分為新增。 showImg(https://segmentfault.com/img/bVbjmMV?w=1008&h=298); 前言   經(jīng)常會有群友問起webpack、react、redux、甚至cre...</p> <div id="qoyqs8suu2u" class="com_white-left-info"> <div id="qoyqs8suu2u" class="com_white-left-infol"> <a href="http://systransis.cn/yun/u-1481.html"><img src="http://systransis.cn/yun/data/avatar/000/00/14/small_000001481.jpg" alt=""><span id="qoyqs8suu2u" class="layui-hide64">dkzwm</span></a> <time datetime="">2019-08-23 13:04</time> <span><i class="fa fa-commenting"></i>評論0</span> <span><i class="fa fa-star"></i>收藏0</span> </div> </div> </div> </li> <li> <div id="qoyqs8suu2u" class="atricle-list-right"> <h2 class="ellipsis2"><a class="hpf" href="http://systransis.cn/yun/102835.html"><b><em>webpack</em>-<em>dev</em>-<em>middleware</em>@1.12.2 源碼解讀</b></a></h2> <p class="ellipsis2 good">摘要:如果此時我們不想把文件輸出到內(nèi)存里,可以通過修改的源代碼來實現(xiàn)。服務(wù)啟動成功。。。根據(jù)請求的,拼接出 ? webpack-dev-middleware 是express的一個中間件,它的主要作用是以監(jiān)聽模式啟動webpack,將webpack編譯后的文件輸出到內(nèi)存里,然后將內(nèi)存的文件輸出到epxress服務(wù)器上;下面通過一張圖片來看一下它的工作原理: showImg(https:...</p> <div id="qoyqs8suu2u" class="com_white-left-info"> <div id="qoyqs8suu2u" class="com_white-left-infol"> <a href="http://systransis.cn/yun/u-1200.html"><img src="http://systransis.cn/yun/data/avatar/000/00/12/small_000001200.jpg" alt=""><span id="qoyqs8suu2u" class="layui-hide64">yearsj</span></a> <time datetime="">2019-08-23 16:15</time> <span><i class="fa fa-commenting"></i>評論0</span> <span><i class="fa fa-star"></i>收藏0</span> </div> </div> </div> </li> <li> <div id="qoyqs8suu2u" class="atricle-list-right"> <h2 class="ellipsis2"><a class="hpf" href="http://systransis.cn/yun/96221.html"><b><em>webpack</em>使用記錄</b></a></h2> <p class="ellipsis2 good">容易混淆概念解析 讀這篇文章理清下面概念 webpack 中那些最易混淆的 5 個知識點 1.module,chunk 和 bundle 的區(qū)別是什么?2.filename 和 chunkFilename 的區(qū)別 版本區(qū)別 webpack 2x entry output loaders file-loader:把文件輸出到一個文件夾中,在代碼中通過相對 URL 去引用輸出的文件 url-lo...</p> <div id="qoyqs8suu2u" class="com_white-left-info"> <div id="qoyqs8suu2u" class="com_white-left-infol"> <a href="http://systransis.cn/yun/u-730.html"><img src="http://systransis.cn/yun/data/avatar/000/00/07/small_000000730.jpg" alt=""><span id="qoyqs8suu2u" class="layui-hide64">Sike</span></a> <time datetime="">2019-08-22 18:48</time> <span><i class="fa fa-commenting"></i>評論0</span> <span><i class="fa fa-star"></i>收藏0</span> </div> </div> </div> </li> </ul> </div> <div id="qoyqs8suu2u" class="topicone-box-wangeditor"> <h3 class="top-com-title mb-64"><span>發(fā)表評論</span></h3> <div id="qoyqs8suu2u" class="xcp-publish-main flex_box_zd"> <div id="qoyqs8suu2u" class="unlogin-pinglun-box"> <a href="javascript:login()" class="grad">登陸后可評論</a> </div> </div> </div> <div id="qoyqs8suu2u" class="site-box-content"> <div id="qoyqs8suu2u" class="site-content-title"> <h3 class="top-com-title mb-64"><span>0條評論</span></h3> </div> <div id="qoyqs8suu2u" class="pages"></ul></div> </div> </div> <div id="qoyqs8suu2u" class="layui-col-md4 layui-col-lg3 com_white-right site-wrap-right"> <div id="qoyqs8suu2u" class=""> <div id="qoyqs8suu2u" class="com_layuiright-box user-msgbox"> <a href="http://systransis.cn/yun/u-380.html"><img src="http://systransis.cn/yun/data/avatar/000/00/03/small_000000380.jpg" alt=""></a> <h3><a href="http://systransis.cn/yun/u-380.html" rel="nofollow">gitmilk</a></h3> <h6>男<span>|</span>高級講師</h6> <div id="qoyqs8suu2u" class="flex_box_zd user-msgbox-atten"> <a href="javascript:attentto_user(380)" id="attenttouser_380" class="grad follow-btn notfollow attention">我要關(guān)注</a> <a href="javascript:login()" title="發(fā)私信" >我要私信</a> </div> <div id="qoyqs8suu2u" class="user-msgbox-list flex_box_zd"> <h3 class="hpf">TA的文章</h3> <a href="http://systransis.cn/yun/ut-380.html" class="box_hxjz">閱讀更多</a> </div> <ul class="user-msgbox-ul"> <li><h3 class="ellipsis"><a href="http://systransis.cn/yun/121948.html">基于javaweb+jsp的醫(yī)院信息管理系統(tǒng)</a></h3> <p>閱讀 2031<span>·</span>2021-10-09 09:41</p></li> <li><h3 class="ellipsis"><a href="http://systransis.cn/yun/121406.html">大齡業(yè)余程序員要搞個django小程序--09--小程序登陸狀態(tài)維護之個人中心如何做數(shù)據(jù)加載</a></h3> <p>閱讀 1606<span>·</span>2021-09-28 09:36</p></li> <li><h3 class="ellipsis"><a href="http://systransis.cn/yun/121126.html">程序員的算法趣題Q39: 反復(fù)排序</a></h3> <p>閱讀 1108<span>·</span>2021-09-26 09:55</p></li> <li><h3 class="ellipsis"><a href="http://systransis.cn/yun/119841.html">DediPath:美國特價獨立服務(wù)器,洛杉磯獨服月付$39起,全場VPS一律4折優(yōu)惠</a></h3> <p>閱讀 1298<span>·</span>2021-09-10 11:17</p></li> <li><h3 class="ellipsis"><a href="http://systransis.cn/yun/118753.html">GigsGigsCloud:洛杉磯CN2+聯(lián)通9929線路VPS限時2折</a></h3> <p>閱讀 1153<span>·</span>2021-09-02 09:56</p></li> <li><h3 class="ellipsis"><a href="http://systransis.cn/yun/115209.html">CSS3魔法堂:說說Multi-column Layout</a></h3> <p>閱讀 2768<span>·</span>2019-08-30 12:58</p></li> <li><h3 class="ellipsis"><a href="http://systransis.cn/yun/112339.html">js實現(xiàn)鼠標拖拽多選功能</a></h3> <p>閱讀 2937<span>·</span>2019-08-29 13:03</p></li> <li><h3 class="ellipsis"><a href="http://systransis.cn/yun/109278.html">摸倚天魚文章推薦系列 - 19/03/31</a></h3> <p>閱讀 1862<span>·</span>2019-08-26 13:40</p></li> </ul> </div> <!-- 文章詳情右側(cè)廣告--> <div id="qoyqs8suu2u" class="com_layuiright-box"> <h6 class="top-com-title"><span>最新活動</span></h6> <div id="qoyqs8suu2u" class="com_adbox"> <div id="qoyqs8suu2u" class="layui-carousel" id="right-item"> <div carousel-item> <div> <a href="http://systransis.cn/site/active/kuaijiesale.html?ytag=seo" rel="nofollow"> <img src="http://systransis.cn/yun/data/attach/240625/2rTjEHmi.png" alt="云服務(wù)器"> </a> </div> <div> <a href="http://systransis.cn/site/product/gpu.html" rel="nofollow"> <img src="http://systransis.cn/yun/data/attach/240807/7NjZjdrd.png" alt="GPU云服務(wù)器"> </a> </div> </div> </div> </div> <!-- banner結(jié)束 --> <div id="qoyqs8suu2u" class="adhtml"> </div> <script> $(function(){ $.ajax({ type: "GET", url:"http://systransis.cn/yun/ad/getad/1.html", cache: false, success: function(text){ $(".adhtml").html(text); } }); }) </script> </div> </div> </div> </div> </div> </section> <!-- wap拉出按鈕 --> <div id="qoyqs8suu2u" class="site-tree-mobile layui-hide"> <i class="layui-icon layui-icon-spread-left"></i> </div> <!-- wap遮罩層 --> <div id="qoyqs8suu2u" class="site-mobile-shade"></div> <!--付費閱讀 --> <div class="qoyqs8suu2u" id="payread"> <div id="qoyqs8suu2u" class="layui-form-item">閱讀需要支付1元查看</div> <div id="qoyqs8suu2u" class="layui-form-item"><button class="btn-right">支付并查看</button></div> </div> <script> var prei=0; $(".site-seo-depict pre").each(function(){ var html=$(this).html().replace("<code>","").replace("</code>","").replace('<code class="javascript hljs" codemark="1">',''); $(this).attr('data-clipboard-text',html).attr("id","pre"+prei); $(this).html("").append("<code>"+html+"</code>"); prei++; }) $(".site-seo-depict img").each(function(){ if($(this).attr("src").indexOf('data:image/svg+xml')!= -1){ $(this).remove(); } }) $("LINK[href*='style-49037e4d27.css']").remove(); $("LINK[href*='markdown_views-d7a94ec6ab.css']").remove(); layui.use(['jquery', 'layer','code'], function(){ $("pre").attr("class","layui-code"); $("pre").attr("lay-title",""); $("pre").attr("lay-skin",""); layui.code(); $(".layui-code-h3 a").attr("class","copycode").html("復(fù)制代碼 ").attr("onclick","copycode(this)"); }); function copycode(target){ var id=$(target).parent().parent().attr("id"); var clipboard = new ClipboardJS("#"+id); clipboard.on('success', function(e) { e.clearSelection(); alert("復(fù)制成功") }); clipboard.on('error', function(e) { alert("復(fù)制失敗") }); } //$(".site-seo-depict").html($(".site-seo-depict").html().slice(0, -5)); </script> <link rel="stylesheet" type="text/css" href="http://systransis.cn/yun/static/js/neweditor/code/styles/tomorrow-night-eighties.css"> <script src="http://systransis.cn/yun/static/js/neweditor/code/highlight.pack.js" type="text/javascript"></script> <script src="http://systransis.cn/yun/static/js/clipboard.js"></script> <script>hljs.initHighlightingOnLoad();</script> <script> function setcode(){ var _html=''; document.querySelectorAll('pre code').forEach((block) => { var _tmptext=$.trim($(block).text()); if(_tmptext!=''){ _html=_html+_tmptext; console.log(_html); } }); } </script> <script> function payread(){ layer.open({ type: 1, title:"付費閱讀", shadeClose: true, content: $('#payread') }); } // 舉報 function jupao_tip(){ layer.open({ type: 1, title:false, shadeClose: true, content: $('#jubao') }); } $(".getcommentlist").click(function(){ var _id=$(this).attr("dataid"); var _tid=$(this).attr("datatid"); $("#articlecommentlist"+_id).toggleClass("hide"); var flag=$("#articlecommentlist"+_id).attr("dataflag"); if(flag==1){ flag=0; }else{ flag=1; //加載評論 loadarticlecommentlist(_id,_tid); } $("#articlecommentlist"+_id).attr("dataflag",flag); }) $(".add-comment-btn").click(function(){ var _id=$(this).attr("dataid"); $(".formcomment"+_id).toggleClass("hide"); }) $(".btn-sendartcomment").click(function(){ var _aid=$(this).attr("dataid"); var _tid=$(this).attr("datatid"); var _content=$.trim($(".commenttext"+_aid).val()); if(_content==''){ alert("評論內(nèi)容不能為空"); return false; } var touid=$("#btnsendcomment"+_aid).attr("touid"); if(touid==null){ touid=0; } addarticlecomment(_tid,_aid,_content,touid); }) $(".button_agree").click(function(){ var supportobj = $(this); var tid = $(this).attr("id"); $.ajax({ type: "GET", url:"http://systransis.cn/yun/index.php?topic/ajaxhassupport/" + tid, cache: false, success: function(hassupport){ if (hassupport != '1'){ $.ajax({ type: "GET", cache:false, url: "http://systransis.cn/yun/index.php?topic/ajaxaddsupport/" + tid, success: function(comments) { supportobj.find("span").html(comments+"人贊"); } }); }else{ alert("您已經(jīng)贊過"); } } }); }); function attenquestion(_tid,_rs){ $.ajax({ //提交數(shù)據(jù)的類型 POST GET type:"POST", //提交的網(wǎng)址 url:"http://systransis.cn/yun/favorite/topicadd.html", //提交的數(shù)據(jù) data:{tid:_tid,rs:_rs}, //返回數(shù)據(jù)的格式 datatype: "json",//"xml", "html", "script", "json", "jsonp", "text". //在請求之前調(diào)用的函數(shù) beforeSend:function(){}, //成功返回之后調(diào)用的函數(shù) success:function(data){ var data=eval("("+data+")"); console.log(data) if(data.code==2000){ layer.msg(data.msg,function(){ if(data.rs==1){ //取消收藏 $(".layui-layer-tips").attr("data-tips","收藏文章"); $(".layui-layer-tips").html('<i class="fa fa-heart-o"></i>'); } if(data.rs==0){ //收藏成功 $(".layui-layer-tips").attr("data-tips","已收藏文章"); $(".layui-layer-tips").html('<i class="fa fa-heart"></i>') } }) }else{ layer.msg(data.msg) } } , //調(diào)用執(zhí)行后調(diào)用的函數(shù) complete: function(XMLHttpRequest, textStatus){ postadopt=true; }, //調(diào)用出錯執(zhí)行的函數(shù) error: function(){ //請求出錯處理 postadopt=false; } }); } </script> <footer> <div id="qoyqs8suu2u" class="layui-container"> <div id="qoyqs8suu2u" class="flex_box_zd"> <div id="qoyqs8suu2u" class="left-footer"> <h6><a href="http://systransis.cn/"><img src="http://systransis.cn/yun/static/theme/ukd//images/logo.png" alt="UCloud (優(yōu)刻得科技股份有限公司)"></a></h6> <p>UCloud (優(yōu)刻得科技股份有限公司)是中立、安全的云計算服務(wù)平臺,堅持中立,不涉足客戶業(yè)務(wù)領(lǐng)域。公司自主研發(fā)IaaS、PaaS、大數(shù)據(jù)流通平臺、AI服務(wù)平臺等一系列云計算產(chǎn)品,并深入了解互聯(lián)網(wǎng)、傳統(tǒng)企業(yè)在不同場景下的業(yè)務(wù)需求,提供公有云、混合云、私有云、專有云在內(nèi)的綜合性行業(yè)解決方案。</p> </div> <div id="qoyqs8suu2u" class="right-footer layui-hidemd"> <ul class="flex_box_zd"> <li> <h6>UCloud與云服務(wù)</h6> <p><a href="http://systransis.cn/site/about/intro/">公司介紹</a></p> <p><a >加入我們</a></p> <p><a href="http://systransis.cn/site/ucan/onlineclass/">UCan線上公開課</a></p> <p><a href="http://systransis.cn/site/solutions.html" >行業(yè)解決方案</a></p> <p><a href="http://systransis.cn/site/pro-notice/">產(chǎn)品動態(tài)</a></p> </li> <li> <h6>友情鏈接</h6> <p><a >GPU算力平臺</a></p> <p><a >UCloud私有云</a></p> <p><a >SurferCloud</a></p> <p><a >工廠仿真軟件</a></p> <p><a >Pinex</a></p> <p><a >AI繪畫</a></p> </li> <li> <h6>社區(qū)欄目</h6> <p><a href="http://systransis.cn/yun/column/index.html">專欄文章</a></p> <p><a href="http://systransis.cn/yun/udata/">專題地圖</a></p> </li> <li> <h6>常見問題</h6> <p><a href="http://systransis.cn/site/ucsafe/notice.html" >安全中心</a></p> <p><a href="http://systransis.cn/site/about/news/recent/" >新聞動態(tài)</a></p> <p><a href="http://systransis.cn/site/about/news/report/">媒體動態(tài)</a></p> <p><a href="http://systransis.cn/site/cases.html">客戶案例</a></p> <p><a href="http://systransis.cn/site/notice/">公告</a></p> </li> <li> <span><img src="https://static.ucloud.cn/7a4b6983f4b94bcb97380adc5d073865.png" alt="優(yōu)刻得"></span> <p>掃掃了解更多</p></div> </div> <div id="qoyqs8suu2u" class="copyright">Copyright ? 2012-2023 UCloud 優(yōu)刻得科技股份有限公司<i>|</i><a rel="nofollow" >滬公網(wǎng)安備 31011002000058號</a><i>|</i><a rel="nofollow" ></a> 滬ICP備12020087號-3</a><i>|</i> <script type="text/javascript" src="https://gyfk12.kuaishang.cn/bs/ks.j?cI=197688&fI=125915" charset="utf-8"></script> <script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://#/hm.js?290c2650b305fc9fff0dbdcafe48b59d"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> <!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-DZSMXQ3P9N"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-DZSMXQ3P9N'); </script> <script> (function(){ var el = document.createElement("script"); el.src = "https://lf1-cdn-tos.bytegoofy.com/goofy/ttzz/push.js?99f50ea166557aed914eb4a66a7a70a4709cbb98a54ecb576877d99556fb4bfc3d72cd14f8a76432df3935ab77ec54f830517b3cb210f7fd334f50ccb772134a"; el.id = "ttzz"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(el, s); })(window) </script></div> </div> </footer> <footer> <div class="friendship-link"> <p>感谢您访问我们的网站,您可能还对以下资源感兴趣:</p> <a href="http://systransis.cn/" title="成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费">成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费</a> <div class="friend-links"> </div> </div> </footer> <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body><div id="ph7nb" class="pl_css_ganrao" style="display: none;"><thead id="ph7nb"><label id="ph7nb"></label></thead><legend id="ph7nb"><sup id="ph7nb"></sup></legend><nobr id="ph7nb"><b id="ph7nb"></b></nobr><optgroup id="ph7nb"><listing id="ph7nb"><dfn id="ph7nb"><mark id="ph7nb"></mark></dfn></listing></optgroup><nobr id="ph7nb"></nobr><rp id="ph7nb"><thead id="ph7nb"><thead id="ph7nb"><label id="ph7nb"></label></thead></thead></rp><dfn id="ph7nb"></dfn><thead id="ph7nb"><label id="ph7nb"><dfn id="ph7nb"><mark id="ph7nb"></mark></dfn></label></thead><address id="ph7nb"><strike id="ph7nb"><var id="ph7nb"><form id="ph7nb"></form></var></strike></address><dfn id="ph7nb"></dfn><form id="ph7nb"><i id="ph7nb"><listing id="ph7nb"><dfn id="ph7nb"></dfn></listing></i></form><meter id="ph7nb"><sup id="ph7nb"><label id="ph7nb"><th id="ph7nb"></th></label></sup></meter><strong id="ph7nb"><optgroup id="ph7nb"><ins id="ph7nb"><address id="ph7nb"></address></ins></optgroup></strong><style id="ph7nb"><th id="ph7nb"></th></style><legend id="ph7nb"><sup id="ph7nb"></sup></legend><sub id="ph7nb"><strike id="ph7nb"><var id="ph7nb"><form id="ph7nb"></form></var></strike></sub><sub id="ph7nb"><div id="ph7nb"></div></sub><sub id="ph7nb"><strike id="ph7nb"><var id="ph7nb"><small id="ph7nb"></small></var></strike></sub><label id="ph7nb"><strong id="ph7nb"></strong></label><ruby id="ph7nb"><thead id="ph7nb"><thead id="ph7nb"><sup id="ph7nb"></sup></thead></thead></ruby><p id="ph7nb"><nobr id="ph7nb"><font id="ph7nb"><meter id="ph7nb"></meter></font></nobr></p><label id="ph7nb"></label><output id="ph7nb"><address id="ph7nb"></address></output><video id="ph7nb"><address id="ph7nb"><strike id="ph7nb"><var id="ph7nb"></var></strike></address></video><mark id="ph7nb"><dl id="ph7nb"><i id="ph7nb"><dfn id="ph7nb"></dfn></i></dl></mark><em id="ph7nb"><big id="ph7nb"></big></em><mark id="ph7nb"></mark><thead id="ph7nb"><dfn id="ph7nb"><dfn id="ph7nb"><mark id="ph7nb"></mark></dfn></dfn></thead><strong id="ph7nb"></strong><i id="ph7nb"></i><big id="ph7nb"><ol id="ph7nb"><optgroup id="ph7nb"><video id="ph7nb"></video></optgroup></ol></big><span id="ph7nb"></span><legend id="ph7nb"><dfn id="ph7nb"></dfn></legend><address id="ph7nb"><p id="ph7nb"><var id="ph7nb"><small id="ph7nb"></small></var></p></address><listing id="ph7nb"><dfn id="ph7nb"><mark id="ph7nb"><thead id="ph7nb"></thead></mark></dfn></listing><ruby id="ph7nb"><thead id="ph7nb"><thead id="ph7nb"><label id="ph7nb"></label></thead></thead></ruby><font id="ph7nb"><progress id="ph7nb"><pre id="ph7nb"><style id="ph7nb"></style></pre></progress></font><style id="ph7nb"><nobr id="ph7nb"></nobr></style><address id="ph7nb"><p id="ph7nb"><nobr id="ph7nb"><small id="ph7nb"></small></nobr></p></address><style id="ph7nb"></style><listing id="ph7nb"><tt id="ph7nb"><big id="ph7nb"><dl id="ph7nb"></dl></big></tt></listing><sub id="ph7nb"></sub><i id="ph7nb"></i><legend id="ph7nb"><sup id="ph7nb"></sup></legend><pre id="ph7nb"></pre><label id="ph7nb"><strong id="ph7nb"></strong></label><meter id="ph7nb"></meter><track id="ph7nb"><tt id="ph7nb"></tt></track><dfn id="ph7nb"><mark id="ph7nb"><span id="ph7nb"><thead id="ph7nb"></thead></span></mark></dfn><font id="ph7nb"><progress id="ph7nb"></progress></font><dfn id="ph7nb"><menuitem id="ph7nb"></menuitem></dfn><big id="ph7nb"><ol id="ph7nb"><pre id="ph7nb"><track id="ph7nb"></track></pre></ol></big><dl id="ph7nb"><pre id="ph7nb"><video id="ph7nb"><sub id="ph7nb"></sub></video></pre></dl><strike id="ph7nb"></strike><acronym id="ph7nb"><strong id="ph7nb"><rp id="ph7nb"><thead id="ph7nb"></thead></rp></strong></acronym><form id="ph7nb"><thead id="ph7nb"></thead></form><strong id="ph7nb"><ruby id="ph7nb"></ruby></strong><dfn id="ph7nb"></dfn><sub id="ph7nb"><div id="ph7nb"></div></sub><rp id="ph7nb"></rp><font id="ph7nb"></font><em id="ph7nb"><big id="ph7nb"><ol id="ph7nb"><pre id="ph7nb"></pre></ol></big></em><form id="ph7nb"></form><var id="ph7nb"></var><pre id="ph7nb"></pre><video id="ph7nb"><em id="ph7nb"></em></video><style id="ph7nb"><th id="ph7nb"></th></style><form id="ph7nb"><thead id="ph7nb"><label id="ph7nb"><strong id="ph7nb"></strong></label></thead></form><ins id="ph7nb"></ins><mark id="ph7nb"><span id="ph7nb"><thead id="ph7nb"><dfn id="ph7nb"></dfn></thead></span></mark><sup id="ph7nb"><strong id="ph7nb"><ruby id="ph7nb"><font id="ph7nb"></font></ruby></strong></sup><listing id="ph7nb"><tt id="ph7nb"><menuitem id="ph7nb"><dl id="ph7nb"></dl></menuitem></tt></listing><track id="ph7nb"><em id="ph7nb"></em></track><output id="ph7nb"><sub id="ph7nb"><div id="ph7nb"><ol id="ph7nb"></ol></div></sub></output><style id="ph7nb"></style><pre id="ph7nb"><p id="ph7nb"></p></pre><font id="ph7nb"><legend id="ph7nb"><label id="ph7nb"><strong id="ph7nb"></strong></label></legend></font><p id="ph7nb"><nobr id="ph7nb"></nobr></p><div id="ph7nb"></div><meter id="ph7nb"><pre id="ph7nb"></pre></meter><rp id="ph7nb"><form id="ph7nb"><thead id="ph7nb"><dfn id="ph7nb"></dfn></thead></form></rp><div id="ph7nb"><var id="ph7nb"></var></div><legend id="ph7nb"></legend><var id="ph7nb"></var><label id="ph7nb"><rp id="ph7nb"><thead id="ph7nb"><legend id="ph7nb"></legend></thead></rp></label><acronym id="ph7nb"><style id="ph7nb"><th id="ph7nb"><small id="ph7nb"></small></th></style></acronym><label id="ph7nb"><ruby id="ph7nb"><thead id="ph7nb"><legend id="ph7nb"></legend></thead></ruby></label><small id="ph7nb"><ins id="ph7nb"></ins></small><th id="ph7nb"></th><span id="ph7nb"><legend id="ph7nb"></legend></span><var id="ph7nb"></var><dfn id="ph7nb"><dfn id="ph7nb"><menuitem id="ph7nb"><form id="ph7nb"></form></menuitem></dfn></dfn><track id="ph7nb"><em id="ph7nb"></em></track><strong id="ph7nb"><rp id="ph7nb"><font id="ph7nb"><progress id="ph7nb"></progress></font></rp></strong><ol id="ph7nb"><pre id="ph7nb"><video id="ph7nb"><em id="ph7nb"></em></video></pre></ol><th id="ph7nb"><b id="ph7nb"><meter id="ph7nb"><pre id="ph7nb"></pre></meter></b></th><legend id="ph7nb"></legend><var id="ph7nb"><form id="ph7nb"><ins id="ph7nb"><pre id="ph7nb"></pre></ins></form></var><th id="ph7nb"><b id="ph7nb"></b></th><label id="ph7nb"><u id="ph7nb"></u></label><form id="ph7nb"><meter id="ph7nb"></meter></form><thead id="ph7nb"></thead><nobr id="ph7nb"></nobr><label id="ph7nb"><strong id="ph7nb"></strong></label><sup id="ph7nb"><strong id="ph7nb"></strong></sup><optgroup id="ph7nb"><output id="ph7nb"></output></optgroup><font id="ph7nb"></font><big id="ph7nb"></big><thead id="ph7nb"><legend id="ph7nb"><label id="ph7nb"><strong id="ph7nb"></strong></label></legend></thead><ruby id="ph7nb"></ruby><output id="ph7nb"><sub id="ph7nb"><strike id="ph7nb"><ol id="ph7nb"></ol></strike></sub></output><p id="ph7nb"><nobr id="ph7nb"><b id="ph7nb"><ins id="ph7nb"></ins></b></nobr></p><dl id="ph7nb"><pre id="ph7nb"><video id="ph7nb"><sub id="ph7nb"></sub></video></pre></dl><acronym id="ph7nb"><label id="ph7nb"><rp id="ph7nb"><font id="ph7nb"></font></rp></label></acronym><sup id="ph7nb"></sup><optgroup id="ph7nb"><video id="ph7nb"><sub id="ph7nb"><div id="ph7nb"></div></sub></video></optgroup><thead id="ph7nb"></thead><div id="ph7nb"><strong id="ph7nb"></strong></div><ol id="ph7nb"><optgroup id="ph7nb"><track id="ph7nb"><em id="ph7nb"></em></track></optgroup></ol><em id="ph7nb"></em><address id="ph7nb"></address><track id="ph7nb"><tt id="ph7nb"></tt></track><label id="ph7nb"></label><optgroup id="ph7nb"><output id="ph7nb"></output></optgroup><i id="ph7nb"><listing id="ph7nb"></listing></i><thead id="ph7nb"></thead><legend id="ph7nb"></legend><dfn id="ph7nb"><mark id="ph7nb"><span id="ph7nb"><thead id="ph7nb"></thead></span></mark></dfn><dl id="ph7nb"></dl><ruby id="ph7nb"><thead id="ph7nb"></thead></ruby><listing id="ph7nb"><dfn id="ph7nb"><menuitem id="ph7nb"><form id="ph7nb"></form></menuitem></dfn></listing><style id="ph7nb"></style><acronym id="ph7nb"><label id="ph7nb"><th id="ph7nb"><b id="ph7nb"></b></th></label></acronym><output id="ph7nb"><address id="ph7nb"></address></output><big id="ph7nb"><ol id="ph7nb"><pre id="ph7nb"><track id="ph7nb"></track></pre></ol></big><div id="ph7nb"></div><u id="ph7nb"><mark id="ph7nb"></mark></u><big id="ph7nb"><ol id="ph7nb"><i id="ph7nb"><track id="ph7nb"></track></i></ol></big><rp id="ph7nb"><font id="ph7nb"><progress id="ph7nb"><acronym id="ph7nb"></acronym></progress></font></rp><optgroup id="ph7nb"><video id="ph7nb"></video></optgroup><legend id="ph7nb"><listing id="ph7nb"><dfn id="ph7nb"><mark id="ph7nb"></mark></dfn></listing></legend><video id="ph7nb"><em id="ph7nb"><div id="ph7nb"><ol id="ph7nb"></ol></div></em></video><ruby id="ph7nb"><thead id="ph7nb"></thead></ruby><sup id="ph7nb"><label id="ph7nb"><rp id="ph7nb"><thead id="ph7nb"></thead></rp></label></sup><form id="ph7nb"></form><optgroup id="ph7nb"><output id="ph7nb"><address id="ph7nb"><strike id="ph7nb"></strike></address></output></optgroup><sub id="ph7nb"><div id="ph7nb"><ol id="ph7nb"><pre id="ph7nb"></pre></ol></div></sub><thead id="ph7nb"><thead id="ph7nb"><label id="ph7nb"><strong id="ph7nb"></strong></label></thead></thead><legend id="ph7nb"><listing id="ph7nb"><tt id="ph7nb"><menuitem id="ph7nb"></menuitem></tt></listing></legend><font id="ph7nb"><progress id="ph7nb"><sup id="ph7nb"><label id="ph7nb"></label></sup></progress></font></div> <script src="http://systransis.cn/yun/static/theme/ukd/js/common.js"></script> <<script type="text/javascript"> $(".site-seo-depict *,.site-content-answer-body *,.site-body-depict *").css("max-width","100%"); </script> </html>