摘要:然而在當(dāng)前以為主要編譯工具的實(shí)際工程應(yīng)用中依然存在問(wèn)題。涉及到的技術(shù)主要為模塊機(jī)制插件編寫(xiě)與插件編寫(xiě)。使用可以參考或,歡迎。上一篇應(yīng)用到前端工程上模塊的編寫(xiě)
在上一篇文章WebAssembly應(yīng)用到前端工程(上)—— webassembly模塊的編寫(xiě)中,完成了@ne_fe/gis模塊的編寫(xiě)與發(fā)布。然而webassembly在當(dāng)前以webpack4為主要編譯工具的實(shí)際工程應(yīng)用中依然存在問(wèn)題。
盡管webpack4新增了對(duì)wasm文件的編譯支持,在wasm模塊編寫(xiě)完成之后將其與webpack結(jié)合的過(guò)程中發(fā)現(xiàn),wasm模塊無(wú)法被正確加載。在對(duì)@ne_fe/gis編譯輸出文件的檢查之后,有了新的解決方案 wasm-module-webpack-plugin。
出現(xiàn)的問(wèn)題直接在前端工程中引入@ne_fe/gis并使用的話,控制臺(tái)會(huì)輸出錯(cuò)誤信息
index.js?558c:1 GET http://localhost:8080/gps.wasm 404 (Not Found)
Uncaught (in promise) TypeError: Incorrect response MIME type. Expected "application/wasm".
查看所引用的@ne_fe/gis/dist/index.js后發(fā)現(xiàn)這樣一句話
var Pn="undefined"!=typeof location?location.pathname.split("/"):[];Pn.pop(),(Cn?WebAssembly.instantiateStreaming(fetch(Pn.join("/")+"/gps.wasm"),o):fetch(Pn.join("/")+"/gps.wasm").then(e=>e.arrayBuffer()).then(e=>WebAssembly.instantiate(e,o)))
出錯(cuò)原因時(shí)由于fetch直接從根路徑下直接獲取wasm文件,但文件并沒(méi)有生成或移動(dòng),webpack并不能處理fetch所加載的文件,最終導(dǎo)致wasm加載失敗。
babelwebpack不能處理js的fetch語(yǔ)句,導(dǎo)致了上面問(wèn)題的出現(xiàn),那么只有一種方法能夠處理fetch語(yǔ)句,那就是babel。
下面來(lái)編寫(xiě)一個(gè)babel插件處理fetch加載wasm的情況
// babel-plugin.js module.exports = function() { return { visitor: { CallExpression(path, state) { if(path.node.callee.name === "fetch"){ const argument = JSON.parse(JSON.stringify(path.node.arguments[0])); for (const i in argument.right) { if (i === "value" && argument.right[i].endsWith(".wasm")) { console.log("argument.right[ i ]", argument.right[ i ], "state.file.opts.filename", state.file.opts.filename); } } } }, } } };
在webpack中使用
// webpack.config.js const path = require("path"); const BabelPlugin = require("./babel-plugin"); module.exports = { module: { rules: [ ... { test: /.js$/, loader: "babel-loader", include: [ path.join(process.cwd(), "./node_modules/@ne_fe/gis") ], options: { plugins: [ BabelPlugin ], }, }, ... ], }, plugins: [ ... ], };
啟動(dòng)webpack進(jìn)行編譯,控制臺(tái)輸出
argument.right[ i ] /gps.wasm state.file.opts.filename C:dir est ode_modules@ne_fegisdistindex.js
最終獲得了fetch所加載的wasm文件名與fetch語(yǔ)句所在文件。
webpack在上一步中獲取到了fetch語(yǔ)句加載的wasm文件名與fetch語(yǔ)句所在文件。
為了將wasm文件輸出到webpack編譯結(jié)果中,需要添加webpack插件。經(jīng)修改之后,整個(gè)結(jié)合wasm與webpack的插件如下
// event-listener.js const EventEmitter = require("events").EventEmitter; class Events extends EventEmitter { constructor(prop) { super(prop); this.data = {}; } } const events = new Events(); events.on("wasm", data => { if (!events.data[data.wasmRefFileName]) { events.data[data.wasmRefFileName] = {}; events.data[data.wasmRefFileName][data.wasmRefPath] = data.wasmDir; } else { if (!events.data[data.wasmRefFileName][data.wasmRefPath]) { events.data[data.wasmRefFileName][data.wasmRefPath] = data.wasmDir; } } }); module.exports = events;
// babel-plugin.js const eventEmitter = require("./event-listener"); const pathInternal = require("path"); module.exports = function() { return { visitor: { CallExpression(path, state) { if(path.node.callee.name === "fetch"){ const argument = JSON.parse(JSON.stringify(path.node.arguments[0])); for (const i in argument.right) { if (i === "value" && argument.right[i].endsWith(".wasm")) { eventEmitter.emit("wasm", { wasmRefPath: argument.right[i], wasmRefFileName: state.file.opts.filename, wasmDir: pathInternal.parse(state.file.opts.filename).dir, }); } } } }, } } };
// webpack-plugin const eventEmitter = require("./event-listener"); const path = require("path"); class WasmPlugin { apply(compiler) { compiler.plugin("emit", function(compilation, callback) { for (const i in eventEmitter.data) { for (const j in eventEmitter.data[i]) { const filePath = path.join(eventEmitter.data[ i ][ j ], "." + j); const content = compiler.inputFileSystem._readFileSync(filePath); const stat = compiler.inputFileSystem._statSync(filePath); const wasmRefPath = j; const wasmName = wasmRefPath.substring(1, wasmRefPath.length); compilation.assets[wasmName] = { size() { return stat.size; }, source() { return content; }, }; } } callback(); }); } } module.exports = WasmPlugin;
event-listener的作用是為了保存babel-plugin中獲取到的wasm相關(guān)信息然后在webpack插件執(zhí)行的時(shí)候使用,webpack-plugin將獲取到的wasm文件輸出到正確路徑。
涉及到的技術(shù)主要為commonjs模塊機(jī)制、babel插件編寫(xiě)與webpack插件編寫(xiě)。
使用可以參考wasm-module-webpack-plugin或@ne_fe/gis,歡迎start。
尾語(yǔ)盡管webassembly的出現(xiàn)對(duì)前端開(kāi)發(fā)高性能瀏覽器應(yīng)用有了重大的作用,webpack4也新增了對(duì)webassembly的支持,但是目前以webpack編譯為主的前端工程對(duì)webassembly的支持依然不友好,開(kāi)發(fā)難度不小,希望以后有更好的解決方案。
?
?
上一篇:WebAssembly應(yīng)用到前端工程(上)—— webassembly模塊的編寫(xiě)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/105127.html
摘要:本文以這個(gè)模塊的開(kāi)發(fā)過(guò)程梳理如何應(yīng)用到前端工程中。注使用完成開(kāi)發(fā)至少需要基礎(chǔ)的編碼能力。具體其他信息可以參考上該模塊的。配置主要針對(duì)源碼文件,需要添加正確的進(jìn)行處理。下一篇應(yīng)用到前端工程下和 前言 WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine...
摘要:年前端有哪些領(lǐng)域,技術(shù)值得關(guān)注,哪些技術(shù)會(huì)興起,哪些技術(shù)會(huì)沒(méi)落。自從谷歌提出后,就持續(xù)的獲得了業(yè)界的關(guān)注,熱度可見(jiàn)一斑。就在今年,谷歌也宣布將獲得與安卓原生應(yīng)用同等的待遇與權(quán)限。但是無(wú)論都值得關(guān)注。 1.前言 2017悄然過(guò)去,2018已經(jīng)來(lái)到。人在進(jìn)步,技術(shù)在發(fā)展。2018年前端有哪些領(lǐng)域,技術(shù)值得關(guān)注,哪些技術(shù)會(huì)興起,哪些技術(shù)會(huì)沒(méi)落。下面就我個(gè)人的判斷進(jìn)行一個(gè)預(yù)測(cè)判斷,希望能對(duì)大家...
摘要:年前端有哪些領(lǐng)域,技術(shù)值得關(guān)注,哪些技術(shù)會(huì)興起,哪些技術(shù)會(huì)沒(méi)落。自從谷歌提出后,就持續(xù)的獲得了業(yè)界的關(guān)注,熱度可見(jiàn)一斑。就在今年,谷歌也宣布將獲得與安卓原生應(yīng)用同等的待遇與權(quán)限。但是無(wú)論都值得關(guān)注。 1.前言 2017悄然過(guò)去,2018已經(jīng)來(lái)到。人在進(jìn)步,技術(shù)在發(fā)展。2018年前端有哪些領(lǐng)域,技術(shù)值得關(guān)注,哪些技術(shù)會(huì)興起,哪些技術(shù)會(huì)沒(méi)落。下面就我個(gè)人的判斷進(jìn)行一個(gè)預(yù)測(cè)判斷,希望能對(duì)大家...
摘要:前端每周清單專(zhuān)注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開(kāi)發(fā)者了解一周前端熱點(diǎn)分為新聞熱點(diǎn)開(kāi)發(fā)教程工程實(shí)踐深度閱讀開(kāi)源項(xiàng)目巔峰人生等欄目。利用降低三倍加載速度自推出之后,很多開(kāi)發(fā)者都開(kāi)始嘗試在小型項(xiàng)目中實(shí)踐,不過(guò)尚缺大型真實(shí)案例比較。 前端每周清單專(zhuān)注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開(kāi)發(fā)者了解一周前端熱點(diǎn);分為新聞熱點(diǎn)、開(kāi)發(fā)教程、工程實(shí)踐、深度閱讀、開(kāi)源項(xiàng)目、巔峰人生等欄目...
摘要:前端每周清單專(zhuān)注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開(kāi)發(fā)者了解一周前端熱點(diǎn)分為新聞熱點(diǎn)開(kāi)發(fā)教程工程實(shí)踐深度閱讀開(kāi)源項(xiàng)目巔峰人生等欄目。背后的故事本文是對(duì)于年之間世界發(fā)生的大事件的詳細(xì)介紹,闡述了從提出到角力到流產(chǎn)的前世今生。 前端每周清單專(zhuān)注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開(kāi)發(fā)者了解一周前端熱點(diǎn);分為新聞熱點(diǎn)、開(kāi)發(fā)教程、工程實(shí)踐、深度閱讀、開(kāi)源項(xiàng)目、巔峰人生等欄目。歡迎...
閱讀 859·2021-11-25 09:44
閱讀 1063·2021-11-19 09:40
閱讀 7062·2021-09-07 10:23
閱讀 1975·2019-08-28 17:51
閱讀 1106·2019-08-26 10:59
閱讀 1928·2019-08-26 10:25
閱讀 3131·2019-08-23 18:22
閱讀 865·2019-08-23 16:58