# 前端云析布局集成 WebAssembly
# 引入 WASM
首先需要生成相应的 WASM,这块是直接让 C++的同学帮忙生成提供给前端。其中包括layouter.js
和layouter.wasm
两个文件。
为了 WASM 布局算法不影响浏览器渲染,这块使用了 HTML5 的标准Web Worker (opens new window),Web Worker 为 Web 内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。
可以通postMessage() (opens new window)方法和onmessage (opens new window)事件处理函数触发 worker。
为了更好的使用 Web Worker,需要在 webpack 引入一个插件,首先来安装:
npm install -D worker-plugin
然后在项目的vue.config.js
引入并使用,如下:
const WorkerPlugin = require("worker-plugin");
// Adds native Web Worker bundling support to Webpack.
module.exports = {
configureWebpack: {
plugins: [
// other plugins
new WorkerPlugin({
// use "self" as the global object when receiving hot updates.
globalObject: "self", // <-- this is the default value
}),
],
},
};
2
3
4
5
6
7
8
9
10
11
12
13
# 踩坑
在开发环境下,由于我们是直接引入layouter.js
的,所以相对应的,layouter.wasm
的路径是相对路径,但是目前来说,webpack
并没有很好的处理wasm
的loader
,所以webpack
并不会去主动处理wasm
文件,在这种情况下直接调用布局算法会发现路径不对。
解决办法是,在layouter.js
通过判断环境来处理:
var wasmBinaryFile = "layouter.wasm";
if (!isDataURI(wasmBinaryFile)) {
var isPro = process.env.NODE_ENV === "production";
wasmBinaryFile = isPro
? locateFile(wasmBinaryFile)
: "http://localhost:8082/static/layouter.wasm";
}
// 开发环境的路径因人而异,取决于wasm存放位置
2
3
4
5
6
7
8
第二个坑是打包时候的路径处理,同样的,因为webpack
不认识wasm
文件,我们需要将wasm
复制到 js 文件夹下,因为layouter.js
会被打包至 js 文件夹下。此时需要用到copy-webpack-plugin
,在生产环境下配置该插件:
new CopyPlugin([
{ from: 'static/layouter.wasm', to: 'js/' },
]),
2
3
第三个坑是当打包好发布到生产环境后,依旧报错。通过一番定位,发现是由于去除了 console.*函数,导致在Web Worker
中运行的layouter.js
中打印日志变成了调用undefined
。
去除 console.*函数是项目中在生产环境引入了terser-webpack-plugin
,该插件是用来压缩 js 代码,是官方推荐的插件。我们来修改下配置:
const TerserPlugin = require("terser-webpack-plugin"); // 压缩js代码,同时支持多进程压缩
module.exports.configureWebpack.optimization = {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
output: {
comments: false, // remove comments
},
compress: {
drop_console: false, // 由于wasm有打印日志,暂不去除console
drop_debugger: true,
pure_funcs: ["console.log"],
},
},
extractComments: false,
}),
],
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
主要就是把drop_console: true
改成drop_console: false
。
第四个坑是nginx
的配置。nginx
目前默认生成的mine.types
并不包含wasm
的格式,所以需要手动来添加。
我们期望nginx
遇到wasm
文件时,将它的Content-Type
设置为Content-Type: application/wasm
。找到 nginx 的mine.types
文件,在合适的位置添加:
application/wasm wasm;
然后重启nginx
。