Skip to content

Commit 86cd7c0

Browse files
authored
Merge branch 'master' into patch-1
2 parents 4aa0559 + 68ea667 commit 86cd7c0

File tree

8 files changed

+130
-23
lines changed

8 files changed

+130
-23
lines changed

.github/workflows/main.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: CI
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
build:
7+
runs-on: ubuntu-latest
8+
9+
steps:
10+
- uses: actions/checkout@v1
11+
- uses: actions/setup-node@v1
12+
with:
13+
node-version: 12
14+
- name: npm install, build, and test
15+
run: |
16+
npm install
17+
npm run prepare --if-present
18+
npm test
19+
env:
20+
CI: true

.gitignore

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
node_modules
2-
.DS_Store
3-
.cache
4-
.mocha-puppeteer
5-
*.log
6-
build
7-
dist
82
package-lock.json
93
yarn.lock
4+
dist
5+
coverage
6+
.DS_Store
7+
*.log

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,40 @@ If you're using [Babel](https://babeljs.io/) in your build, make sure you disabl
8585
}
8686
```
8787

88+
### Testing
89+
90+
To test a module that is normally imported via `workerize-loader` when not using Webpack, import the module directly in your test:
91+
92+
```diff
93+
-const worker = require('workerize-loader!./worker.js');
94+
+const worker = () => require('./worker.js');
95+
96+
const instance = worker();
97+
```
98+
99+
To test modules that rely on workerized imports when not using Webpack, you'll need to dig into your test runner a bit. For Jest, it's possible to define a custom `transform` that emulates workerize-loader on the main thread:
100+
101+
```js
102+
// in your Jest configuration
103+
{
104+
"transform": {
105+
"workerize-loader(\\?.*)?!(.*)": "<rootDir>/workerize-jest.js"
106+
}
107+
}
108+
```
109+
110+
... then add the `workerize-jest.js` shim to your project:
111+
112+
```js
113+
module.exports = {
114+
process(src, filename, config, options) {
115+
return 'module.exports = () => require(' + JSON.stringify(filename.replace(/.+!/,'')) + ')';
116+
},
117+
};
118+
```
119+
120+
Now your tests and any modules they import can use `workerize-loader!` prefixes.
121+
88122
### Credit
89123

90124
The inner workings here are heavily inspired by [worker-loader](https://github.com/webpack-contrib/worker-loader). It's worth a read!

package.json

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
{
22
"name": "workerize-loader",
3-
"version": "1.0.4",
3+
"version": "1.2.1",
44
"description": "Automatically move a module into a Web Worker (Webpack loader)",
55
"main": "dist/index.js",
66
"repository": "developit/workerize-loader",
77
"scripts": {
8-
"build": "microbundle --target node --format cjs --no-compress src/*.js",
8+
"build": "microbundle --format cjs --no-compress --inline none src/*.js",
99
"prepublishOnly": "npm run build",
1010
"dev": "karmatic watch --no-headless",
11-
"test": "npm run build && karmatic",
11+
"test": "npm run build && karmatic && NODE_ENV=production karmatic -p",
1212
"release": "npm t && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"
1313
},
14+
"browserslist": [
15+
"IE 10",
16+
"node 8"
17+
],
1418
"eslintConfig": {
1519
"extends": "eslint-config-developit",
1620
"rules": {
@@ -33,14 +37,14 @@
3337
"author": "Jason Miller <[email protected]> (http://jasonformat.com)",
3438
"license": "MIT",
3539
"devDependencies": {
36-
"eslint": "^5.0.0",
37-
"eslint-config-developit": "^1.1.1",
38-
"karmatic": "^1.2.0",
39-
"microbundle": "^0.6.0",
40-
"webpack": "^4.17.1"
40+
"eslint": "^7.2.0",
41+
"eslint-config-developit": "^1.2.0",
42+
"karmatic": "^1.4.0",
43+
"microbundle": "^0.12.1",
44+
"webpack": "^4.43.0"
4145
},
4246
"dependencies": {
43-
"loader-utils": "^1.1.0"
47+
"loader-utils": "^2.0.0"
4448
},
4549
"peerDependencies": {
4650
"webpack": "*"

src/index.js

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,25 @@ loader.pitch = function(request) {
6464
(new NodeTargetPlugin()).apply(worker.compiler);
6565
}
6666

67+
// webpack >= v4 supports webassembly
68+
let wasmPluginPath = null;
69+
try {
70+
wasmPluginPath = require.resolve(
71+
'webpack/lib/web/FetchCompileWasmTemplatePlugin'
72+
);
73+
}
74+
catch (_err) {
75+
// webpack <= v3, skipping
76+
}
77+
78+
if (wasmPluginPath) {
79+
// eslint-disable-next-line global-require
80+
const FetchCompileWasmTemplatePlugin = require(wasmPluginPath);
81+
new FetchCompileWasmTemplatePlugin({
82+
mangleImports: this._compiler.options.optimization.mangleWasmImports
83+
}).apply(worker.compiler);
84+
}
85+
6786
(new SingleEntryPlugin(this.context, `!!${path.resolve(__dirname, 'rpc-worker-loader.js')}!${request}`, 'main')).apply(worker.compiler);
6887

6988
const subCache = `subcache ${__dirname} ${request}`;
@@ -83,7 +102,8 @@ loader.pitch = function(request) {
83102
// only process entry exports
84103
if (current.resource!==entry) return;
85104

86-
let exports = compilation.__workerizeExports || (compilation.__workerizeExports = {});
105+
let key = current.nameForCondition();
106+
let exports = CACHE[key] || (CACHE[key] = {});
87107

88108
if (decl.id) {
89109
exports[decl.id.name] = true;
@@ -106,8 +126,9 @@ loader.pitch = function(request) {
106126
if (entries[0]) {
107127
worker.file = entries[0].files[0];
108128

129+
let key = entries[0].entryModule.nameForCondition();
109130
let contents = compilation.assets[worker.file].source();
110-
let exports = Object.keys(CACHE[worker.file] = compilation.__workerizeExports || CACHE[worker.file] || {});
131+
let exports = Object.keys(CACHE[key] || {});
111132

112133
// console.log('Workerized exports: ', exports.join(', '));
113134

@@ -125,11 +146,16 @@ loader.pitch = function(request) {
125146
delete this._compilation.assets[worker.file];
126147
}
127148

149+
let workerUrl = worker.url;
150+
if (options.import) {
151+
workerUrl = `"data:,importScripts('"+location.origin+${workerUrl}+"')"`;
152+
}
153+
128154
return cb(null, `
129155
var addMethods = require(${loaderUtils.stringifyRequest(this, path.resolve(__dirname, 'rpc-wrapper.js'))})
130156
var methods = ${JSON.stringify(exports)}
131157
module.exports = function() {
132-
var w = new Worker(${worker.url}, { name: ${JSON.stringify(filename)} })
158+
var w = new Worker(${workerUrl}, { name: ${JSON.stringify(filename)} })
133159
addMethods(w, methods)
134160
${ options.ready ? 'w.ready = new Promise(function(r) { w.addEventListener("ready", function(){ r(w) }) })' : '' }
135161
return w

src/rpc-worker-loader.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ function workerSetup() {
1111
p = Promise.reject('No such method');
1212
}
1313
p.then(result => {
14-
postMessage({ type: 'RPC', id, result });
15-
})
14+
postMessage({ type: 'RPC', id, result });
15+
})
1616
.catch(e => {
17-
let error = { message: e};
17+
let error = { message: e };
1818
if (e.stack) {
1919
error.message = e.message;
2020
error.stack = e.stack;
@@ -29,6 +29,7 @@ function workerSetup() {
2929

3030
const workerScript = '\n' + Function.prototype.toString.call(workerSetup).replace(/(^.*\{|\}.*$|\n\s*)/g, '');
3131

32-
export default function rpcWorkerLoader(content) {
33-
return content + workerScript;
32+
export default function rpcWorkerLoader(content, sourceMap) {
33+
const callback = this.async();
34+
callback(null, content + workerScript, sourceMap);
3435
}

test/src/index.test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import './other';
22
import Worker from 'workerize-loader?ready&name=test!./worker';
33
import InlineWorker from 'workerize-loader?ready&inline&name=test!./worker';
4+
import ImportWorker from 'workerize-loader?import!./worker';
45

56
describe('worker', () => {
67
let worker;
@@ -95,3 +96,21 @@ describe('async/await demo', () => {
9596
expect(elapsed).toBeLessThan(20);
9697
});
9798
});
99+
100+
describe('?import option', () => {
101+
let worker;
102+
103+
it('should be an instance of Worker', () => {
104+
worker = new ImportWorker();
105+
expect(worker).toEqual(jasmine.any(window.Worker));
106+
});
107+
108+
it('worker.foo()', async () => {
109+
expect(await worker.foo()).toBe(1);
110+
});
111+
112+
it('worker.bar()', async () => {
113+
let out = await worker.bar('a', 'b');
114+
expect(out).toEqual('a [bar:3] b');
115+
});
116+
});

webpack.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = function () {
2+
return {
3+
mode: process.env.NODE_ENV || 'development'
4+
};
5+
}

0 commit comments

Comments
 (0)