Web Worker 前端性能提升

在Web开发中,有时我们的应用需要处理复杂的计算或大量数据的操作,由于JavaScript语言采用的是单线程,如果有多个同步计算任务执行,则在这段同步计算逻辑执行完之前,它下方的代码不会执行,从而造成了阻塞,用户的交互也可能无响应。

如果把大量耗时的计算放到 Web Worker 执行,在这段逻辑计算运行期间不影响执行下面的任务,用户的操作也可以响应,就不会出现页面卡顿的现象了。

Web Worker 的基本应用

javascript 复制代码
// 创建一个 Worker 实例 
const myWorker = new Worker("worker.js");

// 向 Worker 发送数据 
myWorker.postMessage('Message posted to worker'); 

// 监听 Worker 返回的数据
myWorker.onmessage = function(event) { 
    console.log('Received message from worker: ' + event.data); 
};

在 worker 中接收到消息后,我们可以写这样一个事件处理函数代码作为响应(worker.js

worker.js 复制代码
onmessage = (e) => {
  console.log("Message received from main script");
  const workerResult = `Result: ${e.data}`;
  console.log("Posting message back to main script");
  postMessage(workerResult);
};

Web Worker 编译

这里以 webpack 为例。

方式一:web worker 独立编译

webpack.config.js 配置目标(target)指定环境为 webworker,编译成一个 web worker。

webpack.config.js 复制代码
module.exports = {
  // ...
  target: 'webworker',
};

方式二:原生 Worker 支持

当把资源的 new URLnew Worker 结合起来时,webpack 会自动为 web worker 创建一个新的入口点(entrypoint)。

javascript 复制代码
new Worker(new URL("./worker.js", import.meta.url))

代码高亮实例

下面是一个利用 remark-shaku-code-annotate 实现代码高亮的示例。

创建代码高亮 web worker

安装包

css 复制代码
npm i @stefanprobst/remark-shiki remark remark-html remark-shaku-code-annotate shiki

创建 worker.js

worker.js 复制代码
import { remark } from 'remark';
import { remarkShakuCodeAnnotate } from 'remark-shaku-code-annotate';

const processor = remark().use(remarkShakuCodeAnnotate, {
    theme: 'github-light',
    langs: ['javascript', 'css', 'jsx', 'html', 'typescript', 'tsx'],
    paths: {
        themes: './static/shiki/themes',
        wasm: './static/shiki/dist',
        languages: './static/shiki/languages',
    },
});

onmessage = (e) => {
    // 接收需要高亮的代码文本
    const code = e.data;
    
    // 将代码文本高亮
    processor.process(code).then((data) => {
        // 将高亮后的代码文本(html)发送给主程序
        postMessage(data.toString());
    });
};

使用 webpack 编译

webpack.config.js 复制代码
module.exports = function (env, args = {}) {
    const config = {
        // ...
        // 编译成 web worker
        target: 'webworker',
        plugins: [
            // ...
            // 将需要用到的 shiki 下的资源文件拷贝至编译输出目录
            new CopyWebpackPlugin({
                patterns: [
                    {
                        from: 'shiki/dist/*',
                        context: path.resolve(__dirname, 'node_modules'),
                        to: 'static/',
                    },
                    {
                        from: 'shiki/languages/*',
                        context: path.resolve(__dirname, 'node_modules'),
                        to: 'static/',
                    },
                    {
                        from: 'shiki/themes/*',
                        context: path.resolve(__dirname, 'node_modules'),
                        to: 'static/',
                    },
                ],
            }),
        ],
    };

    return config;
};

创建 worker 实例

在主程序中将编译的 web worker 拷贝至根目录的 remark-shaku-web-worker 下。

配置 webpack.config.js

webpack.config.js 复制代码
module.exports = function (env, args = {}) {
    const config = {
        // ...
        plugins: [
            // ...
            // 将需要用到的 shiki 下的资源文件拷贝至编译输出目录
            new CopyWebpackPlugin({
                patterns: [
                    {
                        from: '**/*',
                        context: path.resolve(__dirname, 'packages/remark-shaku-web-worker/dist'),
                        to: 'remark-shaku-web-worker/',
                    },
                ],
            }),
        ],
    };

    return config;
};

在主程序中创建 worker 实例,将代码文本转换成高亮 html

javascript 复制代码
const myWorker = new Worker('/remark-shaku-web-worker/worker.js');
myWorker.onmessage = (e) => {
    // 高亮后的代码文本(html)
    const textContent = e.data;
};
myWorker.postMessage('需高亮的代码文本');
相关推荐
Rhys..1 小时前
ES6是什么
前端·javascript·es6
Jammingpro2 小时前
【Vue专题】前端JS基础Part1(含模版字符串、解构赋值、变量常量与对象)
前端·javascript·vue.js
jiangzhihao05156 小时前
前端自动翻译插件webpack-auto-i18n-plugin的使用
前端·webpack·node.js
软件技术NINI8 小时前
html css网页制作成品——HTML+CSS盐津铺子网页设计(5页)附源码
前端·css·html
mapbar_front9 小时前
面试问题—我的问题问完了,你还有什么想问我的吗?
前端·面试
quweiie9 小时前
thinkphp8+layui多图上传,带删除\排序功能
前端·javascript·layui
李鸿耀9 小时前
React 项目 SVG 图标太难管?用这套自动化方案一键搞定!
前端
闲蛋小超人笑嘻嘻9 小时前
树形结构渲染 + 选择(Vue3 + ElementPlus)
前端·javascript·vue.js
叶梅树10 小时前
从零构建A股量化交易工具:基于Qlib的全栈系统指南
前端·后端·算法
巴博尔10 小时前
uniapp的IOS中首次进入,无网络问题
前端·javascript·ios·uni-app