In this post I gonna compile a Solidity program with Solidity Compiler JS in browsers supported WebWorker.
Tools and plugins:
nx@12.7.1
worker-plugin@5.0.1
solc@0.8.7-fixed
webpack@4 (included in NX)
Compiling a smart contract with Solc is a heavy task for browsers, and for such heavy task we need to use WebWorker.
The tool for setting up the project is NX. it is great tool to create monos-repository.
Configuring WebWorker for NX
NX is using Webpack underhood, In this post we use worker-plugin to make WebWorker work with Webpack. In order to config worker-plugin
we need to extend the default configuration of Webpack inside NX.
-
Create webpack.json in root folder of
frontend
module.
const WorkerPlugin = require('worker-plugin'); const nrwlConfig = require('@nrwl/react/plugins/webpack.js'); module.exports = (config, context) => { nrwlConfig(config); return { ...config, node: { Buffer: true, module: 'empty', }, plugins: [new WorkerPlugin(), ...config.plugins], }; };
As you can see we have some polyfill configurations for NodeJS in Webpack
-
Add
webpack.json
to workspace.json file.
"webpackConfig": "apps/frontend/webpack.config.js"
Here is the detail of webpackConfig option.
Compile Solidity Smart Contract with WebWorker
Solc@0.8.7-fixed
doesn't have typescript declaration yet, we have to add a type declaration manually. Simply adddeclare module 'solc/wrapper';
to*.d.ts
file in your project.-
Creating a worker SolcJs.worker.ts file.
/* eslint-disable no-restricted-globals */ import * as wrapper from 'solc/wrapper'; const ctx: Worker = self as any; importScripts( 'https://solc-bin.ethereum.org/bin/soljson-v0.8.6+commit.11564f7e.js' ); ctx.addEventListener('message', ({ data }) => { const solc = wrapper((ctx as any).Module); const compileResult = solc.compile( createCompileInput(data.contractFileName, data.content) ); ctx.postMessage(compileResult); }); function createCompileInput( fileName = 'storage.sol', fileContent: string ): string { const CompileInput = { language: 'Solidity', sources: { [fileName]: { content: fileContent, }, }, settings: { outputSelection: { '*': { '*': ['*'], }, }, }, }; return JSON.stringify(CompileInput); }
-
Create a Promisify function to call
SolcJs.worker.ts
and wait until the compilation finished.
const compileWithWorker = async (data: any) => { return new Promise((resolve, reject) => { const worker = new Worker('../../SolcJs.worker.ts', { type: 'module', }); worker.postMessage(data); worker.onmessage = function (event: any) { resolve(event.data); }; worker.onerror = reject; }); };
Thank to the great answer from T.J. Crower
-
Now we are ready to use WebWorker to compile a Simple Solidity Smart Contract.
const handleCompile = async () => { setCompiling(true); const result = await compileWithWorker({ content: SimpleStorageContact, }); setCompileResult(result as string); setCompiling(false); };
SourceCode in Github - nx-webworker-sample
Top comments (0)